enterpolation/easing/
plateau.rs

1use crate::easing::smoothstep;
2use crate::{Curve, Generator};
3use num_traits::real::Real;
4use num_traits::FromPrimitive;
5
6/// Plateau is an easing curve which - therefore the name - create constant plateaus if given to
7/// an interpolation which works with factors for which an easing function gets applied.
8#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
9#[derive(Debug, Copy, Clone)]
10pub struct Plateau<R> {
11    min: R,
12    max: R,
13}
14
15impl<R> Plateau<R>
16where
17    R: Real + FromPrimitive,
18{
19    /// Create a new Plateau Easing Curve with the given strength. A strength of 0.0 will be the same as
20    /// the identity. A strength of 1.0 will only return 0.0 or 1.0 (depending which is nearer).
21    pub fn new(strength: R) -> Self {
22        let halfed = strength / R::from_usize(2).expect("Could not convert 2 into a real number");
23        Plateau {
24            min: R::zero() + halfed,
25            max: R::one() - halfed,
26        }
27    }
28}
29
30/// Overclamp can be imagined as a to clamp working to hard. That is, not only will be values be
31/// clamped wich are outside the defined area but also some points inside the area, depending on
32/// their distance and how strong the over clamping is done.
33///
34/// Overclamping is done in the area of [0.0,1.0]. All values below a certain threshold will be clamped to
35/// 0.0. All values above a certain threshold will be clamped to 1.0. All other values are stretched
36/// such that they fill out the entire [0.0,1.0] area.
37fn over_clamp<R>(input: R, min: R, max: R) -> R
38where
39    R: Real,
40{
41    if input < min {
42        R::zero()
43    } else if input > max {
44        R::one()
45    } else {
46        (input - min) / (max - min)
47    }
48}
49
50impl<R> Generator<R> for Plateau<R>
51where
52    R: Real + FromPrimitive,
53{
54    type Output = R;
55    fn gen(&self, input: R) -> R {
56        smoothstep(over_clamp(input, self.min, self.max))
57    }
58}
59
60impl<R> Curve<R> for Plateau<R>
61where
62    R: Real + FromPrimitive,
63{
64    fn domain(&self) -> [R; 2] {
65        [R::zero(), R::one()]
66    }
67}