From 02a68f6827398e3e9b823c58d284974849ca1f23 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 17 Sep 2021 15:40:27 +1000 Subject: [PATCH] New utility to get spatial and object decompositions from any IFC element --- .../ifcopenshell/util/element.py | 14 ++++++++++++++ src/ifcopenshell-python/test/util/test_element.py | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index b21a58a7ce..a2167770a2 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -86,6 +86,20 @@ def get_container(element): return element.ContainedInStructure[0].RelatingStructure +def get_decomposition(element): + queue = [element] + results = [] + while queue: + element = queue.pop() + for rel in getattr(element, "ContainsElements", []): + queue.extend(rel.RelatedElements) + results.extend(rel.RelatedElements) + for rel in getattr(element, "IsDecomposedBy", []): + queue.extend(rel.RelatedObjects) + results.extend(rel.RelatedObjects) + return results + + def get_aggregate(element): if hasattr(element, "Decomposes") and element.Decomposes: return element.Decomposes[0].RelatingObject diff --git a/src/ifcopenshell-python/test/util/test_element.py b/src/ifcopenshell-python/test/util/test_element.py index facfdd8093..f2c1dd5f33 100644 --- a/src/ifcopenshell-python/test/util/test_element.py +++ b/src/ifcopenshell-python/test/util/test_element.py @@ -174,6 +174,18 @@ class TestGetContainerIFC4(test.bootstrap.IFC4): assert ifcopenshell.util.element.get_container(subelement) == building +class TestGetDecompositionIFC4(test.bootstrap.IFC4): + def test_getting_decomposed_subelements_of_an_element(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") + building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") + ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) + ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) + results = ifcopenshell.util.element.get_decomposition(building) + assert element in results + assert subelement in results + + class TestGetAggregateIFC4(test.bootstrap.IFC4): def test_getting_the_containing_aggregate_of_a_subelement(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")