From d45fc0601db457fa0f4c4ba82459f363ca59ccd0 Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Mon, 16 Mar 2026 11:39:59 -0500 Subject: [PATCH] copy_representation: preserve MappedRepresentation structure for IfcTypeProduct Incorporates the per-map copy logic from build-0.8.5 that preserves nested MappedRepresentation structure instead of blindly using copy_deep, while retaining HasShapeAspects and StyledByItem handling from this branch. Co-Authored-By: Claude Sonnet 4.6 --- src/bonsai/bonsai/tool/root.py | 42 +++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/bonsai/bonsai/tool/root.py b/src/bonsai/bonsai/tool/root.py index e7d612ba73..ccc76b9526 100644 --- a/src/bonsai/bonsai/tool/root.py +++ b/src/bonsai/bonsai/tool/root.py @@ -124,17 +124,33 @@ class Root(bonsai.core.tool.Root): if not source.RepresentationMaps: return copied_entities - new_representation_maps = [] - for map in source.RepresentationMaps: - new_map = ifcopenshell.util.element.copy_deep( - tool.Ifc.get(), - map, - exclude=["IfcGeometricRepresentationContext"], - exclude_callback=exclude_callback, - copied_entities=copied_entities, - ) + # Copy representation maps while preserving mapped representation structures + new_maps = [] + for rep_map in source.RepresentationMaps: + source_rep = rep_map.MappedRepresentation - for aspect in map.HasShapeAspects: + # Copy the map itself + new_map = ifcopenshell.util.element.copy(tool.Ifc.get(), rep_map) + + # Handle the mapped representation - preserve mapping structure if present + if (source_rep.RepresentationType == 'MappedRepresentation' and + len(source_rep.Items) == 1 and + source_rep.Items[0].is_a("IfcMappedItem")): + # This is a mapped representation - preserve the structure + new_rep = ifcopenshell.util.element.copy(tool.Ifc.get(), source_rep) + new_rep.Items = [ifcopenshell.util.element.copy(tool.Ifc.get(), item) for item in source_rep.Items] + new_map.MappedRepresentation = new_rep + else: + # Not a mapped representation - use copy_deep as before + new_map.MappedRepresentation = ifcopenshell.util.element.copy_deep( + tool.Ifc.get(), + source_rep, + exclude=["IfcGeometricRepresentationContext"], + exclude_callback=exclude_callback, + copied_entities=copied_entities, + ) + + for aspect in rep_map.HasShapeAspects: ifcopenshell.util.element.copy_deep( tool.Ifc.get(), aspect, @@ -143,15 +159,15 @@ class Root(bonsai.core.tool.Root): copied_entities=copied_entities, ) - for item in map.MappedRepresentation.Items: + for item in rep_map.MappedRepresentation.Items: if item.StyledByItem: for styled_by in item.StyledByItem: new_styled_by = ifcopenshell.util.element.copy(tool.Ifc.get(), styled_by) new_styled_by.Item = copied_entities[styled_by.Item.id()] copied_entities[styled_by.id()] = new_styled_by - new_representation_maps.append(new_map) - dest.RepresentationMaps = new_representation_maps + new_maps.append(new_map) + dest.RepresentationMaps = new_maps return copied_entities @classmethod