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}