retrofire_core/math/
param.rs

1use core::ops::Range;
2
3use super::Lerp;
4
5/// Represents a single-variable parametric curve.
6// TODO More documentation
7pub trait Parametric<T> {
8    /// Returns the value of `self` at `t`.
9    ///
10    /// The "canonical" domain of this function is `t` ∈ [0.0, 1.0],
11    /// but implementations should return "reasonable" values outside
12    /// the unit interval as well.
13    #[allow(unused)]
14    fn eval(&self, t: f32) -> T;
15}
16
17impl<F: Fn(f32) -> T, T> Parametric<T> for F {
18    /// Returns `self(t)`.
19    fn eval(&self, t: f32) -> T {
20        self(t)
21    }
22}
23
24impl<T: Lerp> Parametric<T> for Range<T> {
25    /// Linearly interpolates between `self.start` and `self.end`.
26    ///
27    /// Equivalent to `<Self as Lerp>::lerp(&self.start, &self.end, t)`.
28    ///
29    /// See also [`Lerp::lerp`].
30    ///
31    /// # Examples
32    /// ```
33    /// use core::ops::Range;
34    /// use retrofire_core::math::{Parametric, pt2, Point2};
35    ///
36    /// let range: Range<Point2> = pt2(-2.0, 1.0)..pt2(3.0, 2.0);
37    ///
38    /// assert_eq!(range.eval(0.0), range.start);
39    /// assert_eq!(range.eval(0.5), pt2(0.5, 1.5));
40    /// assert_eq!(range.eval(1.0), range.end);
41    /// ```
42    fn eval(&self, t: f32) -> T {
43        self.start.lerp(&self.end, t)
44    }
45}