mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 18:16:20 +00:00
get_pset, get_psets - don't fail on ifc2x3 profile psets and partially handle ifc2x3 material psets #6538
This commit is contained in:
@@ -66,6 +66,10 @@ def add_pset(
|
|||||||
like "Pset_WallCommon". If you create your own, you must not use
|
like "Pset_WallCommon". If you create your own, you must not use
|
||||||
that prefix. It is recommended to use your own prefix tailored to
|
that prefix. It is recommended to use your own prefix tailored to
|
||||||
your project, company, or local government requirement.
|
your project, company, or local government requirement.
|
||||||
|
|
||||||
|
In IFC2X3 should be provided as an empty string for profile properties
|
||||||
|
(they all don't have a name property) and all material properties
|
||||||
|
besides IfcExtendedMaterialProperties.
|
||||||
:param ifc2x3_subclass: IFC2X3 subclass for material or profile properties.
|
:param ifc2x3_subclass: IFC2X3 subclass for material or profile properties.
|
||||||
In IFC2X3 IfcProfileProperties and IfcMaterialProperties are abstract
|
In IFC2X3 IfcProfileProperties and IfcMaterialProperties are abstract
|
||||||
so you need one of their subclasses to instantiate them.
|
so you need one of their subclasses to instantiate them.
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ def get_pset(
|
|||||||
type_pset = None
|
type_pset = None
|
||||||
ifc_file = element.file
|
ifc_file = element.file
|
||||||
is_ifc2x3 = ifc_file.schema == "IFC2X3"
|
is_ifc2x3 = ifc_file.schema == "IFC2X3"
|
||||||
|
is_profile = False
|
||||||
|
|
||||||
if element.is_a("IfcTypeObject"):
|
if element.is_a("IfcTypeObject"):
|
||||||
for definition in element.HasPropertySets or []:
|
for definition in element.HasPropertySets or []:
|
||||||
@@ -81,14 +82,19 @@ def get_pset(
|
|||||||
elif (
|
elif (
|
||||||
(is_ifc2x3_material := (is_ifc2x3 and element.is_a("IfcMaterial")))
|
(is_ifc2x3_material := (is_ifc2x3 and element.is_a("IfcMaterial")))
|
||||||
or element.is_a("IfcMaterialDefinition")
|
or element.is_a("IfcMaterialDefinition")
|
||||||
or element.is_a("IfcProfileDef")
|
or (is_profile := element.is_a("IfcProfileDef"))
|
||||||
):
|
):
|
||||||
if is_ifc2x3_material:
|
if is_ifc2x3_material:
|
||||||
|
# Support extended props as they do have a name.
|
||||||
for definition in ifc_file.by_type("IfcExtendedMaterialProperties"):
|
for definition in ifc_file.by_type("IfcExtendedMaterialProperties"):
|
||||||
if definition.Material == element and definition.Name == name:
|
if definition.Material == element and definition.Name == name:
|
||||||
pset = definition
|
pset = definition
|
||||||
break
|
break
|
||||||
|
elif is_ifc2x3 and is_profile:
|
||||||
|
# Don't support them as they don't have a name.
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
|
# IfcProfileDef or IfcMaterialDefinition, IFC4+.
|
||||||
for definition in element.HasProperties or []:
|
for definition in element.HasProperties or []:
|
||||||
if definition.Name == name:
|
if definition.Name == name:
|
||||||
pset = definition
|
pset = definition
|
||||||
@@ -165,6 +171,8 @@ def get_psets(
|
|||||||
qsets = ifcopenshell.util.element.get_psets(element, qtos_only=True)
|
qsets = ifcopenshell.util.element.get_psets(element, qtos_only=True)
|
||||||
psets_and_qtos = ifcopenshell.util.element.get_psets(element)
|
psets_and_qtos = ifcopenshell.util.element.get_psets(element)
|
||||||
"""
|
"""
|
||||||
|
ifc_file = element.file
|
||||||
|
is_ifc2x3 = ifc_file.schema == "IFC2X3"
|
||||||
psets = {}
|
psets = {}
|
||||||
if element.is_a("IfcTypeObject"):
|
if element.is_a("IfcTypeObject"):
|
||||||
for definition in element.HasPropertySets or []:
|
for definition in element.HasPropertySets or []:
|
||||||
@@ -174,8 +182,22 @@ def get_psets(
|
|||||||
continue
|
continue
|
||||||
psets.setdefault(definition.Name, {}).update(get_property_definition(definition, verbose=verbose))
|
psets.setdefault(definition.Name, {}).update(get_property_definition(definition, verbose=verbose))
|
||||||
# NOTE: doesn't account for IFC2X3 missing HasProperties
|
# NOTE: doesn't account for IFC2X3 missing HasProperties
|
||||||
elif element.is_a("IfcMaterialDefinition") or element.is_a("IfcProfileDef"):
|
elif (
|
||||||
for definition in getattr(element, "HasProperties", None) or []:
|
(is_ifc2x3_material := (is_ifc2x3 and element.is_a("IfcMaterial")))
|
||||||
|
or element.is_a("IfcMaterialDefinition")
|
||||||
|
or element.is_a("IfcProfileDef")
|
||||||
|
):
|
||||||
|
definitions: list[ifcopenshell.entity_instance]
|
||||||
|
if is_ifc2x3:
|
||||||
|
if is_ifc2x3_material:
|
||||||
|
# Only extended props have a name.
|
||||||
|
definitions = [d for d in ifc_file.by_type("IfcExtendedMaterialProperties") if d.Material == element]
|
||||||
|
else:
|
||||||
|
# Ignoring profiles as they don't have names.
|
||||||
|
definitions = []
|
||||||
|
else:
|
||||||
|
definitions = getattr(element, "HasProperties", None) or []
|
||||||
|
for definition in definitions:
|
||||||
if qtos_only:
|
if qtos_only:
|
||||||
continue
|
continue
|
||||||
psets.setdefault(definition.Name, {}).update(get_property_definition(definition, verbose=verbose))
|
psets.setdefault(definition.Name, {}).update(get_property_definition(definition, verbose=verbose))
|
||||||
@@ -247,6 +269,9 @@ def get_property_definition(
|
|||||||
elif ifc_class == "IfcMaterialProperties" or ifc_class == "IfcProfileProperties":
|
elif ifc_class == "IfcMaterialProperties" or ifc_class == "IfcProfileProperties":
|
||||||
# 2 IfcExtendedProperties.Properties
|
# 2 IfcExtendedProperties.Properties
|
||||||
props.update(get_properties(definition[2], verbose=verbose))
|
props.update(get_properties(definition[2], verbose=verbose))
|
||||||
|
elif ifc_class == "IfcExtendedMaterialProperties":
|
||||||
|
# 1 IfcExtendedMaterialProperties.ExtendedProperties
|
||||||
|
props.update(get_properties(definition[1], verbose=verbose))
|
||||||
else:
|
else:
|
||||||
# Entity introduced in IFC4
|
# Entity introduced in IFC4
|
||||||
# definition.is_a('IfcPreDefinedPropertySet'):
|
# definition.is_a('IfcPreDefinedPropertySet'):
|
||||||
|
|||||||
@@ -41,6 +41,28 @@ import ifcopenshell.util.element as subject
|
|||||||
from ifcopenshell.util.shape_builder import ShapeBuilder
|
from ifcopenshell.util.shape_builder import ShapeBuilder
|
||||||
|
|
||||||
|
|
||||||
|
class TestIFC2X3MaterialProfilePsts(test.bootstrap.IFC2X3):
|
||||||
|
def test_get_profile_pset(self):
|
||||||
|
profile = ifcopenshell.api.profile.add_parameterized_profile(self.file, "IfcRectangleProfileDef")
|
||||||
|
pset = ifcopenshell.api.pset.add_pset(self.file, profile, "")
|
||||||
|
pset.Perimeter = 25.0
|
||||||
|
# We don't support them, just making sure there are no errors.
|
||||||
|
assert subject.get_pset(profile, "Test") is None
|
||||||
|
assert subject.get_psets(profile) == {}
|
||||||
|
|
||||||
|
def get_material_pset_extended_params(self):
|
||||||
|
material_with_extended_params = ifcopenshell.api.material.add_material(self.file)
|
||||||
|
pset = ifcopenshell.api.pset.add_pset(self.file, material_with_extended_params, "Test")
|
||||||
|
ifcopenshell.api.pset.edit_pset(self.file, pset, "Test", {"GassPressure": 25.0})
|
||||||
|
pset_data = subject.get_pset(material_with_extended_params, "Test")
|
||||||
|
del pset_data["id"]
|
||||||
|
assert pset_data == {"GassPressure": 25.0}
|
||||||
|
psets_data = subject.get_psets(material_with_extended_params)
|
||||||
|
for value in psets_data.values():
|
||||||
|
del value["id"]
|
||||||
|
assert psets_data == {"Test": {"GassPressure": 25.0}}
|
||||||
|
|
||||||
|
|
||||||
class TestGetPsetIFC4(test.bootstrap.IFC4):
|
class TestGetPsetIFC4(test.bootstrap.IFC4):
|
||||||
def test_getting_the_psets_of_a_product_as_a_dictionary(self):
|
def test_getting_the_psets_of_a_product_as_a_dictionary(self):
|
||||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
|||||||
Reference in New Issue
Block a user