remove_representation - optimizations

1) `do_not_delete` performs best when it's set
2) also_consider when `element` related elements go first, so there will be no need to traverse all other elements to see if they cover `element`'s inverses.
This commit is contained in:
Andrej730
2025-02-21 15:54:58 +05:00
parent 6e20ee9fea
commit f7efbe5924
2 changed files with 15 additions and 6 deletions
@@ -39,7 +39,8 @@ def remove_representation(
"""
is_ifc2x3 = file.schema == "IFC2X3"
styled_items = set()
presentation_layer_assignments = set()
presentation_layer_assignments_items: set[ifcopenshell.entity_instance] = set()
presentation_layer_assignments_reps: set[ifcopenshell.entity_instance] = set()
textures = set()
colours = set()
named_profiles = set()
@@ -48,13 +49,13 @@ def remove_representation(
[styled_items.add(s) for s in subelement.StyledByItem or []]
# IFC2X3 is using LayerAssignments
for s in subelement.LayerAssignment if not is_ifc2x3 else subelement.LayerAssignments:
presentation_layer_assignments.add(s)
presentation_layer_assignments_items.add(s)
# IfcTessellatedFaceSet inverses
[textures.add(t) for t in getattr(subelement, "HasTextures", []) or []]
[colours.add(t) for t in getattr(subelement, "HasColours", []) or []]
elif subelement.is_a("IfcRepresentation"):
for layer in subelement.LayerAssignments:
presentation_layer_assignments.add(layer)
presentation_layer_assignments_reps.add(layer)
elif subelement.is_a("IfcProfileDef") and subelement.ProfileName:
named_profiles.add(subelement)
@@ -62,11 +63,16 @@ def remove_representation(
if should_keep_named_profiles:
do_not_delete += named_profiles
# Order matters - layer assignments may reference representation directly.
also_consider = list(presentation_layer_assignments_reps)
also_consider.extend(presentation_layer_assignments_items - presentation_layer_assignments_reps)
also_consider.extend(styled_items)
also_consider.extend(textures)
ifcopenshell.util.element.remove_deep2(
file,
representation,
also_consider=list(styled_items | presentation_layer_assignments | colours),
do_not_delete=do_not_delete,
also_consider=also_consider,
do_not_delete=set(do_not_delete),
)
for texture in textures:
@@ -79,6 +85,7 @@ def remove_representation(
item = element.Item
if not item or item in to_delete:
file.remove(element)
presentation_layer_assignments = presentation_layer_assignments_reps | presentation_layer_assignments_items
for element in presentation_layer_assignments:
if all(item in to_delete for item in element.AssignedItems):
file.remove(element)
@@ -1434,7 +1434,7 @@ def remove_deep2(
ifc_file: ifcopenshell.file,
element: ifcopenshell.entity_instance,
also_consider: list[ifcopenshell.entity_instance] = [],
do_not_delete: list[ifcopenshell.entity_instance] = [],
do_not_delete: set[ifcopenshell.entity_instance] = set(),
) -> None:
"""Recursively purges a subgraph safely, starting at an element
@@ -1462,6 +1462,8 @@ def remove_deep2(
:param ifc_file: The IFC file object
:param also_consider: elements to also consider as a part of a subgraph
Order could matter for perfomance - elements that reference `element`
directly should go first for the better performance.
:param do_not_delete: elements to protect from deletion
:param element: The starting element that defines the subgraph
"""