Fix #3996. Reassigning occurrences or types now also reassigns the correlating occurrence or type.

This commit is contained in:
Dion Moult
2023-11-28 16:44:31 +11:00
parent 3e268be5c7
commit 03809b3d5e
3 changed files with 50 additions and 20 deletions
@@ -39,6 +39,14 @@ class Usecase:
This is especially useful when dealing with poorly classified data from
proprietary software with limited IFC capabilities.
If you are reassigning a type, the occurrence classes are also
reassigned to maintain validity.
Vice versa, if you are reassigning an occurrence, the type is also
reassigned in IFC4 and up. In IFC2X3, this may not occur if the type
cannot be unambiguously derived, so you are required to manually check
this.
:param product: The IfcProduct that you want to change the class of.
:type product: ifcopenshell.entity_instance.entity_instance
:param ifc_class: The new IFC class you want to change it to.
@@ -70,10 +78,27 @@ class Usecase:
}
def execute(self):
element = ifcopenshell.util.schema.reassign_class(
self.file, self.settings["product"], self.settings["ifc_class"]
)
is_type = element.is_a("IfcTypeProduct")
element = self.reassign_class(self.settings["product"], self.settings["ifc_class"])
if element.is_a("IfcTypeProduct"):
for occurrence in ifcopenshell.util.element.get_types(element) or []:
ifc_class = ifcopenshell.util.type.get_applicable_entities(self.settings["ifc_class"])[0]
self.reassign_class(occurrence, ifc_class)
else:
element_type = ifcopenshell.util.element.get_type(element)
if element_type:
ifc_class = ifcopenshell.util.type.get_applicable_types(self.settings["ifc_class"])
if ifc_class and len(ifc_class) == 1:
element_type = self.reassign_class(element_type, ifc_class[0])
ifc_class = element.is_a()
for occurrence in ifcopenshell.util.element.get_types(element_type) or []:
if occurrence == element:
continue
self.reassign_class(occurrence, ifc_class)
return element
def reassign_class(self, element, ifc_class):
element = ifcopenshell.util.schema.reassign_class(self.file, element, ifc_class)
if self.settings["predefined_type"] and hasattr(element, "PredefinedType"):
try:
element.PredefinedType = self.settings["predefined_type"]
@@ -81,20 +106,9 @@ class Usecase:
# PredefinedType wasn't in the respective enum, assume it's actually USERDEFINED
# and set .ElementType / .ObjectType to the provided predefined type
element.PredefinedType = "USERDEFINED"
if is_type:
if element.is_a("IfcTypeProduct"):
element.ElementType = self.settings["predefined_type"]
else:
element.ObjectType = self.settings["predefined_type"]
# reassign classes for occurences connected to the type
if is_type:
for occurrence in ifcopenshell.util.element.get_types(element) or []:
ifc_class = ifcopenshell.util.type.get_applicable_entities(self.settings["ifc_class"])[0]
ifcopenshell.api.run(
"root.reassign_class",
self.file,
product=occurrence,
ifc_class=ifc_class,
predefined_type=self.settings["predefined_type"],
)
return element