diff --git a/src/spline.rs b/src/spline.rs index fc425d7..ba260b7 100644 --- a/src/spline.rs +++ b/src/spline.rs @@ -102,7 +102,7 @@ impl Spline { /// sampling impossible. For instance, [`Interpolation::CatmullRom`] requires *four* keys. If /// you’re near the beginning of the spline or its end, ensure you have enough keys around to make /// the sampling. - pub fn sample_with_key(&self, t: T) -> Option<(V, &Key, Option<&Key>)> + pub fn sample_with_key(&self, t: T) -> Option> where T: Additive + One + Trigo + Mul + Div + PartialOrd, V: Additive + Interpolate, @@ -111,13 +111,13 @@ impl Spline { let i = search_lower_cp(keys, t)?; let cp0 = &keys[i]; - match cp0.interpolation { + let value = match cp0.interpolation { Interpolation::Step(threshold) => { let cp1 = &keys[i + 1]; let nt = normalize_time(t, cp0, cp1); let value = if nt < threshold { cp0.value } else { cp1.value }; - Some((value, cp0, Some(cp1))) + Some(value) } Interpolation::Linear => { @@ -125,7 +125,7 @@ impl Spline { let nt = normalize_time(t, cp0, cp1); let value = Interpolate::lerp(cp0.value, cp1.value, nt); - Some((value, cp0, Some(cp1))) + Some(value) } Interpolation::Cosine => { @@ -135,7 +135,7 @@ impl Spline { let cos_nt = (T::one() - (nt * T::pi()).cos()) / two_t; let value = Interpolate::lerp(cp0.value, cp1.value, cos_nt); - Some((value, cp0, Some(cp1))) + Some(value) } Interpolation::CatmullRom => { @@ -156,7 +156,7 @@ impl Spline { nt, ); - Some((value, cp0, Some(cp1))) + Some(value) } } @@ -177,9 +177,11 @@ impl Spline { _ => Interpolate::quadratic_bezier(cp0.value, u, cp1.value, nt), }; - Some((value, cp0, Some(cp1))) + Some(value) } - } + }; + + value.map(|value| SampledWithKey { value, key: i }) } /// Sample a spline at a given time. @@ -189,7 +191,7 @@ impl Spline { T: Additive + One + Trigo + Mul + Div + PartialOrd, V: Additive + Interpolate, { - self.sample_with_key(t).map(|(v, _, _)| v) + self.sample_with_key(t).map(|sampled| sampled.value) } /// Sample a spline at a given time with clamping, returning the interpolated value along with its @@ -203,7 +205,7 @@ impl Spline { /// # Error /// /// This function returns [`None`] if you have no key. - pub fn clamped_sample_with_key(&self, t: T) -> Option<(V, &Key, Option<&Key>)> + pub fn clamped_sample_with_key(&self, t: T) -> Option> where T: Additive + One + Trigo + Mul + Div + PartialOrd, V: Additive + Interpolate, @@ -214,18 +216,22 @@ impl Spline { self.sample_with_key(t).or_else(move || { let first = self.0.first().unwrap(); + if t <= first.t { - let second = if self.0.len() >= 2 { - Some(&self.0[1]) - } else { - None + let sampled = SampledWithKey { + value: first.value, + key: 0, }; - Some((first.value, &first, second)) + Some(sampled) } else { let last = self.0.last().unwrap(); if t >= last.t { - Some((last.value, &last, None)) + let sampled = SampledWithKey { + value: last.value, + key: self.0.len() - 1, + }; + Some(sampled) } else { None } @@ -239,7 +245,7 @@ impl Spline { T: Additive + One + Trigo + Mul + Div + PartialOrd, V: Additive + Interpolate, { - self.clamped_sample_with_key(t).map(|(v, _, _)| v) + self.clamped_sample_with_key(t).map(|sampled| sampled.value) } /// Add a key into the spline. @@ -293,11 +299,22 @@ impl Spline { } } +/// A sampled value along with its key index. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct SampledWithKey { + /// Sampled value. + pub value: V, + + /// Key index. + pub key: usize, +} + /// A mutable [`Key`]. /// /// Mutable keys allow to edit the carried values and the interpolation mode but not the actual /// interpolator value as it would invalidate the internal structure of the [`Spline`]. If you /// want to achieve this, you’re advised to use [`Spline::replace`]. +#[derive(Debug)] pub struct KeyMut<'a, T, V> { /// Carried value. pub value: &'a mut V, diff --git a/tests/mod.rs b/tests/mod.rs index 4ff6aae..d443c0e 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -1,4 +1,4 @@ -use splines::{Interpolation, Key, Spline}; +use splines::{spline::SampledWithKey, Interpolation, Key, Spline}; #[cfg(feature = "cgmath")] use cgmath as cg; @@ -18,8 +18,14 @@ fn step_interpolation_f32() { assert_eq!(spline.sample(0.9), Some(10.)); assert_eq!(spline.sample(1.), None); assert_eq!(spline.clamped_sample(1.), Some(10.)); - assert_eq!(spline.sample_with_key(0.2), Some((10., &start, Some(&end)))); - assert_eq!(spline.clamped_sample_with_key(1.), Some((10., &end, None))); + assert_eq!( + spline.sample_with_key(0.2), + Some(SampledWithKey { value: 10., key: 0 }) + ); + assert_eq!( + spline.clamped_sample_with_key(1.), + Some(SampledWithKey { value: 10., key: 1 }) + ); } #[test] @@ -35,8 +41,14 @@ fn step_interpolation_f64() { assert_eq!(spline.sample(0.9), Some(10.)); assert_eq!(spline.sample(1.), None); assert_eq!(spline.clamped_sample(1.), Some(10.)); - assert_eq!(spline.sample_with_key(0.2), Some((10., &start, Some(&end)))); - assert_eq!(spline.clamped_sample_with_key(1.), Some((10., &end, None))); + assert_eq!( + spline.sample_with_key(0.2), + Some(SampledWithKey { value: 10., key: 0 }) + ); + assert_eq!( + spline.clamped_sample_with_key(1.), + Some(SampledWithKey { value: 10., key: 1 }) + ); } #[test]