diff --git a/src/ifcpatch/ifcpatch/recipes/MergeDuplicateTypes.py b/src/ifcpatch/ifcpatch/recipes/MergeDuplicateTypes.py index 83cdae5235..fe82b33cfb 100644 --- a/src/ifcpatch/ifcpatch/recipes/MergeDuplicateTypes.py +++ b/src/ifcpatch/ifcpatch/recipes/MergeDuplicateTypes.py @@ -25,7 +25,7 @@ from typing import Any class Patcher: - def __init__(self, file: ifcopenshell.file, logger: Logger, attribute: str = "Tag"): + def __init__(self, file: ifcopenshell.file, logger: Logger, attribute: str = "Tag", should_merge_null: bool = True): """Merge duplicate element types via the Tag or another attribute Revit is notorious for creating many duplicate element types. Element @@ -50,6 +50,8 @@ class Patcher: :param attribute: The name of the attribute to merge element types based on. Typically this will be "Tag" as it stores the unique ID from the proprietary BIM software. + :param should_merge_null: If True, all elements with an empty attribute + will be merged. If False, they will be kept separate. Example: @@ -64,12 +66,15 @@ class Patcher: self.file = file self.logger = logger self.attribute = attribute + self.should_merge_null = should_merge_null def patch(self): - key = self.attribute keys: dict[Any, ifcopenshell.entity_instance] = {} for element_type in self.file.by_type("IfcTypeObject"): - original_type = keys.get(getattr(element_type, key), None) + key = getattr(element_type, self.attribute) + if not key and not self.should_merge_null: + continue + original_type = keys.get(key, None) if original_type: elements = ifcopenshell.util.element.get_types(element_type) if elements: @@ -78,7 +83,7 @@ class Patcher: ifcopenshell.util.element.replace_attribute(inverse, element_type, original_type) self.file.remove(element_type) else: - keys[getattr(element_type, key)] = element_type + keys[key] = element_type def assign_type( self, related_objects: list[ifcopenshell.entity_instance], relating_type: ifcopenshell.entity_instance diff --git a/src/ifcpatch/test/test_MergeDuplicateTypes.py b/src/ifcpatch/test/test_MergeDuplicateTypes.py index 9abc29c044..37e37d39b4 100644 --- a/src/ifcpatch/test/test_MergeDuplicateTypes.py +++ b/src/ifcpatch/test/test_MergeDuplicateTypes.py @@ -74,6 +74,15 @@ class TestMergeDuplicateTypes(test.bootstrap.IFC4): assert ifcopenshell.util.element.get_material(wall1, should_inherit=False) == None assert ifcopenshell.util.element.get_material(wall2, should_inherit=False) == None + def test_not_merging_empty_attributes(self): + wall_type1 = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType", name="") + wall_type2 = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType", name="") + output = ifcpatch.execute({"file": self.file, "recipe": "MergeDuplicateTypes", "arguments": ["Name", True]}) + assert len(output.by_type("IfcWallType")) == 1 + wall_type3 = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType", name="") + output = ifcpatch.execute({"file": self.file, "recipe": "MergeDuplicateTypes", "arguments": ["Name", False]}) + assert len(output.by_type("IfcWallType")) == 2 + class TestMergeDuplicateTypesIFC2X3(test.bootstrap.IFC2X3, TestMergeDuplicateTypes): pass