Fix IfcOpeningElement using wrong geometry context

When creating an IfcOpeningElement via AddElement, the context
was read from props.contexts which could accidentally or intentionally through previous operation be set to
IfcGeometricRepresentationContext ("Model") rather than the
Body subcontext ("Model/Body/MODEL_VIEW"). The boolean engine
only searches subcontexts for opening geometry, so the void
was silently never applied.

Fix: always resolve Model/Body/MODEL_VIEW directly from the
IFC file when the class is IfcOpeningElement, bypassing the
context dropdown entirely.

Also add warnings in AddOpening when the opening has no Body
representation, and when switch_representation produces no
IfcBooleanResult after the opening is applied.

Generated with the assistance of an AI coding tool.
This commit is contained in:
Ryan Schultz
2026-04-02 21:09:53 -05:00
parent 256d5a63f1
commit b0246f7609
2 changed files with 16 additions and 1 deletions
@@ -27,6 +27,7 @@ import ifcopenshell.api.material
import ifcopenshell.api.pset
import ifcopenshell.api.root
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.schema
import ifcopenshell.util.shape_builder
import ifcopenshell.util.type
@@ -530,7 +531,13 @@ class AddElement(bpy.types.Operator, tool.Ifc.Operator):
return self.report({"WARNING"}, "A featured element must be nominated.")
ifc_context = None
if get_enum_items(props, "contexts", context):
if props.ifc_class == "IfcOpeningElement":
ifc_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
if ifc_context is None:
ifc_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body")
if ifc_context is None:
self.report({"WARNING"}, "No Model/Body context found. Opening representation may be on the wrong context.")
elif get_enum_items(props, "contexts", context):
ifc_context = int(props.contexts or "0") or None
if ifc_context:
ifc_context = tool.Ifc.get().by_id(ifc_context)
@@ -156,6 +156,14 @@ class AddOpening(bpy.types.Operator, tool.Ifc.Operator):
should_add_representation=True,
context=body_context,
)
if element2:
opening_body_rep = ifcopenshell.util.representation.get_representation(element2, "Model", "Body")
if opening_body_rep is None:
self.report(
{"WARNING"},
f"Opening '{element2.Name}' has no Body representation — void will not be cut. "
f"Check its context in the IFC file (ContextIdentifier must be 'Body').",
)
ifcopenshell.api.feature.add_feature(tool.Ifc.get(), feature=element2, element=element1)
if tool.Ifc.is_moved(obj2):