mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
8c434b7167
replace_attribute() rewrites references inside aggregate attributes via element.walk(), but never checked whether the replacement value was already present elsewhere in the same aggregate. For an EXPRESS SET (e.g. IfcProject.RepresentationContexts, IfcRelAggregates.RelatedObjects) this can leave the same reference listed twice, which is invalid IFC. LIST and BAG aggregates legitimately allow duplicates, so a blanket dedup would be wrong; only SET-typed attributes are deduplicated, determined at runtime from the schema declaration (IfcOpenShell#8706 review comment). The SET/LIST/BAG check is cached per (schema, class, attribute index), and the dedup pass itself only runs when a cheap linear pre-check finds the replacement value already present in the aggregate, so the common case (no duplicate produced) pays only that pre-check, not a hash-set rebuild. Benchmarked against a 23MB (431k entities) and a 104MB (2.4M entities) IFC model against a large SET attribute: worst case adds well under 1ms per call; the realistic case (merging duplicate contexts, matching the PR #8706 scenario) shows no measurable regression. Fixes the root cause flagged in IfcOpenShell#8706 (Moult), obviating the need for MergeDuplicateContexts' own manual aggregate-dedup pass for that scenario. Generated with the assistance of an AI coding tool.
ifcopenshell-python
Python bindings, utility functions, and high-level API for IfcOpenShell.