fix(solid): tessellate cone-surface faces to their arc, not a full circle

Curved 3D-solid faces backed by an ACIS cone-surface (e.g. the arched
mullion bars of a storefront curtain wall) were swept a full revolution
regardless of the face's actual angular extent, so a bar bounded to an
8-16 degree arc rendered as a full circle of the surface radius — a large
jagged loop instead of a small arch.

cone_faces (the truck B-rep path) now derives the angular span from the
face's boundary loop and rsweeps only that arc; the bespoke fallback
tess_cone_face no longer forces a full revolution when a thin face
collapses to a single height. Arc extraction uses a seam-robust
largest-gap method so faces straddling +/-pi (the crown of an arch) are
not mistaken for full circles.

Verified against Clinic_Architectural.dwg: the seven arch-bar solids drop
from a ~12.9 (2R) bbox to their true ~1-2 unit extent, and a file-wide
check of 155 cone-bearing solids shows none ballooned and none collapsed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-04 16:11:24 +03:00
1 parent a8c368aef9
commit 9f7fdc5f8f
2 files changed
+86 -10

No files matched your search

+8 -4
View File
@@ -609,14 +609,17 @@ fn tess_cone_face(
// boundary alone can't span the height — the second extent (top rim or
// apex) lives on a different face. When the boundary collapses to one
// height, recover the span from the solid's coaxial circle rims plus the
// analytic apex of a true cone, and sweep the full revolution.
// analytic apex of a true cone. Only sweep the full revolution when the
// boundary really is a closed rim; a bounded arc face (e.g. a curved
// mullion bar) keeps its own angular span, else it balloons to a circle.
if (h_max - h_min).abs() < 1e-9 {
if let Some((vmin, vmax)) = cone_axis_span(sat, cone, axis, [cx, cy, cz]) {
h_min = vmin;
h_max = vmax;
theta_min = 0.0;
theta_max = TAU;
full_circle = true;
if full_circle {
theta_min = 0.0;
theta_max = TAU;
}
}
}
@@ -1012,3 +1015,4 @@ fn norm3(v: [f64; 3]) -> [f64; 3] {
[v[0] / len, v[1] / len, v[2] / len]
}
}