From 9147938c363b1427695e61cd45090003dc6f3d3b Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 14 Jan 2026 13:59:07 +0100 Subject: [PATCH] Aggregate data types --- .../api/geometry/remove_representation.py | 6 +++--- .../ifcopenshell/api/project/append_asset.py | 11 ++++++----- src/ifcopenshell-python/ifcopenshell/util/element.py | 9 +++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/remove_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/remove_representation.py index 6262060fa7..fa96768679 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/remove_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/remove_representation.py @@ -60,9 +60,9 @@ def remove_representation( elif subelement.is_a("IfcProfileDef") and subelement.ProfileName: named_profiles.add(subelement) - do_not_delete = file.by_type("IfcGeometricRepresentationContext") + do_not_delete = set(file.by_type("IfcGeometricRepresentationContext")) if should_keep_named_profiles: - do_not_delete += named_profiles + do_not_delete |= named_profiles # Order matters - layer assignments may reference representation directly. also_consider = list(presentation_layer_assignments_reps) @@ -73,7 +73,7 @@ def remove_representation( file, representation, also_consider=also_consider, - do_not_delete=set(do_not_delete), + do_not_delete=do_not_delete, ) for texture in textures: diff --git a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py index 0951aba498..bd96bf7135 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +from collections import deque import ifcopenshell import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.api.geometry @@ -302,7 +303,7 @@ class Usecase: self.whitelisted_inverse_attributes = { "IfcMaterial": ["HasExternalReferences", "HasProperties", "HasRepresentation"] } - self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext") + self.existing_contexts = list(self.file.by_type("IfcGeometricRepresentationContext")) element = self.add_element(self.settings["element"]) if element.HasRepresentation: self.reuse_existing_contexts() @@ -329,7 +330,7 @@ class Usecase: "IfcProductDefinitionShape": ["HasShapeAspects"], "IfcRepresentationMap": ["HasShapeAspects"], } - self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext") + self.existing_contexts = list(self.file.by_type("IfcGeometricRepresentationContext")) element = self.add_element(self.settings["element"]) self.reuse_existing_contexts() return element @@ -348,7 +349,7 @@ class Usecase: "IfcProductDefinitionShape": ["HasShapeAspects"], "IfcRepresentationMap": ["HasShapeAspects"], } - self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext") + self.existing_contexts = list(self.file.by_type("IfcGeometricRepresentationContext")) element = self.add_element(self.settings["element"]) self.reuse_existing_contexts() @@ -390,9 +391,9 @@ class Usecase: new = self.file_add(element) self.added_elements[element.id()] = new self.check_inverses(element) - subelement_queue = self.settings["library"].traverse(element, max_levels=1)[1:] + subelement_queue = deque(self.settings["library"].traverse(element, max_levels=1)[1:]) while subelement_queue: - subelement = subelement_queue.pop(0) + subelement = subelement_queue.popleft() existing_element = self.get_existing_element(subelement) if existing_element: self.added_elements[subelement.id()] = existing_element diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index 067febd115..7bcce39171 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -22,7 +22,7 @@ import ifcopenshell.util.element import ifcopenshell.util.representation from typing import Any, Callable, Optional, Union, Literal, overload from collections.abc import Generator, Sequence -from collections import namedtuple +from collections import deque, namedtuple MATERIAL_TYPE = Literal[ @@ -958,7 +958,7 @@ def get_elements_by_profile(profile: ifcopenshell.entity_instance) -> set[ifcope :return: The elements using the profile. """ ifc_file = profile.file - queue = ifc_file.get_inverse(profile) + queue = list(ifc_file.get_inverse(profile)) processed: set[ifcopenshell.entity_instance] = set() representations: set[ifcopenshell.entity_instance] = set() while queue: @@ -1661,14 +1661,14 @@ def remove_deep2( subgraph = list(ifc_file.traverse(element, breadth_first=True)) subgraph.extend(also_consider) subgraph_set = set(subgraph) - subelement_queue = [element] + subelement_queue = deque([element]) # Cache already processed entities to avoid traversing them multiple time. # E.g. lots of IFCINDEXEDPOLYCURVES may reference the same IFCCARTESIANPOINTLIST2D. processed_ids: set[int] = set() while subelement_queue: - subelement = subelement_queue.pop(0) + subelement = subelement_queue.popleft() subelement_id = subelement.id() if ( subelement_id @@ -1703,6 +1703,7 @@ def remove_deep2( # We delete elements from subgraph in reverse order to allow batching to work for subelement in filter(lambda e: e in to_delete, subgraph[::-1]): + to_delete.remove(subelement) ifc_file.remove(subelement) # ifc_file.unbatch()