From 54fa45850a2233a39e21bf96e7836df8dc76a410 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 25 Oct 2021 16:09:04 +1100 Subject: [PATCH] Get psets utility now supports getting material and profile psets --- .../ifcopenshell/util/element.py | 22 ++++++++----- .../test/util/test_element.py | 33 +++++++++++++++---- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index 9af1ce647d..aa52b029c8 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -4,13 +4,17 @@ import ifcopenshell def get_psets(element, psets_only=False, qtos_only=False): psets = {} if element.is_a("IfcTypeObject"): - if element.HasPropertySets: - for definition in element.HasPropertySets: - if psets_only and not definition.is_a("IfcPropertySet"): - continue - if qtos_only and not definition.is_a("IfcElementQuantity"): - continue - psets[definition.Name] = get_property_definition(definition) + for definition in element.HasPropertySets or []: + if psets_only and not definition.is_a("IfcPropertySet"): + continue + if qtos_only and not definition.is_a("IfcElementQuantity"): + continue + psets[definition.Name] = get_property_definition(definition) + elif element.is_a("IfcMaterialDefinition") or element.is_a("IfcProfileDef"): + for definition in element.HasProperties or []: + if qtos_only: + continue + psets[definition.Name] = get_property_definition(definition) elif hasattr(element, "IsDefinedBy"): for relationship in element.IsDefinedBy: if relationship.is_a("IfcRelDefinesByProperties"): @@ -30,6 +34,8 @@ def get_property_definition(definition): props.update(get_quantities(definition.Quantities)) elif definition.is_a("IfcPropertySet"): props.update(get_properties(definition.HasProperties)) + elif definition.is_a("IfcMaterialProperties") or definition.is_a("IfcProfileProperties"): + props.update(get_properties(definition.Properties)) else: # Entity introduced in IFC4 # definition.is_a('IfcPreDefinedPropertySet'): @@ -42,7 +48,7 @@ def get_property_definition(definition): def get_quantities(quantities): results = {} - for quantity in quantities: + for quantity in quantities or []: if quantity.is_a("IfcPhysicalSimpleQuantity"): results[quantity.Name] = quantity[3] return results diff --git a/src/ifcopenshell-python/test/util/test_element.py b/src/ifcopenshell-python/test/util/test_element.py index 8bd4dedcb3..d3f9c23158 100644 --- a/src/ifcopenshell-python/test/util/test_element.py +++ b/src/ifcopenshell-python/test/util/test_element.py @@ -19,6 +19,20 @@ class TestGetPsetsIFC4(test.bootstrap.IFC4): ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"x": "y"}) assert subject.get_psets(type_element) == {"name": {"x": "y", "id": pset.id()}} + def test_getting_the_psets_of_a_material_as_a_dictionary(self): + material = self.file.createIfcMaterial() + assert subject.get_psets(material) == {} + pset = ifcopenshell.api.run("pset.add_pset", self.file, product=material, name="name") + ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"x": "y"}) + assert subject.get_psets(material) == {"name": {"x": "y", "id": pset.id()}} + + def test_getting_the_psets_of_a_profile_as_a_dictionary(self): + profile = self.file.createIfcCircleProfileDef() + assert subject.get_psets(profile) == {} + pset = ifcopenshell.api.run("pset.add_pset", self.file, product=profile, name="name") + ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"x": "y"}) + assert subject.get_psets(profile) == {"name": {"x": "y", "id": pset.id()}} + def test_getting_psets_from_an_element_which_cannot_have_psets(self): assert subject.get_psets(self.file.create_entity("IfcPerson")) == {} @@ -52,6 +66,16 @@ class TestGetPropertyDefinitionIFC4(test.bootstrap.IFC4): ifcopenshell.api.run("pset.edit_qto", self.file, qto=qto, properties={"x": 42}) assert subject.get_property_definition(qto) == {"x": 42, "id": qto.id()} + def test_getting_the_properties_of_a_material_property(self): + pset = self.file.createIfcMaterialProperties() + ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"a": "b"}) + assert subject.get_property_definition(pset) == {"a": "b", "id": pset.id()} + + def test_getting_the_properties_of_a_profile_property(self): + pset = self.file.createIfcProfileProperties() + ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"a": "b"}) + assert subject.get_property_definition(pset) == {"a": "b", "id": pset.id()} + def test_getting_the_properties_of_a_predefined_pset(self): pset = self.file.create_entity("IfcDoorLiningProperties", ifcopenshell.guid.new()) pset.LiningDepth = 42 @@ -156,19 +180,14 @@ class TestGetMaterial(test.bootstrap.IFC4): rel = ifcopenshell.api.run( "material.assign_material", self.file, product=element, type="IfcMaterialLayerSetUsage" ) - assert ( - subject.get_material(element, should_skip_usage=True) == rel.RelatingMaterial.ForLayerSet - ) + assert subject.get_material(element, should_skip_usage=True) == rel.RelatingMaterial.ForLayerSet def test_getting_a_material_profile_set_indirectly_from_an_assigned_usage(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") rel = ifcopenshell.api.run( "material.assign_material", self.file, product=element, type="IfcMaterialProfileSetUsage" ) - assert ( - subject.get_material(element, should_skip_usage=True) - == rel.RelatingMaterial.ForProfileSet - ) + assert subject.get_material(element, should_skip_usage=True) == rel.RelatingMaterial.ForProfileSet def test_getting_an_inherited_material_from_the_elements_type(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")