Merge pull request #883 from vangel76/fix-880-spatial-nan

#880: motion paths with overflowing or NaN arc length evaluate without panicking
This commit is contained in:
Brandon Thomas
2026-10-12 04:20:41 -04:00
+27 -1
View File
@@ -287,7 +287,9 @@ impl SpatialSeg {
/// along curved paths instead of piecewise linear per cell (#456).
fn at_length(&self, s: f64) -> [f64; 3] {
let len = self.length();
if len <= 0.0 {
// A path whose length overflowed (huge coordinates) or is NaN has no arc-length table to
// walk: `clamp` would panic on a NaN bound.
if !(len > 0.0 && len.is_finite()) {
return self.p[0];
}
let s = s.clamp(0.0, len);
@@ -878,6 +880,30 @@ mod tests {
assert_eq!(segment_value(&keys, 0, s(1.0), true), Value::Vec2([80.0, 50.0]));
}
/// #880: a motion path whose arc length overflows (huge coordinates, as the Position field
/// accepts) or is NaN evaluates without panicking: scrubbing over it crashed the app.
#[test]
fn overflowing_or_nan_motion_paths_evaluate() {
let paths = [
[[-1.7e308, 0.0], [1.7e308, 0.0], [-1.7e308, 5.0]],
[[0.0, 0.0], [f64::NAN, 10.0], [20.0, 0.0]],
[[f64::INFINITY, 0.0], [0.0, f64::NEG_INFINITY], [20.0, 0.0]],
];
for path in paths {
let mut keys: Vec<Keyframe> = path.iter().enumerate().map(|(i, &v)| Keyframe::new(s(i as f64 * 2.0), Value::Vec2(v))).collect();
for eased in [false, true] {
if eased {
keys = keys.into_iter().map(Keyframe::eased).collect();
}
for f in 0..=40 {
let t = s(f as f64 * 0.1);
assert!(evaluate(&keys, t, true).is_some());
let _ = speed(&keys, t, true);
}
}
}
}
#[test]
fn spatial_auto_bezier_tangents_follow_after_effects() {
// Measured on After Effects 26.3 with original paths (docs/fidelity/README.md): each