extending a2a5780d59: Reuse opening if mapped.

This commit is contained in:
Ryan Schultz
2025-12-27 09:23:33 -06:00
parent bc6209ad91
commit 7fcdec0a4c
+78 -22
View File
@@ -133,6 +133,7 @@ class FilledOpeningGenerator:
existing_opening_occurrence = self.get_existing_opening_occurrence_if_any(filling)
# CREATE THE OPENING FIRST
opening = ifcopenshell.api.root.create_entity(
tool.Ifc.get(),
ifc_class="IfcOpeningElement",
@@ -146,25 +147,31 @@ class FilledOpeningGenerator:
is_si=True,
)
# NOW HANDLE REPRESENTATION
# Variables to track if we should reuse a mapped representation
reuse_mapped_representation = False
existing_mapping_source = None
representation = None
if existing_opening_occurrence:
representation = ifcopenshell.util.representation.get_representation(
existing_opening_occurrence, "Model", "Body", "MODEL_VIEW"
)
assert representation
# Check if mapped representation - preserve it
# Check if mapped representation - PRESERVE the mapping structure
if (
representation.RepresentationType == "MappedRepresentation"
and len(representation.Items) == 1
and representation.Items[0].is_a("IfcMappedItem")
):
source_rep = representation.Items[0].MappingSource.MappedRepresentation
representation = ifcopenshell.util.element.copy_deep(
tool.Ifc.get(), source_rep, exclude=["IfcGeometricRepresentationContext"]
)
# Store the existing RepresentationMap to reuse it
existing_mapping_source = representation.Items[0].MappingSource
reuse_mapped_representation = True
else:
representation = ifcopenshell.util.representation.resolve_representation(representation)
else:
if not reuse_mapped_representation:
# Check for library template before generating from filling
template_rep = self.get_opening_template_from_type(filling)
@@ -175,9 +182,34 @@ class FilledOpeningGenerator:
filling, filling_obj, opening_thickness_si=opening_thickness_si
)
mapped_representation = ifcopenshell.api.geometry.map_representation(
tool.Ifc.get(), representation=representation
)
# Create mapped representation
if reuse_mapped_representation:
# Reuse the existing RepresentationMap - don't create a new one!
context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
new_mapped_item = tool.Ifc.get().create_entity(
"IfcMappedItem",
MappingSource=existing_mapping_source,
MappingTarget=tool.Ifc.get().create_entity(
"IfcCartesianTransformationOperator3D",
Axis1=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(1., 0., 0.)),
Axis2=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0., 1., 0.)),
LocalOrigin=tool.Ifc.get().create_entity("IfcCartesianPoint", Coordinates=(0., 0., 0.)),
Scale=1.,
Axis3=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0., 0., 1.))
)
)
mapped_representation = tool.Ifc.get().create_entity(
"IfcShapeRepresentation",
ContextOfItems=context,
RepresentationIdentifier="Body",
RepresentationType="MappedRepresentation",
Items=[new_mapped_item]
)
else:
mapped_representation = ifcopenshell.api.geometry.map_representation(
tool.Ifc.get(), representation=representation
)
ifcopenshell.api.geometry.assign_representation(
tool.Ifc.get(), product=opening, representation=mapped_representation
)
@@ -249,12 +281,14 @@ class FilledOpeningGenerator:
existing_opening_occurrence = self.get_existing_opening_occurrence_if_any(filling)
# Priority order for choosing representation:
# 1. Existing occurrence with Tessellation (best quality)
# 1. Existing occurrence with MappedRepresentation (preserve mapping!)
# 2. Library template with Tessellation
# 3. Preserved representation from old opening (maintain user's work)
# 4. Generate from filling (last resort)
representation_to_use = None
reuse_mapped_representation = False
existing_mapping_source = None
if existing_opening_occurrence:
representation = ifcopenshell.util.representation.get_representation(
@@ -267,24 +301,21 @@ class FilledOpeningGenerator:
and len(representation.Items) == 1
and representation.Items[0].is_a("IfcMappedItem")
):
source_rep = representation.Items[0].MappingSource.MappedRepresentation
# Prefer Tessellation from existing occurrence over preserved representation
if source_rep.RepresentationType == "Tessellation":
representation_to_use = ifcopenshell.util.element.copy_deep(
tool.Ifc.get(), source_rep, exclude=["IfcGeometricRepresentationContext"]
)
# PRESERVE the mapped structure - reuse the same RepresentationMap
existing_mapping_source = representation.Items[0].MappingSource
reuse_mapped_representation = True
else:
representation_to_use = ifcopenshell.util.representation.resolve_representation(representation)
if not representation_to_use:
if not representation_to_use and not reuse_mapped_representation:
template_rep = self.get_opening_template_from_type(filling)
if template_rep and template_rep.RepresentationType == "Tessellation":
representation_to_use = template_rep
if not representation_to_use and preserved_representation:
if not representation_to_use and not reuse_mapped_representation and preserved_representation:
representation_to_use = preserved_representation
if not representation_to_use:
if not representation_to_use and not reuse_mapped_representation:
opening_obj = tool.Ifc.get_object(opening)
if opening_obj:
tool.Ifc.unlink(element=opening)
@@ -293,9 +324,34 @@ class FilledOpeningGenerator:
filling_obj = tool.Ifc.get_object(filling)
representation_to_use = self.generate_opening_from_filling(filling, filling_obj)
mapped_representation = ifcopenshell.api.geometry.map_representation(
tool.Ifc.get(), representation=representation_to_use
)
# Create the mapped representation
if reuse_mapped_representation:
# Reuse existing RepresentationMap - don't create a new one!
context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
new_mapped_item = tool.Ifc.get().create_entity(
"IfcMappedItem",
MappingSource=existing_mapping_source,
MappingTarget=tool.Ifc.get().create_entity(
"IfcCartesianTransformationOperator3D",
Axis1=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(1., 0., 0.)),
Axis2=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0., 1., 0.)),
LocalOrigin=tool.Ifc.get().create_entity("IfcCartesianPoint", Coordinates=(0., 0., 0.)),
Scale=1.,
Axis3=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0., 0., 1.))
)
)
mapped_representation = tool.Ifc.get().create_entity(
"IfcShapeRepresentation",
ContextOfItems=context,
RepresentationIdentifier="Body",
RepresentationType="MappedRepresentation",
Items=[new_mapped_item]
)
else:
mapped_representation = ifcopenshell.api.geometry.map_representation(
tool.Ifc.get(), representation=representation_to_use
)
ifcopenshell.api.geometry.assign_representation(
tool.Ifc.get(), product=opening, representation=mapped_representation
)