From 0ca1e58b1f1db9242a0408c87329c506b1cd4795 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Wed, 10 Jun 2026 20:27:45 +0300 Subject: [PATCH] fix(io): purge zero-length point-collapsed splines that hang load sample_layout_03/04.dwg would not open: a periodic 9-control-point spline with every control point pinned at the origin (zero extent) reaches truck's parameter_division, which never converges on a zero-length curve and hangs the first-frame tessellation. The spline passed every existing guard (finite points, no knots, degree 3). Reject splines whose control-point extent is sub-precision (< 1e-6 on all axes). Verified: all five sample_layout DWGs now load + tessellate (03/04 went from a hang to ~356 ms; 01/02/05 unchanged, no valid spline dropped). Co-Authored-By: Claude Opus 4.8 --- src/io/mod.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/io/mod.rs b/src/io/mod.rs index 273571220..9afa5ec66 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -498,10 +498,28 @@ pub(crate) fn is_entity_corrupt(e: &EntityType) -> bool { && (s.knots.iter().any(|k| !k.is_finite()) || s.knots.windows(2).any(|w| w[1] < w[0]) || s.knots.len() != n + deg + 1); + // Degenerate: every control point collapses onto (nearly) the same + // point, so the curve has zero length. truck's `circle_arc` / + // `parameter_division` never converges on it and the tessellation + // hangs — a periodic 9-point spline pinned at the origin is the seen + // case. Reject when the control-point extent is sub-precision. + let degenerate_extent = n >= 2 && { + let (mut mn, mut mx) = ([f64::MAX; 3], [f64::MIN; 3]); + for p in &s.control_points { + mn[0] = mn[0].min(p.x); + mx[0] = mx[0].max(p.x); + mn[1] = mn[1].min(p.y); + mx[1] = mx[1].max(p.y); + mn[2] = mn[2].min(p.z); + mx[2] = mx[2].max(p.z); + } + (mx[0] - mn[0]).max(mx[1] - mn[1]).max(mx[2] - mn[2]) < 1.0e-6 + }; n >= MAX_VERTS || degree_bad || s.control_points.iter().any(|p| !finite_vec3(p)) || knots_bad + || degenerate_extent } _ => false, } @@ -651,6 +669,16 @@ mod corrupt_guard_tests { assert!(is_entity_corrupt(&EntityType::Spline(s))); } + // A periodic spline whose control points all collapse onto (nearly) one + // point has zero length; truck's parameter_division never converges and the + // tessellation hangs. The control-point extent floor must reject it. + #[test] + fn rejects_degenerate_point_spline() { + let pts = vec![Vector3::new(1e-12, -1e-12, 0.0); 9]; + let s = Spline::from_control_points(3, pts); + assert!(is_entity_corrupt(&EntityType::Spline(s))); + } + // A normal cubic spline (4 control points, valid clamped knots) survives. #[test] fn keeps_valid_spline() {