Add emath::inverse_lerp

This commit is contained in:
Emil Ernerfeldt 2022-12-22 12:33:06 +01:00
parent fa0d7f7f7f
commit 34f587d1e1

View file

@ -87,6 +87,14 @@ impl Real for f64 {}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/// Linear interpolation. /// Linear interpolation.
///
/// ```
/// # use emath::lerp;
/// assert_eq!(lerp(1.0..=5.0, 0.0), 1.0);
/// assert_eq!(lerp(1.0..=5.0, 0.5), 3.0);
/// assert_eq!(lerp(1.0..=5.0, 1.0), 5.0);
/// assert_eq!(lerp(1.0..=5.0, 2.0), 9.0);
/// ```
#[inline(always)] #[inline(always)]
pub fn lerp<R, T>(range: RangeInclusive<R>, t: T) -> R pub fn lerp<R, T>(range: RangeInclusive<R>, t: T) -> R
where where
@ -96,6 +104,34 @@ where
(T::one() - t) * *range.start() + t * *range.end() (T::one() - t) * *range.start() + t * *range.end()
} }
/// Where in the range is this value? Returns 0-1 if within the range.
///
/// Returns <0 if before and >1 if after.
///
/// Returns `None` if the input range is zero-width.
///
/// ```
/// # use emath::inverse_lerp;
/// assert_eq!(inverse_lerp(1.0..=5.0, 1.0), Some(0.0));
/// assert_eq!(inverse_lerp(1.0..=5.0, 3.0), Some(0.5));
/// assert_eq!(inverse_lerp(1.0..=5.0, 5.0), Some(1.0));
/// assert_eq!(inverse_lerp(1.0..=5.0, 9.0), Some(2.0));
/// assert_eq!(inverse_lerp(1.0..=1.0, 3.0), None);
/// ```
#[inline]
pub fn inverse_lerp<R>(range: RangeInclusive<R>, value: R) -> Option<R>
where
R: Copy + PartialEq + Sub<R, Output = R> + Div<R, Output = R>,
{
let min = *range.start();
let max = *range.end();
if min == max {
None
} else {
Some((value - min) / (max - min))
}
}
/// Linearly remap a value from one range to another, /// Linearly remap a value from one range to another,
/// so that when `x == from.start()` returns `to.start()` /// so that when `x == from.start()` returns `to.start()`
/// and when `x == from.end()` returns `to.end()`. /// and when `x == from.end()` returns `to.end()`.