Fix space generation location and IFC2X3 B-rep

Two fixes for space generation:

1. IFC2X3 schema: build_brep_space now falls back to plain
   IfcRelSpaceBoundary because IfcRelSpaceBoundary1stLevel does not exist in
   IFC2X3.

2. Geometry location: set_space_representation_from_polygon now aligns the
   IFC ObjectPlacement with the Blender object, converts base_z/planes and
   the footprint polygon to the object's local coordinate system before
   building, and fixes the base_z unit scale. The centred-cube regeneration
   test was updated to check world bounds because the mesh is now placed
   relative to the object placement.

Generated with the assistance of an AI coding tool.
This commit is contained in:
CyrilWaechter
2026-08-03 18:37:21 +02:00
parent 332435416a
commit fb3cd09d6d
4 changed files with 93 additions and 11 deletions
@@ -565,8 +565,11 @@ def build_brep_space(
ifcopenshell.api.geometry.assign_representation(ifc_file, product=space, representation=seed_rep)
local_shapes = _build_local_shapes(ifc_file)
boundary_class = "IfcRelSpaceBoundary1stLevel"
if ifc_file.schema == "IFC2X3":
boundary_class = "IfcRelSpaceBoundary"
boundaries = ifcopenshell.util.boundary.auto_generate_boundaries(
ifc_file, space, local_shapes, boundary_class="IfcRelSpaceBoundary1stLevel"
ifc_file, space, local_shapes, boundary_class=boundary_class
)
if isinstance(boundaries, str) or not boundaries:
ifcopenshell.api.geometry.remove_representation(ifc_file, representation=seed_rep)
@@ -24,6 +24,7 @@ import ifcopenshell.util.shape
import ifcopenshell.util.space as subject
import math
import numpy as np
import os
import pytest
import shapely
import test.bootstrap
@@ -320,3 +321,24 @@ class TestBuildBrepSpace(test.bootstrap.IFC4):
item = subject.build_brep_space(self.file, space, shapes, shapely.box(-4, -4, 4, 4), 0.0)
assert item is not None
assert item.is_a("IfcFacetedBrep") or item.is_a("IfcPolygonalFaceSet")
class TestBuildBrepSpaceIfc2x3:
def test_build_brep_space_on_ifc2x3_uses_rel_space_boundary(self):
# IFC2X3 does not have IfcRelSpaceBoundary1stLevel; build_brep_space must
# fall back to plain IfcRelSpaceBoundary without raising a schema error.
# We use the real IFC2X3 fixture because the installed wrapper in this
# environment has a quirk with synthetic IFC2X3 geometry creation.
path = os.path.join(
os.path.dirname(__file__),
"..",
"IfcRelSpaceBoundary_TestFiles",
"IfcRelSpaceBoundary2ndLevel",
"HouseWithGarage_AC22_IFC2X3.ifc",
)
ifc_file = ifcopenshell.open(path)
space = ifc_file.by_type("IfcSpace")[0]
shapes = _build_shapes_dict(ifc_file, ifc_file.by_type("IfcWall") + ifc_file.by_type("IfcSlab"))
item = subject.build_brep_space(ifc_file, space, shapes, shapely.box(-1, -1, 1, 1), 0.0)
assert item is not None
assert item.is_a("IfcFacetedBrep") or item.is_a("IfcPolygonalFaceSet")