forked from 1b-agent/opencadstudio-upstream
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 <[email protected]>
This commit is contained in:
1 parent
e5d0c3950b
commit
0ca1e58b1f
1 file changed
+28
@@ -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() {
|
||||
|
||||
Reference in new issue
Block a user