Handle slab arc segments for wall generation

This commit is contained in:
copilot-swe-agent[bot]
2026-07-02 21:38:16 +00:00
committed by GitHub
parent 6d3bed1f7d
commit 0a9d709111
+56 -4
View File
@@ -1297,6 +1297,51 @@ class DumbWallGenerator:
walls.append(self.create_wall_from_2_points(coords))
return walls, is_polyline_closed
def _curve_has_arc_segments(self, curve: ifcopenshell.entity_instance) -> bool:
if not curve.is_a("IfcIndexedPolyCurve"):
return False
segments = getattr(curve, "Segments", None) or ()
for segment in segments:
if (hasattr(segment, "is_a") and segment.is_a("IfcArcIndex")) or len(segment[0]) == 3:
return True
return False
def _world_xy_point(self, slab_obj: bpy.types.Object, elevation: float, coord: Any) -> Vector:
return slab_obj.matrix_world @ Vector((coord[0] * self.unit_scale, coord[1] * self.unit_scale, elevation))
def _derive_points_from_arc_segments(
self, slab_obj: bpy.types.Object, elevation: float, curve: ifcopenshell.entity_instance
) -> list[Vector]:
points: list[Vector] = []
coord_list = curve.Points.CoordList
arc_resolution = 24
precision = 1e-6
def append_point(point: Vector) -> None:
if points and (points[-1] - point).length < precision:
return
points.append(point)
for segment in curve.Segments:
segment_indices = [i - 1 for i in segment[0]]
if len(segment_indices) == 3:
p1 = self._world_xy_point(slab_obj, elevation, coord_list[segment_indices[0]])
p2 = self._world_xy_point(slab_obj, elevation, coord_list[segment_indices[1]])
p3 = self._world_xy_point(slab_obj, elevation, coord_list[segment_indices[2]])
arc_points, _ = tool.Cad.create_arc_segments([p1, p2, p3], num_verts=arc_resolution + 1)
arc_points = [Vector(arc_point) for arc_point in arc_points]
if arc_points and (arc_points[0] - p1).length > (arc_points[-1] - p1).length:
arc_points.reverse()
for arc_point in arc_points:
append_point(arc_point)
elif len(segment_indices) >= 2:
append_point(self._world_xy_point(slab_obj, elevation, coord_list[segment_indices[0]]))
append_point(self._world_xy_point(slab_obj, elevation, coord_list[segment_indices[1]]))
if points and (points[0] - points[-1]).length >= precision:
points.append(points[0].copy())
return points
def derive_from_slab(self):
slab_obj = bpy.context.active_object
slab = tool.Ifc.get_entity(slab_obj)
@@ -1305,10 +1350,17 @@ class DumbWallGenerator:
elevation = self.container_obj.location.z
representation = ifcopenshell.util.representation.get_representation(slab, "Model", "Body", "MODEL_VIEW")
extrusion = tool.Model.get_extrusion(representation)
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
polyline_points = builder.get_polyline_coords(extrusion.SweptArea.OuterCurve)
polyline_points = [[(v * self.unit_scale) for v in p] for p in polyline_points]
polyline_points = [slab_obj.matrix_world @ Vector((p[0], p[1], elevation)) for p in polyline_points]
outer_curve = extrusion.SweptArea.OuterCurve
if self._curve_has_arc_segments(outer_curve):
polyline_points = self._derive_points_from_arc_segments(slab_obj, elevation, outer_curve)
else:
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
polyline_points = builder.get_polyline_coords(outer_curve)
polyline_points = [[(v * self.unit_scale) for v in p] for p in polyline_points]
polyline_points = [slab_obj.matrix_world @ Vector((p[0], p[1], elevation)) for p in polyline_points]
if len(polyline_points) < 3:
return []
if not tool.Cad.is_counter_clockwise_order(polyline_points[0], polyline_points[1], polyline_points[2]):
polyline_points = polyline_points[::-1]
walls = []