mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 15:08:51 +00:00
New verbose option in util get_pset(s) which lets you get ID and class for complex processing.
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
|
||||||
|
|
||||||
def get_pset(element, name, prop=None, should_inherit=True):
|
def get_pset(element, name, prop=None, should_inherit=True, verbose=False):
|
||||||
"""Retrieve a single property set or single property
|
"""Retrieve a single property set or single property
|
||||||
|
|
||||||
This is more efficient than ifcopenshell.util.element.get_psets if you know
|
This is more efficient than ifcopenshell.util.element.get_psets if you know
|
||||||
@@ -64,7 +64,7 @@ def get_pset(element, name, prop=None, should_inherit=True):
|
|||||||
if should_inherit:
|
if should_inherit:
|
||||||
element_type = ifcopenshell.util.element.get_type(element)
|
element_type = ifcopenshell.util.element.get_type(element)
|
||||||
if element_type:
|
if element_type:
|
||||||
type_pset = get_pset(element_type, name, prop, should_inherit=False)
|
type_pset = get_pset(element_type, name, prop, should_inherit=False, verbose=verbose)
|
||||||
for relationship in element.IsDefinedBy:
|
for relationship in element.IsDefinedBy:
|
||||||
if relationship.is_a("IfcRelDefinesByProperties"):
|
if relationship.is_a("IfcRelDefinesByProperties"):
|
||||||
definition = relationship.RelatingPropertyDefinition
|
definition = relationship.RelatingPropertyDefinition
|
||||||
@@ -77,19 +77,19 @@ def get_pset(element, name, prop=None, should_inherit=True):
|
|||||||
|
|
||||||
if not prop:
|
if not prop:
|
||||||
if type_pset:
|
if type_pset:
|
||||||
occurrence_pset = get_property_definition(pset)
|
occurrence_pset = get_property_definition(pset, verbose=verbose)
|
||||||
if occurrence_pset:
|
if occurrence_pset:
|
||||||
type_pset.update(occurrence_pset)
|
type_pset.update(occurrence_pset)
|
||||||
return type_pset
|
return type_pset
|
||||||
return get_property_definition(pset)
|
return get_property_definition(pset, verbose=verbose)
|
||||||
|
|
||||||
value = get_property_definition(pset, prop)
|
value = get_property_definition(pset, prop=prop, verbose=verbose)
|
||||||
if value is None and type_pset is not None:
|
if value is None and type_pset is not None:
|
||||||
return type_pset
|
return type_pset
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def get_psets(element, psets_only=False, qtos_only=False, should_inherit=True):
|
def get_psets(element, psets_only=False, qtos_only=False, should_inherit=True, verbose=False):
|
||||||
"""Retrieve property sets, their related properties' names & values and ids.
|
"""Retrieve property sets, their related properties' names & values and ids.
|
||||||
|
|
||||||
If should_inherit is true, the pset "id" only refers to the ID of the
|
If should_inherit is true, the pset "id" only refers to the ID of the
|
||||||
@@ -122,12 +122,12 @@ def get_psets(element, psets_only=False, qtos_only=False, should_inherit=True):
|
|||||||
continue
|
continue
|
||||||
if qtos_only and not definition.is_a("IfcElementQuantity"):
|
if qtos_only and not definition.is_a("IfcElementQuantity"):
|
||||||
continue
|
continue
|
||||||
psets[definition.Name] = get_property_definition(definition)
|
psets[definition.Name] = get_property_definition(definition, verbose=verbose)
|
||||||
elif element.is_a("IfcMaterialDefinition") or element.is_a("IfcProfileDef"):
|
elif element.is_a("IfcMaterialDefinition") or element.is_a("IfcProfileDef"):
|
||||||
for definition in getattr(element, "HasProperties", None) or []:
|
for definition in getattr(element, "HasProperties", None) or []:
|
||||||
if qtos_only:
|
if qtos_only:
|
||||||
continue
|
continue
|
||||||
psets[definition.Name] = get_property_definition(definition)
|
psets[definition.Name] = get_property_definition(definition, verbose=verbose)
|
||||||
elif hasattr(element, "IsDefinedBy"):
|
elif hasattr(element, "IsDefinedBy"):
|
||||||
if should_inherit:
|
if should_inherit:
|
||||||
element_type = ifcopenshell.util.element.get_type(element)
|
element_type = ifcopenshell.util.element.get_type(element)
|
||||||
@@ -140,21 +140,21 @@ def get_psets(element, psets_only=False, qtos_only=False, should_inherit=True):
|
|||||||
continue
|
continue
|
||||||
if qtos_only and not definition.is_a("IfcElementQuantity"):
|
if qtos_only and not definition.is_a("IfcElementQuantity"):
|
||||||
continue
|
continue
|
||||||
psets.setdefault(definition.Name, {}).update(get_property_definition(definition))
|
psets.setdefault(definition.Name, {}).update(get_property_definition(definition, verbose=verbose))
|
||||||
return psets
|
return psets
|
||||||
|
|
||||||
|
|
||||||
def get_property_definition(definition, prop=None):
|
def get_property_definition(definition, prop=None, verbose=False):
|
||||||
if not definition:
|
if not definition:
|
||||||
return
|
return
|
||||||
|
|
||||||
if prop:
|
if prop:
|
||||||
if definition.is_a("IfcElementQuantity"):
|
if definition.is_a("IfcElementQuantity"):
|
||||||
return get_quantity(definition.Quantities, prop)
|
return get_quantity(definition.Quantities, prop, verbose=verbose)
|
||||||
elif definition.is_a("IfcPropertySet"):
|
elif definition.is_a("IfcPropertySet"):
|
||||||
return get_property(definition.HasProperties, prop)
|
return get_property(definition.HasProperties, prop, verbose=verbose)
|
||||||
elif definition.is_a("IfcMaterialProperties") or definition.is_a("IfcProfileProperties"):
|
elif definition.is_a("IfcMaterialProperties") or definition.is_a("IfcProfileProperties"):
|
||||||
return get_property(definition.Properties, prop)
|
return get_property(definition.Properties, prop, verbose=verbose)
|
||||||
else:
|
else:
|
||||||
# Entity introduced in IFC4
|
# Entity introduced in IFC4
|
||||||
# definition.is_a('IfcPreDefinedPropertySet'):
|
# definition.is_a('IfcPreDefinedPropertySet'):
|
||||||
@@ -166,11 +166,11 @@ def get_property_definition(definition, prop=None):
|
|||||||
|
|
||||||
props = {}
|
props = {}
|
||||||
if definition.is_a("IfcElementQuantity"):
|
if definition.is_a("IfcElementQuantity"):
|
||||||
props.update(get_quantities(definition.Quantities))
|
props.update(get_quantities(definition.Quantities, verbose=verbose))
|
||||||
elif definition.is_a("IfcPropertySet"):
|
elif definition.is_a("IfcPropertySet"):
|
||||||
props.update(get_properties(definition.HasProperties))
|
props.update(get_properties(definition.HasProperties, verbose=verbose))
|
||||||
elif definition.is_a("IfcMaterialProperties") or definition.is_a("IfcProfileProperties"):
|
elif definition.is_a("IfcMaterialProperties") or definition.is_a("IfcProfileProperties"):
|
||||||
props.update(get_properties(definition.Properties))
|
props.update(get_properties(definition.Properties, verbose=verbose))
|
||||||
else:
|
else:
|
||||||
# Entity introduced in IFC4
|
# Entity introduced in IFC4
|
||||||
# definition.is_a('IfcPreDefinedPropertySet'):
|
# definition.is_a('IfcPreDefinedPropertySet'):
|
||||||
@@ -181,76 +181,105 @@ def get_property_definition(definition, prop=None):
|
|||||||
return props
|
return props
|
||||||
|
|
||||||
|
|
||||||
def get_quantity(quantities, name):
|
def get_quantity(quantities, name, verbose=False):
|
||||||
for quantity in quantities or []:
|
for quantity in quantities or []:
|
||||||
if quantity.Name != name:
|
if quantity.Name != name:
|
||||||
continue
|
continue
|
||||||
if quantity.is_a("IfcPhysicalSimpleQuantity"):
|
if quantity.is_a("IfcPhysicalSimpleQuantity"):
|
||||||
return quantity[3]
|
result = quantity[3]
|
||||||
results[quantity.Name] = quantity[3]
|
|
||||||
elif quantity.is_a("IfcPhysicalComplexQuantity"):
|
elif quantity.is_a("IfcPhysicalComplexQuantity"):
|
||||||
data = {k: v for k, v in quantity.get_info().items() if v is not None and k != "Name"}
|
data = {k: v for k, v in quantity.get_info().items() if v is not None and k != "Name"}
|
||||||
data["properties"] = get_quantities(quantity.HasQuantities)
|
data["properties"] = get_quantities(quantity.HasQuantities)
|
||||||
del data["HasQuantities"]
|
del data["HasQuantities"]
|
||||||
return data
|
result = data
|
||||||
|
if verbose:
|
||||||
|
result = {"id": quantity.id(), "class": quantity.is_a(), "value": result}
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_quantities(quantities, name=None):
|
def get_quantities(quantities, verbose=False):
|
||||||
results = {}
|
results = {}
|
||||||
for quantity in quantities or []:
|
for quantity in quantities or []:
|
||||||
if quantity.is_a("IfcPhysicalSimpleQuantity"):
|
if quantity.is_a("IfcPhysicalSimpleQuantity"):
|
||||||
results[quantity.Name] = quantity[3]
|
results[quantity.Name] = quantity[3]
|
||||||
|
if verbose:
|
||||||
|
results[quantity.Name] = {
|
||||||
|
"id": quantity.id(),
|
||||||
|
"class": quantity.is_a(),
|
||||||
|
"value": results[quantity.Name],
|
||||||
|
}
|
||||||
elif quantity.is_a("IfcPhysicalComplexQuantity"):
|
elif quantity.is_a("IfcPhysicalComplexQuantity"):
|
||||||
data = {k: v for k, v in quantity.get_info().items() if v is not None and k != "Name"}
|
data = {k: v for k, v in quantity.get_info().items() if v is not None and k != "Name"}
|
||||||
data["properties"] = get_quantities(quantity.HasQuantities)
|
data["properties"] = get_quantities(quantity.HasQuantities)
|
||||||
del data["HasQuantities"]
|
del data["HasQuantities"]
|
||||||
results[quantity.Name] = data
|
results[quantity.Name] = data
|
||||||
|
if verbose:
|
||||||
|
results[quantity.Name] = {
|
||||||
|
"id": quantity.id(),
|
||||||
|
"class": quantity.is_a(),
|
||||||
|
"value": results[quantity.Name],
|
||||||
|
}
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def get_property(properties, name):
|
def get_property(properties, name, verbose=False):
|
||||||
for prop in properties or []:
|
for prop in properties or []:
|
||||||
if prop.Name != name:
|
if prop.Name != name:
|
||||||
continue
|
continue
|
||||||
if prop.is_a("IfcPropertySingleValue"):
|
if prop.is_a("IfcPropertySingleValue"):
|
||||||
return prop.NominalValue.wrappedValue if prop.NominalValue else None
|
result = prop.NominalValue.wrappedValue if prop.NominalValue else None
|
||||||
elif prop.is_a("IfcPropertyEnumeratedValue"):
|
elif prop.is_a("IfcPropertyEnumeratedValue"):
|
||||||
return [v.wrappedValue for v in prop.EnumerationValues] if prop.EnumerationValues else None
|
result = [v.wrappedValue for v in prop.EnumerationValues] if prop.EnumerationValues else None
|
||||||
elif prop.is_a("IfcPropertyListValue"):
|
elif prop.is_a("IfcPropertyListValue"):
|
||||||
return [v.wrappedValue for v in prop.ListValues] or None
|
result = [v.wrappedValue for v in prop.ListValues] or None
|
||||||
elif prop.is_a("IfcPropertyBoundedValue"):
|
elif prop.is_a("IfcPropertyBoundedValue"):
|
||||||
data = prop.get_info()
|
data = prop.get_info()
|
||||||
del data["Unit"]
|
del data["Unit"]
|
||||||
return data
|
result = data
|
||||||
elif prop.is_a("IfcPropertyTableValue"):
|
elif prop.is_a("IfcPropertyTableValue"):
|
||||||
return prop.get_info()
|
result = prop.get_info()
|
||||||
elif prop.is_a("IfcComplexProperty"):
|
elif prop.is_a("IfcComplexProperty"):
|
||||||
data = {k: v for k, v in prop.get_info().items() if v is not None and k != "Name"}
|
data = {k: v for k, v in prop.get_info().items() if v is not None and k != "Name"}
|
||||||
data["properties"] = get_properties(prop.HasProperties)
|
data["properties"] = get_properties(prop.HasProperties)
|
||||||
del data["HasProperties"]
|
del data["HasProperties"]
|
||||||
return data
|
result = data
|
||||||
|
if verbose:
|
||||||
|
result = {"id": prop.id(), "class": prop.is_a(), "value": result}
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_properties(properties):
|
def get_properties(properties, verbose=False):
|
||||||
results = {}
|
results = {}
|
||||||
for prop in properties or []:
|
for prop in properties or []:
|
||||||
if prop.is_a("IfcPropertySingleValue"):
|
if prop.is_a("IfcPropertySingleValue"):
|
||||||
results[prop.Name] = prop.NominalValue.wrappedValue if prop.NominalValue else None
|
results[prop.Name] = prop.NominalValue.wrappedValue if prop.NominalValue else None
|
||||||
|
if verbose:
|
||||||
|
results[prop.Name] = {"id": prop.id(), "class": prop.is_a(), "value": results[prop.Name]}
|
||||||
elif prop.is_a("IfcPropertyEnumeratedValue"):
|
elif prop.is_a("IfcPropertyEnumeratedValue"):
|
||||||
results[prop.Name] = [v.wrappedValue for v in prop.EnumerationValues] if prop.EnumerationValues else None
|
results[prop.Name] = [v.wrappedValue for v in prop.EnumerationValues] if prop.EnumerationValues else None
|
||||||
|
if verbose:
|
||||||
|
results[prop.Name] = {"id": prop.id(), "class": prop.is_a(), "value": results[prop.Name]}
|
||||||
elif prop.is_a("IfcPropertyListValue"):
|
elif prop.is_a("IfcPropertyListValue"):
|
||||||
results[prop.Name] = [v.wrappedValue for v in prop.ListValues] or None
|
results[prop.Name] = [v.wrappedValue for v in prop.ListValues] or None
|
||||||
|
if verbose:
|
||||||
|
results[prop.Name] = {"id": prop.id(), "class": prop.is_a(), "value": results[prop.Name]}
|
||||||
elif prop.is_a("IfcPropertyBoundedValue"):
|
elif prop.is_a("IfcPropertyBoundedValue"):
|
||||||
data = prop.get_info()
|
data = prop.get_info()
|
||||||
del data["Unit"]
|
del data["Unit"]
|
||||||
results[prop.Name] = data
|
results[prop.Name] = data
|
||||||
|
if verbose:
|
||||||
|
results[prop.Name] = {"id": prop.id(), "class": prop.is_a(), "value": results[prop.Name]}
|
||||||
elif prop.is_a("IfcPropertyTableValue"):
|
elif prop.is_a("IfcPropertyTableValue"):
|
||||||
results[prop.Name] = prop.get_info()
|
results[prop.Name] = prop.get_info()
|
||||||
|
if verbose:
|
||||||
|
results[prop.Name] = {"id": prop.id(), "class": prop.is_a(), "value": results[prop.Name]}
|
||||||
elif prop.is_a("IfcComplexProperty"):
|
elif prop.is_a("IfcComplexProperty"):
|
||||||
data = {k: v for k, v in prop.get_info().items() if v is not None and k != "Name"}
|
data = {k: v for k, v in prop.get_info().items() if v is not None and k != "Name"}
|
||||||
data["properties"] = get_properties(prop.HasProperties)
|
data["properties"] = get_properties(prop.HasProperties)
|
||||||
del data["HasProperties"]
|
del data["HasProperties"]
|
||||||
results[prop.Name] = data
|
results[prop.Name] = data
|
||||||
|
if verbose:
|
||||||
|
results[prop.Name] = {"id": prop.id(), "class": prop.is_a(), "value": results[prop.Name]}
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ class TestGetPsetIFC4(test.bootstrap.IFC4):
|
|||||||
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"a": "b"})
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"a": "b"})
|
||||||
assert subject.get_pset(element, "name") == {"a": "b", "id": pset.id()}
|
assert subject.get_pset(element, "name") == {"a": "b", "id": pset.id()}
|
||||||
assert subject.get_pset(element, "name", "a") == "b"
|
assert subject.get_pset(element, "name", "a") == "b"
|
||||||
|
assert subject.get_pset(element, "name", "a", verbose=True) == {
|
||||||
|
"id": 4,
|
||||||
|
"class": "IfcPropertySingleValue",
|
||||||
|
"value": "b",
|
||||||
|
}
|
||||||
|
|
||||||
def test_getting_the_psets_of_a_product_type_as_a_dictionary(self):
|
def test_getting_the_psets_of_a_product_type_as_a_dictionary(self):
|
||||||
type_element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
|
type_element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
|
||||||
@@ -38,6 +43,14 @@ class TestGetPsetIFC4(test.bootstrap.IFC4):
|
|||||||
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=type_element, name="name")
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=type_element, name="name")
|
||||||
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"x": "y"})
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"x": "y"})
|
||||||
assert subject.get_pset(type_element, "name") == {"x": "y", "id": pset.id()}
|
assert subject.get_pset(type_element, "name") == {"x": "y", "id": pset.id()}
|
||||||
|
assert subject.get_pset(type_element, "name", verbose=True) == {
|
||||||
|
"x": {
|
||||||
|
"id": 3,
|
||||||
|
"class": "IfcPropertySingleValue",
|
||||||
|
"value": "y",
|
||||||
|
},
|
||||||
|
"id": pset.id(),
|
||||||
|
}
|
||||||
|
|
||||||
def test_getting_inherited_psets(self):
|
def test_getting_inherited_psets(self):
|
||||||
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||||
@@ -401,34 +414,55 @@ class TestGetStyles(test.bootstrap.IFC4):
|
|||||||
assert subject.get_styles(element) == []
|
assert subject.get_styles(element) == []
|
||||||
|
|
||||||
model = ifcopenshell.api.run("context.add_context", self.file, context_type="Model")
|
model = ifcopenshell.api.run("context.add_context", self.file, context_type="Model")
|
||||||
body = ifcopenshell.api.run("context.add_context", self.file,
|
body = ifcopenshell.api.run(
|
||||||
context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=model)
|
"context.add_context",
|
||||||
|
self.file,
|
||||||
|
context_type="Model",
|
||||||
|
context_identifier="Body",
|
||||||
|
target_view="MODEL_VIEW",
|
||||||
|
parent=model,
|
||||||
|
)
|
||||||
|
|
||||||
material = ifcopenshell.api.run("material.add_material", self.file)
|
material = ifcopenshell.api.run("material.add_material", self.file)
|
||||||
ifcopenshell.api.run("material.assign_material", self.file, product=element, material=material)
|
ifcopenshell.api.run("material.assign_material", self.file, product=element, material=material)
|
||||||
|
|
||||||
style = ifcopenshell.api.run("style.add_style", self.file)
|
style = ifcopenshell.api.run("style.add_style", self.file)
|
||||||
ifcopenshell.api.run("style.add_surface_style", self.file,
|
ifcopenshell.api.run(
|
||||||
style=style, ifc_class="IfcSurfaceStyleShading", attributes={
|
"style.add_surface_style",
|
||||||
"SurfaceColour": { "Name": None, "Red": 1.0, "Green": 0.8, "Blue": 0.8 },
|
self.file,
|
||||||
"Transparency": 0., # 0 is opaque, 1 is transparent
|
style=style,
|
||||||
})
|
ifc_class="IfcSurfaceStyleShading",
|
||||||
|
attributes={
|
||||||
|
"SurfaceColour": {"Name": None, "Red": 1.0, "Green": 0.8, "Blue": 0.8},
|
||||||
|
"Transparency": 0.0, # 0 is opaque, 1 is transparent
|
||||||
|
},
|
||||||
|
)
|
||||||
ifcopenshell.api.run("style.assign_material_style", self.file, material=material, style=style, context=body)
|
ifcopenshell.api.run("style.assign_material_style", self.file, material=material, style=style, context=body)
|
||||||
|
|
||||||
assert subject.get_styles(element) == [style]
|
assert subject.get_styles(element) == [style]
|
||||||
|
|
||||||
style2 = ifcopenshell.api.run("style.add_style", self.file)
|
style2 = ifcopenshell.api.run("style.add_style", self.file)
|
||||||
ifcopenshell.api.run("style.add_surface_style", self.file,
|
ifcopenshell.api.run(
|
||||||
style=style2, ifc_class="IfcSurfaceStyleShading", attributes={
|
"style.add_surface_style",
|
||||||
"SurfaceColour": { "Name": None, "Red": 1.0, "Green": 0.8, "Blue": 0.8 },
|
self.file,
|
||||||
"Transparency": 0., # 0 is opaque, 1 is transparent
|
style=style2,
|
||||||
})
|
ifc_class="IfcSurfaceStyleShading",
|
||||||
|
attributes={
|
||||||
|
"SurfaceColour": {"Name": None, "Red": 1.0, "Green": 0.8, "Blue": 0.8},
|
||||||
|
"Transparency": 0.0, # 0 is opaque, 1 is transparent
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
representation = ifcopenshell.api.run("geometry.add_wall_representation", self.file,
|
representation = ifcopenshell.api.run(
|
||||||
context=body, length=5, height=3, thickness=0.118)
|
"geometry.add_wall_representation", self.file, context=body, length=5, height=3, thickness=0.118
|
||||||
|
)
|
||||||
|
|
||||||
ifcopenshell.api.run("geometry.assign_representation", self.file, product=element, representation=representation)
|
ifcopenshell.api.run(
|
||||||
ifcopenshell.api.run("style.assign_representation_styles", self.file, shape_representation=representation, styles=[style2])
|
"geometry.assign_representation", self.file, product=element, representation=representation
|
||||||
|
)
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"style.assign_representation_styles", self.file, shape_representation=representation, styles=[style2]
|
||||||
|
)
|
||||||
|
|
||||||
assert subject.get_styles(element) == [style, style2]
|
assert subject.get_styles(element) == [style, style2]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user