Motion Trace: a point's path as a joint is driven or a study plays, kept as a 3D spline (#1529)
Thanks @SychPL.
This commit is contained in:
1 parent
dcffab09b1
commit
571122c4ba
19 files changed
+769
-9
No files matched your search
@@ -61,9 +61,13 @@ pub fn fit_polyline(fit: &[Vec3]) -> Vec<Vec3> {
|
||||
return fit.to_vec();
|
||||
}
|
||||
let n = fit.len();
|
||||
// A curve that ends where it starts is smooth through that point (its neighbours wrap).
|
||||
let closed = n > 3 && fit[0].dist(fit[n - 1]) < 1e-9;
|
||||
let at = |i: isize| -> Vec3 {
|
||||
match usize::try_from(i) {
|
||||
Ok(i) if i < n => fit[i],
|
||||
Ok(_) if closed => fit[1],
|
||||
Err(_) if closed => fit[n - 2],
|
||||
// Mirrored end tangents.
|
||||
Ok(_) => fit[n - 1] * 2.0 - fit[n - 2],
|
||||
Err(_) => fit[0] * 2.0 - fit[1],
|
||||
@@ -330,4 +334,20 @@ mod tests {
|
||||
assert_eq!(sk, before);
|
||||
sk.validate_wires().unwrap();
|
||||
}
|
||||
|
||||
/// Through points around a circle that end where they start, the spline turns as smoothly at
|
||||
/// the closing point as everywhere else; an open one keeps its mirrored end tangents.
|
||||
#[test]
|
||||
fn a_closed_spline_is_smooth_where_it_closes() {
|
||||
let ring: Vec<Vec3> = (0..=12).map(|k| f64::from(k) * std::f64::consts::TAU / 12.0).map(|a| Vec3::new(a.cos(), a.sin(), 0.0)).collect();
|
||||
let pts = fit_polyline(&ring);
|
||||
let dir = |a: Vec3, b: Vec3| (b - a).normalized().unwrap();
|
||||
let n = pts.len();
|
||||
let (start, end) = (dir(pts[0], pts[1]), dir(pts[n - 2], pts[n - 1]));
|
||||
let mid = |i: usize| dir(pts[i - 1], pts[i]).dot(dir(pts[i], pts[i + 1]));
|
||||
assert!(start.dot(end) >= mid(SPAN_SAMPLES) - 1e-9, "turn at the close {}, at a fit point {}", start.dot(end), mid(SPAN_SAMPLES));
|
||||
let open = fit_polyline(&ring[..12]);
|
||||
assert_eq!(open.first(), ring.first());
|
||||
assert_eq!(open.last(), ring.get(11));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user