mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 06:39:13 +00:00
Fix #7213. IfcTester now supports checking for USERDEFINED predefined types
Can I just take this moment to complain about the overengineered complexity of how predefined types work in IFC.
This commit is contained in:
@@ -565,6 +565,40 @@ def get_predefined_type(element: ifcopenshell.entity_instance) -> Union[str, Non
|
|||||||
return predefined_type
|
return predefined_type
|
||||||
|
|
||||||
|
|
||||||
|
def is_userdefined_type(element: ifcopenshell.entity_instance) -> bool:
|
||||||
|
"""Checks if the predefined type is userdefined
|
||||||
|
|
||||||
|
:param element: The IFC Element entity
|
||||||
|
:return: True if userdefined
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
element = ifcopenshell.by_type("IfcWall")[0]
|
||||||
|
is_userdefined_type = ifcopenshell.util.element.is_userdefined_type(element)
|
||||||
|
"""
|
||||||
|
if element_type := get_type(element):
|
||||||
|
predefined_type = getattr(element_type, "PredefinedType", None)
|
||||||
|
if predefined_type == "USERDEFINED":
|
||||||
|
return True
|
||||||
|
elif not predefined_type:
|
||||||
|
predefined_type = getattr(element_type, "ElementType", ...)
|
||||||
|
if predefined_type == ...:
|
||||||
|
predefined_type = getattr(element_type, "ProcessType", None)
|
||||||
|
if predefined_type:
|
||||||
|
return True
|
||||||
|
if predefined_type and predefined_type != "NOTDEFINED":
|
||||||
|
return False
|
||||||
|
|
||||||
|
predefined_type = getattr(element, "PredefinedType", None)
|
||||||
|
if predefined_type == "USERDEFINED":
|
||||||
|
return True
|
||||||
|
elif not predefined_type:
|
||||||
|
return bool(getattr(element, "ObjectType", None))
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_type(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
def get_type(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
"""Retrieves the construction type element of an element occurrence.
|
"""Retrieves the construction type element of an element occurrence.
|
||||||
|
|
||||||
|
|||||||
@@ -369,6 +369,65 @@ class TestGetPredefinedTypeIFC4(test.bootstrap.IFC4):
|
|||||||
assert subject.get_predefined_type(element_type) == "NOTDEFINED"
|
assert subject.get_predefined_type(element_type) == "NOTDEFINED"
|
||||||
|
|
||||||
|
|
||||||
|
class TestIsUserdefinedTypeIFC4(test.bootstrap.IFC4):
|
||||||
|
def test_getting_a_predefined_element(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
element.PredefinedType = "PARTITIONING"
|
||||||
|
assert not subject.is_userdefined_type(element)
|
||||||
|
|
||||||
|
def test_getting_an_element_userdefined_type(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
element.PredefinedType = "USERDEFINED"
|
||||||
|
element.ObjectType = "FOOBAR"
|
||||||
|
assert subject.is_userdefined_type(element)
|
||||||
|
|
||||||
|
def test_getting_an_element_type_without_a_predefined_type_attribute(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcAnnotation")
|
||||||
|
element.ObjectType = "FOOBAR"
|
||||||
|
assert subject.is_userdefined_type(element)
|
||||||
|
|
||||||
|
def test_getting_an_inherited_predefined_type(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
ifcopenshell.api.type.assign_type(self.file, related_objects=[element], relating_type=element_type)
|
||||||
|
element_type.PredefinedType = "PARTITIONING"
|
||||||
|
assert not subject.is_userdefined_type(element)
|
||||||
|
|
||||||
|
def test_getting_an_inherited_userdefined_type_for_an_element_type(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
ifcopenshell.api.type.assign_type(self.file, related_objects=[element], relating_type=element_type)
|
||||||
|
element_type.PredefinedType = "USERDEFINED"
|
||||||
|
element_type.ElementType = "FOOBAR"
|
||||||
|
assert subject.is_userdefined_type(element)
|
||||||
|
|
||||||
|
def test_getting_an_overriden_predefined_type(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
ifcopenshell.api.type.assign_type(self.file, related_objects=[element], relating_type=element_type)
|
||||||
|
element_type.PredefinedType = "NOTDEFINED"
|
||||||
|
element.PredefinedType = "PARTITIONING"
|
||||||
|
assert not subject.is_userdefined_type(element)
|
||||||
|
|
||||||
|
def test_getting_an_inherited_userdefined_type_for_a_process_type(self):
|
||||||
|
element = ifcopenshell.api.sequence.add_task(self.file)
|
||||||
|
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcTaskType")
|
||||||
|
ifcopenshell.api.type.assign_type(self.file, related_objects=[element], relating_type=element_type)
|
||||||
|
element_type.PredefinedType = "USERDEFINED"
|
||||||
|
element_type.ProcessType = "FOOBAR"
|
||||||
|
assert subject.is_userdefined_type(element)
|
||||||
|
|
||||||
|
def test_getting_an_element_type_predefined_type(self):
|
||||||
|
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
element_type.PredefinedType = "PARTITIONING"
|
||||||
|
assert not subject.is_userdefined_type(element_type)
|
||||||
|
|
||||||
|
def test_getting_an_element_type_null_predefined_type(self):
|
||||||
|
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||||
|
element_type.PredefinedType = "NOTDEFINED"
|
||||||
|
assert not subject.is_userdefined_type(element_type)
|
||||||
|
|
||||||
|
|
||||||
class TestGetTypeIFC4(test.bootstrap.IFC4):
|
class TestGetTypeIFC4(test.bootstrap.IFC4):
|
||||||
def test_getting_the_type_of_a_product(self):
|
def test_getting_the_type_of_a_product(self):
|
||||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
|||||||
@@ -227,8 +227,13 @@ class Entity(Facet):
|
|||||||
reason = {"type": "NAME", "actual": inst.is_a().upper()}
|
reason = {"type": "NAME", "actual": inst.is_a().upper()}
|
||||||
|
|
||||||
if is_pass and self.predefinedType:
|
if is_pass and self.predefinedType:
|
||||||
predefined_type = ifcopenshell.util.element.get_predefined_type(inst)
|
if self.predefinedType == "USERDEFINED":
|
||||||
is_pass = predefined_type == self.predefinedType
|
is_pass = ifcopenshell.util.element.is_userdefined_type(inst)
|
||||||
|
if not is_pass:
|
||||||
|
predefined_type = ifcopenshell.util.element.get_predefined_type(inst)
|
||||||
|
else:
|
||||||
|
predefined_type = ifcopenshell.util.element.get_predefined_type(inst)
|
||||||
|
is_pass = predefined_type == self.predefinedType
|
||||||
|
|
||||||
if not is_pass:
|
if not is_pass:
|
||||||
reason = {"type": "PREDEFINEDTYPE", "actual": predefined_type}
|
reason = {"type": "PREDEFINEDTYPE", "actual": predefined_type}
|
||||||
|
|||||||
@@ -172,10 +172,10 @@ class TestEntity:
|
|||||||
facet = Entity(name="IFCWALL", predefinedType="USERDEFINED")
|
facet = Entity(name="IFCWALL", predefinedType="USERDEFINED")
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
run(
|
run(
|
||||||
"A predefined type must always specify a meaningful type, not USERDEFINED itself",
|
"A predefined type may specify USERDEFINED itself",
|
||||||
facet=facet,
|
facet=facet,
|
||||||
inst=ifc.createIfcWall(PredefinedType="USERDEFINED", ObjectType="WALDO"),
|
inst=ifc.createIfcWall(PredefinedType="USERDEFINED", ObjectType="WALDO"),
|
||||||
expected=False,
|
expected=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
|
|||||||
Reference in New Issue
Block a user