From b0246f76097b89813f9e32eae2cb01607d6f9afe Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Thu, 2 Apr 2026 21:09:53 -0500 Subject: [PATCH] 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. --- src/bonsai/bonsai/bim/module/root/operator.py | 9 ++++++++- src/bonsai/bonsai/bim/module/void/operator.py | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/bonsai/bonsai/bim/module/root/operator.py b/src/bonsai/bonsai/bim/module/root/operator.py index 159f157d44..3ab9d60efb 100644 --- a/src/bonsai/bonsai/bim/module/root/operator.py +++ b/src/bonsai/bonsai/bim/module/root/operator.py @@ -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) diff --git a/src/bonsai/bonsai/bim/module/void/operator.py b/src/bonsai/bonsai/bim/module/void/operator.py index 433ea3a06b..a3c80de072 100644 --- a/src/bonsai/bonsai/bim/module/void/operator.py +++ b/src/bonsai/bonsai/bim/module/void/operator.py @@ -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):