#[cfg(feature = "interpolation")]
mod asymmetric_tangents {
use std::collections::BTreeMap;
use token_value_map::*;
#[test]
fn test_symmetric_speed_tangents() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(0.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(1.0))),
},
);
map.insert_with_interpolation(
Time::from(10.0),
Real(10.0),
Key {
interpolation_in: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(1.0))),
interpolation_out: Interpolation::Linear,
},
);
let mid = map.interpolate(Time::from(5.0));
assert!((mid.0 - 5.0).abs() < 0.5, "Expected ~5.0, got {:?}", mid);
}
#[test]
fn test_asymmetric_speed_tangents() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(0.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(2.0))),
},
);
map.insert_with_interpolation(
Time::from(10.0),
Real(10.0),
Key {
interpolation_in: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(0.5))),
interpolation_out: Interpolation::Linear,
},
);
let early = map.interpolate(Time::from(2.0));
let mid = map.interpolate(Time::from(5.0));
let late = map.interpolate(Time::from(8.0));
assert!(
early.0 > 2.0,
"Early value should be > 2.0 (linear), got {:?}",
early
);
assert!(
late.0 < 10.0,
"Late value should be < 10.0 (endpoint), got {:?}",
late
);
assert!(
early.0 < mid.0 && mid.0 < late.0,
"Values should be monotonic: {:?} < {:?} < {:?}",
early,
mid,
late
);
}
#[test]
fn test_hold_interpolation() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(0.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Hold,
},
);
map.insert_with_interpolation(
Time::from(10.0),
Real(10.0),
Key {
interpolation_in: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(1.0))),
interpolation_out: Interpolation::Linear,
},
);
let mid = map.interpolate(Time::from(5.0));
assert_eq!(mid, Real(0.0), "Hold should keep value at 0.0");
}
#[test]
fn test_linear_interpolation() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(0.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Linear,
},
);
map.insert_with_interpolation(
Time::from(10.0),
Real(10.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Linear,
},
);
let mid = map.interpolate(Time::from(5.0));
assert!((mid.0 - 5.0).abs() < 0.1, "Expected ~5.0, got {:?}", mid);
}
#[cfg(feature = "vector3")]
#[test]
fn test_vector_asymmetric_tangents() {
use token_value_map::math::Vec3Impl as NVector3;
let mut map = TimeDataMap::<Vector3>::from(BTreeMap::new());
let v0 = Vector3(NVector3::new(0.0, 0.0, 0.0));
let v1 = Vector3(NVector3::new(10.0, 10.0, 10.0));
let speed_out = Vector3(NVector3::new(2.0, 2.0, 2.0));
let speed_in = Vector3(NVector3::new(0.5, 0.5, 0.5));
map.insert_with_interpolation(
Time::from(0.0),
v0,
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Bezier(BezierHandle::SlopePerSecond(speed_out)),
},
);
map.insert_with_interpolation(
Time::from(10.0),
v1,
Key {
interpolation_in: Interpolation::Bezier(BezierHandle::SlopePerSecond(speed_in)),
interpolation_out: Interpolation::Linear,
},
);
let mid = map.interpolate(Time::from(5.0));
assert!(
mid.0.x > 5.0 && mid.0.y > 5.0 && mid.0.z > 5.0,
"Mid values should be > 5.0, got {:?}",
mid
);
}
#[test]
fn test_mixed_interpolation_modes() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(0.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(2.0))),
},
);
map.insert_with_interpolation(
Time::from(10.0),
Real(10.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Linear,
},
);
let mid = map.interpolate(Time::from(5.0));
assert!((mid.0 - 5.0).abs() < 0.1, "Expected ~5.0, got {:?}", mid);
}
#[test]
fn test_boundary_conditions() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(0.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(1.0))),
},
);
map.insert_with_interpolation(
Time::from(10.0),
Real(10.0),
Key {
interpolation_in: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(1.0))),
interpolation_out: Interpolation::Linear,
},
);
assert_eq!(map.interpolate(Time::from(0.0)), Real(0.0));
assert_eq!(map.interpolate(Time::from(10.0)), Real(10.0));
assert_eq!(map.interpolate(Time::from(-5.0)), Real(0.0));
assert_eq!(map.interpolate(Time::from(15.0)), Real(10.0));
}
#[test]
fn test_extreme_asymmetric_speeds() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(0.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(10.0))), },
);
map.insert_with_interpolation(
Time::from(10.0),
Real(10.0),
Key {
interpolation_in: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(0.1))), interpolation_out: Interpolation::Linear,
},
);
let early = map.interpolate(Time::from(1.0));
let late = map.interpolate(Time::from(9.0));
assert!(early.0 > 1.5, "Early should be > 1.5, got {:?}", early);
assert!(late.0 > 9.0, "Late should be > 9.0, got {:?}", late);
assert!(
early.0 < 12.0,
"Early should be reasonable, got {:?}",
early
);
assert!(late.0 < 12.0, "Late should be reasonable, got {:?}", late);
}
#[test]
fn test_zero_speed_tangents() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(0.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(0.0))), },
);
map.insert_with_interpolation(
Time::from(10.0),
Real(10.0),
Key {
interpolation_in: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(0.0))), interpolation_out: Interpolation::Linear,
},
);
let early = map.interpolate(Time::from(2.0));
let mid = map.interpolate(Time::from(5.0));
let late = map.interpolate(Time::from(8.0));
assert!(early.0 < 1.5, "Early should be < 1.5, got {:?}", early);
assert!(late.0 > 8.0, "Late should be > 8.0, got {:?}", late);
assert!(
(mid.0 - 5.0).abs() < 1.5,
"Mid should be ~5.0, got {:?}",
mid
);
}
#[test]
fn test_negative_speeds() {
let mut map = TimeDataMap::<Real>::from(BTreeMap::new());
map.insert_with_interpolation(
Time::from(0.0),
Real(5.0),
Key {
interpolation_in: Interpolation::Linear,
interpolation_out: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(-2.0))), },
);
map.insert_with_interpolation(
Time::from(10.0),
Real(5.0),
Key {
interpolation_in: Interpolation::Bezier(BezierHandle::SlopePerSecond(Real(2.0))), interpolation_out: Interpolation::Linear,
},
);
let mid = map.interpolate(Time::from(5.0));
assert!(mid.0 < 5.0, "Mid should be < 5.0, got {:?}", mid);
assert_eq!(map.interpolate(Time::from(0.0)), Real(5.0));
assert_eq!(map.interpolate(Time::from(10.0)), Real(5.0));
}
}