From cefa088b59d788677c307e885da1c8ee7cbb1231 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 5 Apr 2024 16:28:16 +0500 Subject: [PATCH] spatial.unassign_container - support batching #4474 --- .../api/spatial/unassign_container.py | 32 ++++++++++--------- .../api/spatial/test_unassign_container.py | 7 ++-- .../nodes/ifc/add_spatial_element.py | 2 +- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/spatial/unassign_container.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/unassign_container.py index 7c46bd3e49..f7c831b9fd 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/spatial/unassign_container.py +++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/unassign_container.py @@ -22,11 +22,11 @@ import ifcopenshell.util.element class Usecase: - def __init__(self, file, product=None): - """Unassigns a container from a product. + def __init__(self, file: ifcopenshell.file, products: list[ifcopenshell.entity_instance]): + """Unassigns a container from products. - :param product: The IfcProduct to remove the containment from. - :type product: ifcopenshell.entity_instance.entity_instance + :param product: A list of IfcProducts to remove the containment from. + :type product: list[ifcopenshell.entity_instance.entity_instance] :return: None :rtype: None @@ -40,32 +40,34 @@ class Usecase: storey = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBuildingStorey") # The project contains a site (note that project aggregation is a special case in IFC) - ifcopenshell.api.run("aggregate.assign_object", model, product=site, relating_object=project) + ifcopenshell.api.run("aggregate.assign_object", model, products=[site], relating_object=project) # The site has a building, the building has a storey, and the storey has a space - ifcopenshell.api.run("aggregate.assign_object", model, product=building, relating_object=site) - ifcopenshell.api.run("aggregate.assign_object", model, product=storey, relating_object=building) + ifcopenshell.api.run("aggregate.assign_object", model, products=[building], relating_object=site) + ifcopenshell.api.run("aggregate.assign_object", model, products=[storey], relating_object=building) # Create a wall wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall") # The wall is in the storey - ifcopenshell.api.run("spatial.assign_container", model, product=wall, relating_structure=storey) + ifcopenshell.api.run("spatial.assign_container", model, products=[wall], relating_structure=storey) # Not anymore! - ifcopenshell.api.run("spatial.unassign_container", model, product=wall) + ifcopenshell.api.run("spatial.unassign_container", model, products=[wall]) """ self.file = file self.settings = { - "product": product, + "products": products, } - def execute(self): - for rel in self.settings["product"].ContainedInStructure or []: - related_elements = list(rel.RelatedElements) - related_elements.remove(self.settings["product"]) + def execute(self) -> None: + products = set(self.settings["products"]) + rels = set(rel for product in products if (rel := next(iter(product.ContainedInStructure), None))) + + for rel in rels: + related_elements = set(rel.RelatedElements) - products if related_elements: - rel.RelatedElements = related_elements + rel.RelatedElements = list(related_elements) ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel) else: history = rel.OwnerHistory diff --git a/src/ifcopenshell-python/test/api/spatial/test_unassign_container.py b/src/ifcopenshell-python/test/api/spatial/test_unassign_container.py index 4240c13ff1..cbd591c0a1 100644 --- a/src/ifcopenshell-python/test/api/spatial/test_unassign_container.py +++ b/src/ifcopenshell-python/test/api/spatial/test_unassign_container.py @@ -28,8 +28,9 @@ class TestAssignContainer(test.bootstrap.IFC4): def test_unassigning_a_container(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") - ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element) - ifcopenshell.api.run("spatial.unassign_container", self.file, product=subelement) + subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement, subelement2], relating_structure=element) + ifcopenshell.api.run("spatial.unassign_container", self.file, products=[subelement, subelement2]) assert not self.file.by_type("IfcRelContainedInSpatialStructure") def test_unassigning_a_container_with_other_elements(self): @@ -38,6 +39,6 @@ class TestAssignContainer(test.bootstrap.IFC4): subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement2], relating_structure=element) - ifcopenshell.api.run("spatial.unassign_container", self.file, product=subelement) + ifcopenshell.api.run("spatial.unassign_container", self.file, products=[subelement]) rel = self.file.by_type("IfcRelContainedInSpatialStructure")[0] assert list(rel.RelatedElements) == [subelement2] diff --git a/src/ifcsverchok/nodes/ifc/add_spatial_element.py b/src/ifcsverchok/nodes/ifc/add_spatial_element.py index 07cd6b56e1..ac94ea1a3c 100644 --- a/src/ifcsverchok/nodes/ifc/add_spatial_element.py +++ b/src/ifcsverchok/nodes/ifc/add_spatial_element.py @@ -180,7 +180,7 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h ifcopenshell.api.run( "spatial.unassign_container", self.file, - product=removed_element, + products=[removed_element], relating_object=result, ) for added_element in element_set - subelements: