mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 10:57:49 +00:00
ifcopenshell: attach owning file to geom.tree select results #3189
tree.select and tree.select_box wrapped their C++ results as entity_instance(e) with no file, so wrapped_data.file was None. That forces entity_instance.__eq__ down the slow recursive get_info_2 attribute comparison instead of the fast step-id path, and drops the gc-keepalive the file reference provides. The underlying instances carry a valid file_pointer(), so resolve the owning file via file.from_pointer() and attach it to each result. Verified with the compiled wrapper on basic.ifc: before, wrapped_data.file is None and equality takes the slow path (2 get_info_2 calls); after, the file is attached, equality/hash use the fast path (0 slow calls), for both select and select_box. Generated with the assistance of an AI coding tool. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -370,6 +370,17 @@ CLASH_TYPE_ITEMS = ("protrusion", "pierce", "collision", "clearance")
|
||||
|
||||
|
||||
class tree(ifcopenshell_wrapper.tree):
|
||||
@staticmethod
|
||||
def _wrap(e: ifcopenshell_wrapper.entity_instance) -> entity_instance:
|
||||
inst = entity_instance(e)
|
||||
# #3189 attach the owning file so that equality and hashing of
|
||||
# selected instances use the fast step-id based path instead of
|
||||
# falling back to a slow recursive attribute comparison.
|
||||
ptr = e.file_pointer()
|
||||
if ptr:
|
||||
inst.wrapped_data.file = file.from_pointer(ptr)
|
||||
return inst
|
||||
|
||||
def __init__(self, file: Optional[file] = None, settings: Optional[settings] = None):
|
||||
args = [self]
|
||||
if file is not None:
|
||||
@@ -412,7 +423,7 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
args.append(kwargs.get("completely_within", False))
|
||||
if "extend" in kwargs:
|
||||
args.append(kwargs["extend"])
|
||||
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select(*args)]
|
||||
return [self._wrap(e) for e in ifcopenshell_wrapper.tree.select(*args)]
|
||||
|
||||
def select_box(self, value, **kwargs) -> list[entity_instance]:
|
||||
def unwrap(value):
|
||||
@@ -427,7 +438,7 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
args.append(kwargs.get("completely_within", False))
|
||||
if "extend" in kwargs:
|
||||
args.append(kwargs.get("extend", -1.0e-5))
|
||||
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select_box(*args)]
|
||||
return [self._wrap(e) for e in ifcopenshell_wrapper.tree.select_box(*args)]
|
||||
|
||||
def clash_intersection_many(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user