Compare commits

...

1 Commits

Author SHA1 Message Date
Petru Conduraru 0593a84d34 Bonsai: let standalone IfcCurtainWall bound spaces and boundaries
brunopostle reported that a curtain wall used as a standalone room side
(not decomposed into IfcMember/IfcPlate children) was invisible to
space/boundary generation, since only IfcWall, IfcColumn, IfcMember,
IfcVirtualElement, and IfcPlate were treated as bounding classes.
CyrilWaechter concretely proposed adding curtain wall to that
detection list, while explicitly leaving structural elements (a
separate, still-open design question) alone.

IfcCurtainWall is not a schema subtype of IfcWall, so it was silently
skipped by every class list that checked "is this a wall/column/etc."
Three separate lists needed it:

- tool.Spatial.is_bounding_class, used by "Generate Space" (cursor
  cutting-plane detection).
- tool.Spatial.get_boundary_elements, used by "Generate Spaces From
  Walls" (bulk perimeter detection).
- AddBoundary.auto_generate_boundaries' building_elements gather, used
  by "Add Boundary" when auto-detecting nearby elements for a single
  selected IfcSpace.

The separate manual AddBoundary path (selecting an IfcSpace plus one
IfcElement directly) was already class-agnostic and did not need a
change; verified live that it already creates a boundary against an
IfcCurtainWall today.

Verified live in headless Blender: a synthetic 4m x 4m room with 3
IfcWalls and one standalone IfcCurtainWall (single object, not
aggregated into members/plates) produced 0 spaces via "Generate
Spaces From Walls" before this fix, and 1 correctly-bounded space
after. The manual "Add Boundary" (IfcSpace + IfcCurtainWall selected)
path created an IfcRelSpaceBoundary against the curtain wall both
before and after, confirming it needed no change.

IfcWindow remains untouched; CyrilWaechter was explicit that
whether to auto-detect standalone windows/structural elements is a
separate, unresolved design question.

Fixes #3995

Generated with the assistance of an AI coding tool.
2026-07-16 18:26:22 +03:00
2 changed files with 3 additions and 2 deletions
@@ -682,6 +682,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
tool.Ifc.get().by_type("IfcWall")
+ tool.Ifc.get().by_type("IfcSlab")
+ tool.Ifc.get().by_type("IfcVirtualElement")
+ tool.Ifc.get().by_type("IfcCurtainWall")
)
for building_element in building_elements:
+2 -2
View File
@@ -755,7 +755,7 @@ class Spatial(bonsai.core.tool.Spatial):
@classmethod
def is_bounding_class(cls, visible_element: ifcopenshell.entity_instance) -> bool:
for ifc_class in ["IfcWall", "IfcColumn", "IfcMember", "IfcVirtualElement", "IfcPlate"]:
for ifc_class in ["IfcWall", "IfcColumn", "IfcMember", "IfcVirtualElement", "IfcPlate", "IfcCurtainWall"]:
if visible_element.is_a(ifc_class):
return True
return False
@@ -936,7 +936,7 @@ class Spatial(bonsai.core.tool.Spatial):
boundary_elements = []
for obj in selected_objects:
subelement = tool.Ifc.get_entity(obj)
if subelement.is_a("IfcWall") or subelement.is_a("IfcColumn"):
if subelement.is_a("IfcWall") or subelement.is_a("IfcColumn") or subelement.is_a("IfcCurtainWall"):
boundary_elements.append(subelement)
return boundary_elements