diff --git a/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py b/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py index 17752a6168..c3577a43e0 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py +++ b/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py @@ -65,6 +65,11 @@ class Usecase: representations = self.settings["product"].Representation.Representations or [] else: representations = [] + + object_placement = self.settings["product"].ObjectPlacement + if object_placement and self.file.get_total_inverses(object_placement) == 1: + self.settings["product"].ObjectPlacement = None # remove the inverse for remove_deep2 to work + ifcopenshell.util.element.remove_deep2(self.file, object_placement) elif self.settings["product"].is_a("IfcTypeProduct"): representations = [rm.MappedRepresentation for rm in self.settings["product"].RepresentationMaps or []] for representation in representations: 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 c37048874a..d45b306e76 100644 --- a/src/ifcopenshell-python/test/api/root/test_remove_product.py +++ b/src/ifcopenshell-python/test/api/root/test_remove_product.py @@ -26,6 +26,34 @@ class TestRemoveProduct(test.bootstrap.IFC4): ifcopenshell.api.run("root.remove_product", self.file, product=element) assert len(self.file.by_type("IfcWall")) == 0 + def test_removing_an_element_local_placement(self): + # just removing the product with the placement + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + placement = ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=element) + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(self.file.by_type("IfcObjectPlacement")) == 0 + + # removing the product that shares the placement with other product + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + placement = ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=element) + element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + element1.ObjectPlacement = placement + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(self.file.by_type("IfcObjectPlacement")) == 1 + ifcopenshell.api.run("root.remove_product", self.file, product=element1) + assert len(self.file.by_type("IfcObjectPlacement")) == 0 + + # removing the product that's placement used as a reference point for another placement + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + placement = ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=element) + element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + placement1 = ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=element1) + placement.PlacementRelTo = placement1 + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(self.file.by_type("IfcObjectPlacement")) == 1 + ifcopenshell.api.run("root.remove_product", self.file, product=element1) + assert len(self.file.by_type("IfcObjectPlacement")) == 0 + def test_removing_all_representations_of_an_element(self): ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject") ifcopenshell.api.run("unit.assign_unit", self.file)