From ec1090837e54846285159216dc036e7b837faf3b Mon Sep 17 00:00:00 2001 From: bherbruck Date: Thu, 8 Oct 2026 06:51:34 +0000 Subject: [PATCH] Merged topology: a sphere's normals must be radial too (torus strips no longer pass for spheres), so torus pieces merge (40) Oracle: 73/76. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL --- crates/kernel/src/topo.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/kernel/src/topo.rs b/crates/kernel/src/topo.rs index 5facfae9..960a5759 100644 --- a/crates/kernel/src/topo.rs +++ b/crates/kernel/src/topo.rs @@ -138,7 +138,9 @@ fn classify(pts: &[Vec3], nrm: &[Vec3], tol: f64, id: usize) -> Surf { // Sphere: algebraic least-squares fit |p|² = 2c·p + k, then every point at the same distance. if let Some((c, r)) = fit_sphere(pts) { let spread = pts.iter().map(|p| p.dist(p0)).fold(0.0, f64::max); - if spread > tol && pts.iter().all(|p| (p.dist(c) - r).abs() < tol.max(r * 2e-3)) && r < spread * 1e4 { + // Normals radial too (a torus strip can fit a sphere's points closely). + let radial = pts.iter().zip(nrm).all(|(p, n)| (*p - c).normalized().is_some_and(|d| d.dot(*n).abs() > 1.0 - 2e-3)); + if spread > tol && radial && pts.iter().all(|p| (p.dist(c) - r).abs() < tol.max(r * 2e-3)) && r < spread * 1e4 { return Surf::Sphere { c, r }; } }