mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 10:51:13 +00:00
Deduplicate opening boundaries in auto_generate_boundaries
When a building element has multiple ngons matching the same space face, _process_openings was called multiple times for the same opening/filling, producing duplicate boundaries (e.g. two boundaries for the same door). Fix: pass a set of processed filling IDs to _process_openings and skip already-processed openings. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -108,6 +108,7 @@ def auto_generate_boundaries(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Compare space faces and building element faces
|
# Compare space faces and building element faces
|
||||||
|
processed_fillings: set[int] = set()
|
||||||
for space_ngon in space_ngons:
|
for space_ngon in space_ngons:
|
||||||
space_verts_l = space_verts_local[space_ngon]
|
space_verts_l = space_verts_local[space_ngon]
|
||||||
# Normal from local verts, then transform to world via space placement
|
# Normal from local verts, then transform to world via space placement
|
||||||
@@ -224,6 +225,7 @@ def auto_generate_boundaries(
|
|||||||
parent_boundary,
|
parent_boundary,
|
||||||
space,
|
space,
|
||||||
unit_scale,
|
unit_scale,
|
||||||
|
processed_fillings,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -243,6 +245,7 @@ def _process_openings(
|
|||||||
parent_boundary,
|
parent_boundary,
|
||||||
space,
|
space,
|
||||||
unit_scale,
|
unit_scale,
|
||||||
|
processed_fillings: set[int],
|
||||||
):
|
):
|
||||||
"""Process openings and fillings for a building element.
|
"""Process openings and fillings for a building element.
|
||||||
|
|
||||||
@@ -251,12 +254,16 @@ def _process_openings(
|
|||||||
:param element_matrix: The building element placement matrix.
|
:param element_matrix: The building element placement matrix.
|
||||||
:param face_matrix: The face matrix in space-local coordinates (for connection geometry).
|
:param face_matrix: The face matrix in space-local coordinates (for connection geometry).
|
||||||
:param face_matrix_inv: The inverse face matrix (for 2D projection).
|
:param face_matrix_inv: The inverse face matrix (for 2D projection).
|
||||||
|
:param processed_fillings: Set of element IDs that already have opening boundaries.
|
||||||
"""
|
"""
|
||||||
boundaries = []
|
boundaries = []
|
||||||
|
|
||||||
for rel in getattr(building_element, "HasOpenings", []):
|
for rel in getattr(building_element, "HasOpenings", []):
|
||||||
opening = rel.RelatedOpeningElement
|
opening = rel.RelatedOpeningElement
|
||||||
filling = opening.HasFillings[0].RelatedBuildingElement if opening.HasFillings else None
|
filling = opening.HasFillings[0].RelatedBuildingElement if opening.HasFillings else None
|
||||||
|
filling_id = (filling or opening).id()
|
||||||
|
if filling_id in processed_fillings:
|
||||||
|
continue
|
||||||
|
|
||||||
settings = ifcopenshell.geom.settings()
|
settings = ifcopenshell.geom.settings()
|
||||||
try:
|
try:
|
||||||
@@ -317,6 +324,7 @@ def _process_openings(
|
|||||||
if boundary.is_a() != "IfcRelSpaceBoundary":
|
if boundary.is_a() != "IfcRelSpaceBoundary":
|
||||||
boundary.ParentBoundary = parent_boundary
|
boundary.ParentBoundary = parent_boundary
|
||||||
_set_boundary_name(boundary)
|
_set_boundary_name(boundary)
|
||||||
|
processed_fillings.add(filling_id)
|
||||||
boundaries.append(boundary)
|
boundaries.append(boundary)
|
||||||
|
|
||||||
return boundaries
|
return boundaries
|
||||||
|
|||||||
Reference in New Issue
Block a user