[math] make lerp, remap and remap_clamp work for both f32 and f64
This commit is contained in:
parent
7a71ac1a95
commit
a49cba54ac
1 changed files with 49 additions and 12 deletions
|
@ -1,6 +1,6 @@
|
|||
//! Vectors, positions, rectangles etc.
|
||||
|
||||
use std::ops::{Add, Mul, RangeInclusive};
|
||||
use std::ops::{Add, Div, Mul, RangeInclusive, Sub};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -13,27 +13,64 @@ pub use {pos2::*, rect::*, vec2::*};
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Linear interpolation.
|
||||
pub fn lerp<T>(range: RangeInclusive<T>, t: f32) -> T
|
||||
where
|
||||
f32: Mul<T, Output = T>,
|
||||
T: Add<T, Output = T> + Copy,
|
||||
pub trait One {
|
||||
fn one() -> Self;
|
||||
}
|
||||
impl One for f32 {
|
||||
fn one() -> Self {
|
||||
1.0
|
||||
}
|
||||
}
|
||||
impl One for f64 {
|
||||
fn one() -> Self {
|
||||
1.0
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Real:
|
||||
Copy
|
||||
+ PartialEq
|
||||
+ PartialOrd
|
||||
+ One
|
||||
+ Add<Self, Output = Self>
|
||||
+ Sub<Self, Output = Self>
|
||||
+ Mul<Self, Output = Self>
|
||||
+ Div<Self, Output = Self>
|
||||
{
|
||||
(1.0 - t) * *range.start() + t * *range.end()
|
||||
}
|
||||
|
||||
impl Real for f32 {}
|
||||
impl Real for f64 {}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Linear interpolation.
|
||||
pub fn lerp<R, T>(range: RangeInclusive<R>, t: T) -> R
|
||||
where
|
||||
T: Real + Mul<R, Output = R>,
|
||||
R: Copy + Add<R, Output = R>,
|
||||
{
|
||||
(T::one() - t) * *range.start() + t * *range.end()
|
||||
}
|
||||
|
||||
/// Linearly remap a value from one range to another,
|
||||
/// so that when `x == from.start()` returns `to.start()`
|
||||
/// and when `x == from.end()` returns `to.end()`.
|
||||
pub fn remap(x: f32, from: RangeInclusive<f32>, to: RangeInclusive<f32>) -> f32 {
|
||||
pub fn remap<T>(x: T, from: RangeInclusive<T>, to: RangeInclusive<T>) -> T
|
||||
where
|
||||
T: Real,
|
||||
{
|
||||
#![allow(clippy::float_cmp)]
|
||||
debug_assert!(from.start() != from.end());
|
||||
let t = (x - from.start()) / (from.end() - from.start());
|
||||
let t = (x - *from.start()) / (*from.end() - *from.start());
|
||||
lerp(to, t)
|
||||
}
|
||||
|
||||
/// Like `remap`, but also clamps the value so that the returned value is always in the `to` range.
|
||||
pub fn remap_clamp(x: f32, from: RangeInclusive<f32>, to: RangeInclusive<f32>) -> f32 {
|
||||
pub fn remap_clamp<T>(x: T, from: RangeInclusive<T>, to: RangeInclusive<T>) -> T
|
||||
where
|
||||
T: Real,
|
||||
{
|
||||
#![allow(clippy::float_cmp)]
|
||||
if from.end() < from.start() {
|
||||
return remap_clamp(x, *from.end()..=*from.start(), *to.end()..=*to.start());
|
||||
|
@ -44,9 +81,9 @@ pub fn remap_clamp(x: f32, from: RangeInclusive<f32>, to: RangeInclusive<f32>) -
|
|||
*to.end()
|
||||
} else {
|
||||
debug_assert!(from.start() != from.end());
|
||||
let t = (x - from.start()) / (from.end() - from.start());
|
||||
let t = (x - *from.start()) / (*from.end() - *from.start());
|
||||
// Ensure no numerical inaccuracies sneak in:
|
||||
if 1.0 <= t {
|
||||
if T::one() <= t {
|
||||
*to.end()
|
||||
} else {
|
||||
lerp(to, t)
|
||||
|
|
Loading…
Reference in a new issue