From 229c7285c220d78cb6bb8cd50e8e5a8045652489 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 20 Nov 2023 16:57:19 +1100 Subject: [PATCH] Add support for loading nested elements and consider nesting for indirect spatial containment. --- src/blenderbim/blenderbim/bim/import_ifc.py | 13 +++++++++-- src/blenderbim/blenderbim/tool/collector.py | 8 +++++++ .../ifcopenshell/util/element.py | 22 ++++++++++++++++++- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index a5d53fdef0..f6da9fc310 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -1537,7 +1537,7 @@ class IfcImporter: def create_collections(self): self.create_spatial_decomposition_collections() if self.ifc_import_settings.collection_mode == "DECOMPOSITION": - self.create_aggregate_collections() + self.create_aggregate_and_nest_collections() elif self.ifc_import_settings.collection_mode == "SPATIAL_DECOMPOSITION": pass @@ -1573,16 +1573,22 @@ class IfcImporter: for rel_aggregate in element.IsDecomposedBy: self.create_spatial_decomposition_collection(collection, rel_aggregate.RelatedObjects) - def create_aggregate_collections(self): + def create_aggregate_and_nest_collections(self): if self.ifc_import_settings.has_filter: rel_aggregates = [e.IsDecomposedBy[0] for e in self.elements if e.IsDecomposedBy] rel_aggregates += [e.Decomposes[0] for e in self.elements if e.Decomposes] + rel_aggregates += [e.IsNestedBy[0] for e in self.elements if e.IsNestedBy] + rel_aggregates += [e.Nests[0] for e in self.elements if e.Nests] rel_aggregates = set(rel_aggregates) else: rel_aggregates = [ a for a in self.file.by_type("IfcRelAggregates") if a.RelatingObject.is_a("IfcElement") or a.RelatingObject.is_a("IfcElementType") + ] + [ + a + for a in self.file.by_type("IfcRelNests") + if a.RelatingObject.is_a("IfcElement") or a.RelatingObject.is_a("IfcElementType") ] if len(rel_aggregates) > 10000: @@ -1687,6 +1693,9 @@ class IfcImporter: elif getattr(element, "Decomposes", None): aggregate = ifcopenshell.util.element.get_aggregate(element) return self.collections[aggregate.GlobalId].objects.link(obj) + elif getattr(element, "Nests", None): + nest = ifcopenshell.util.element.get_nest(element) + return self.collections[nest.GlobalId].objects.link(obj) else: return self.place_object_in_spatial_decomposition_collection(element, obj) diff --git a/src/blenderbim/blenderbim/tool/collector.py b/src/blenderbim/blenderbim/tool/collector.py index 3bf150ae93..4d9a4b2705 100644 --- a/src/blenderbim/blenderbim/tool/collector.py +++ b/src/blenderbim/blenderbim/tool/collector.py @@ -199,6 +199,14 @@ class Collector(blenderbim.core.tool.Collector): if collection: return collection + nest = ifcopenshell.util.element.get_nest(element) + if nest: + nest_obj = tool.Ifc.get_object(nest) + if nest_obj: + collection = nest_obj.BIMObjectProperties.collection + if collection: + return collection + container = ifcopenshell.util.element.get_container(element) if container: container_obj = tool.Ifc.get_object(container) diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index 11d222d318..ca9ee2665d 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -691,6 +691,9 @@ def get_container(element, should_get_direct=False, ifc_class=None): aggregate = get_aggregate(element) if aggregate: return get_container(aggregate, should_get_direct) + nest = get_nest(element) + if nest: + return get_container(nest, should_get_direct) if hasattr(element, "ContainedInStructure") and element.ContainedInStructure: container = element.ContainedInStructure[0].RelatingStructure if not ifc_class: @@ -790,7 +793,7 @@ def get_grouped_by(element): def get_aggregate(element): """ - Retrieves the aggregate of an element. + Retrieves the aggregate parent of an element. :param element: The IFC element :return: The aggregate of the element @@ -805,6 +808,23 @@ def get_aggregate(element): return element.Decomposes[0].RelatingObject +def get_nest(element): + """ + Retrieves the nest parent of an element. + + :param element: The IFC element + :return: The nested whole of the element + + Example: + + .. code:: python + element = file.by_type("IfcBeam")[0] + aggregate = ifcopenshell.util.element.get_nest(element) + """ + if hasattr(element, "Nests") and element.Nests: + return element.Nests[0].RelatingObject + + def get_parts(element): """ Retrieves the parts of an element.