mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Bonsai: short-circuit recreate_wall when no layer set
regenerate_wall_representation returns None for walls without an IfcMaterialLayerSet (the only mode it knows how to rebuild). Feeding None to switch_representation crashes deep in resolve_representation on .Items. Document the None return on the API side and bail in tool.Model.recreate_wall when it hits. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -3058,6 +3058,9 @@ class Model(bonsai.core.tool.Model):
|
||||
regenerate_fillet_corner_wall(element, obj)
|
||||
return
|
||||
rep = ifcopenshell.api.geometry.regenerate_wall_representation(tool.Ifc.get(), element)
|
||||
if rep is None:
|
||||
# Wall has no IfcMaterialLayerSet — layer-set rebuild not applicable.
|
||||
return
|
||||
bonsai.core.geometry.switch_representation(
|
||||
tool.Ifc,
|
||||
tool.Geometry,
|
||||
|
||||
@@ -83,3 +83,25 @@ def test_regenerate_wall_noops_when_obj_has_no_ifc_entity():
|
||||
recreate.assert_not_called()
|
||||
has_top.assert_not_called()
|
||||
regen.assert_not_called()
|
||||
|
||||
|
||||
def test_recreate_wall_noops_when_wall_has_no_layer_set():
|
||||
"""``recreate_wall`` must short-circuit when
|
||||
``regenerate_wall_representation`` returns ``None``. That API only knows
|
||||
how to rebuild ``IfcMaterialLayerSet`` walls; for walls without one it
|
||||
returns ``None``, and feeding ``None`` to ``switch_representation``
|
||||
crashes deep inside ``resolve_representation`` on ``.Items``."""
|
||||
element = Mock()
|
||||
obj = Mock()
|
||||
|
||||
with patch("bonsai.tool.model.tool.Parametric.is_fillet_corner_wall", return_value=False), patch(
|
||||
"bonsai.tool.model.tool.Ifc.get", return_value=Mock()
|
||||
), patch("bonsai.tool.model.ifcopenshell.api.geometry.regenerate_wall_representation", return_value=None), patch(
|
||||
"bonsai.tool.model.bonsai.core.geometry.switch_representation"
|
||||
) as switch, patch.object(
|
||||
tool.Geometry, "record_object_materials"
|
||||
) as record:
|
||||
tool.Model.recreate_wall(element, obj)
|
||||
|
||||
switch.assert_not_called()
|
||||
record.assert_not_called()
|
||||
|
||||
@@ -44,7 +44,7 @@ def regenerate_wall_representation(
|
||||
length: float = 1.0,
|
||||
height: float = 1.0,
|
||||
angle: Optional[float] = None,
|
||||
) -> ifcopenshell.entity_instance:
|
||||
) -> Optional[ifcopenshell.entity_instance]:
|
||||
"""
|
||||
Regenerate the body representation of a wall taking into account connections.
|
||||
|
||||
@@ -94,7 +94,10 @@ def regenerate_wall_representation(
|
||||
default height in SI units.
|
||||
:param angle: If the wall doesn't already have a slope, this is the default
|
||||
angle in radians. Left as none or 0 defines no slope.
|
||||
:return: The newly generated body IfcShapeRepresentation
|
||||
:return: The newly generated body IfcShapeRepresentation, or ``None`` if
|
||||
the wall has no ``IfcMaterialLayerSet`` (the layer-set rebuild is the
|
||||
only mode this function knows; without layers there is nothing to
|
||||
regenerate and callers should leave the existing representation alone).
|
||||
"""
|
||||
return Regenerator(file).regenerate(wall, length=length, height=height, angle=angle)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user