From f139f2ba1ed59abe4acbd08a8574e84e02fb9a40 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 23 Sep 2022 23:00:07 +1000 Subject: [PATCH] Fix bug where removing an element in an aggregation could leave the file in an invalid state --- .../ifcopenshell/api/root/remove_product.py | 5 +++++ .../test/api/root/test_remove_product.py | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py b/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py index 489be2a31f..41de3aed29 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py +++ b/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py @@ -64,4 +64,9 @@ class Usecase: ifcopenshell.api.run("root.remove_product", self.file, product=subelement) if not inverse.RelatedObjects: self.file.remove(inverse) + elif inverse.is_a("IfcRelAggregates"): + if inverse.RelatingObject == self.settings["product"]: + self.file.remove(inverse) + elif len(inverse.RelatedObjects) == 1: + self.file.remove(inverse) self.file.remove(self.settings["product"]) diff --git a/src/ifcopenshell-python/test/api/root/test_remove_product.py b/src/ifcopenshell-python/test/api/root/test_remove_product.py index 7eeb17d3cf..ce6aaf2fa1 100644 --- a/src/ifcopenshell-python/test/api/root/test_remove_product.py +++ b/src/ifcopenshell-python/test/api/root/test_remove_product.py @@ -140,3 +140,25 @@ class TestRemoveProduct(test.bootstrap.IFC4): assert len(self.file.by_type("IfcChiller")) == 0 assert len(self.file.by_type("IfcRelNests")) == 0 assert len(self.file.by_type("IfcDistributionPort")) == 0 + + def test_removing_all_aggregate_relationships_of_a_whole(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly") + subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBeam") + ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) + total_entities = len(list(self.file)) + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(list(self.file)) == total_entities - 2 + assert len(self.file.by_type("IfcRelAggregates")) == 0 + assert len(self.file.by_type("IfcElementAssembly")) == 0 + assert len(self.file.by_type("IfcBeam")) == 1 + + def test_removing_all_aggregate_relationships_of_a_part(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly") + subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBeam") + ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) + total_entities = len(list(self.file)) + ifcopenshell.api.run("root.remove_product", self.file, product=subelement) + assert len(list(self.file)) == total_entities - 2 + assert len(self.file.by_type("IfcRelAggregates")) == 0 + assert len(self.file.by_type("IfcElementAssembly")) == 1 + assert len(self.file.by_type("IfcBeam")) == 0