From 8eb77affb020fbe55dabc4a48b85c7528009e2e4 Mon Sep 17 00:00:00 2001 From: jyviko <2501648+jyviko@users.noreply.github.com> Date: Thu, 29 Oct 2026 00:11:19 -0400 Subject: [PATCH] Kernel: a body's size counts its edges, so a sphere, cylinder or torus is its own size Body size (the box diagonal every size-relative tolerance comes from: mesh chords, reach, fit tolerances) came from the record's vertices alone. SMLib closes a sphere, a cylinder or a torus along seam edges, so those vertices can be two poles, two seam ends or a single point: a torus was 1 mm across (its preview at a hundredth of that took 214 720 triangles and broke the budget), a 5 x 8 cylinder 8 instead of 16.2. The size now also takes three points along each edge: points on the edges, not their control hulls, which for a rational edge can lie far off it (a sheared L-prism's outline box was 49 km across). Co-Authored-By: Claude Opus 5.5 --- crates/kernel/src/body.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/crates/kernel/src/body.rs b/crates/kernel/src/body.rs index e87c5803f5..773e4fdb58 100644 --- a/crates/kernel/src/body.rs +++ b/crates/kernel/src/body.rs @@ -344,9 +344,25 @@ fn coarse_tolerance(span: f64) -> f64 { (span * 0.01).clamp(1e-3, 1.0) } -/// Box diagonal of a record's vertices (0 when it has none or no finite extent). +/// Box diagonal of a record's vertices and points along its edges (0 when it has none or no +/// finite extent). The edges count: SMLib closes a sphere, a cylinder or a torus along seams, so +/// its vertices alone can be two poles or a single point (a torus came out 1 mm across, and its +/// display mesh at a hundredth of that took 214 720 triangles). Points on the edges, not their +/// control hulls: a rational edge's control points can lie far off it. fn span_of(record: &Brep) -> f64 { - let bounds: Aabb3 = record.vertices.iter().map(|v| v3(v.point)).collect(); + let mut bounds: Aabb3 = record.vertices.iter().map(|v| v3(v.point)).collect(); + for e in &record.edges { + if let Ok(c) = brep::eval::CurveEval::new(e.parameters()) { + let [t0, t1] = e.interval; + for i in 1..4 { + if let Some(p) = c.point(t0 + (t1 - t0) * f64::from(i) / 4.0) + && p.is_finite() + { + bounds.add(p); + } + } + } + } let d = if bounds.is_empty() { 0.0 } else { bounds.diagonal() }; if d.is_finite() && d > 0.0 { d } else { 0.0 } }