1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::ops::{Add,Sub,Mul,Div};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let a=10.0f32;
let b=20.0f32;
let f0=0.25f32;
let f1=0.75f32;
let f=0.5f32;
let z1=a.lerp(&b,f0);
let z2=a.pair_with(&b).lerp_by(f1);
let w1=12.5f32;
let w2=17.5f32;
assert_eq!(z1,w1);
assert_eq!(z2,w2);
assert_eq!(z1.inv_lerp(&a,&b),f0);
assert_eq!(z2.inv_lerp(&a,&b),f1);
}
}
pub trait Lerp<F=f32> :Sized{
fn lerp(&self,b:&Self,factor:F)->Self;
fn lerp_points<Y>(&self,a:&Self,b:&Self, y0:&Y,y1:&Y)->Y
where Y:Lerp<F>, Self:InvLerp<F>
{
lerp_points(self,a,b, y0,y1)
}
}
pub trait LerpBetween<T> :Sized+Clone where T:Lerp<Self>{
fn lerp_between(&self,a:&T,b:&T)->T {
a.lerp(b,self.clone())
}
}
pub fn lerp<F,T:Lerp<F>>(a:&T,b:&T, f:F)->T{
a.lerp(b,f)
}
pub trait InvLerp<F=f32>:Sized {
fn inv_lerp(&self,a:&Self,b:&Self)->F;
}
pub trait LerpBy<F>{
type Output;
fn lerp_by(&self,f:F)->Self::Output;
}
impl<'a,'b, F,T:Lerp<F>> LerpBy<F> for (&'a T,&'b T) {
type Output=T;
fn lerp_by(&self,f:F)->Self::Output{ self.0.lerp(&self.1,f) }
}
pub trait PairWith<B> {
fn pair_with<'a,'b>(&'a self,b:&'b B)->(&'a Self,&'b B);
}
impl<A,B> PairWith<B> for A {
fn pair_with<'a,'b>(&'a self,b:&'b B)->(&'a A,&'b B){(self,b)}
}
fn lerp_points<X,Y,F>(x:&X,x0:&X,x1:&X, y0:&Y,y1:&Y)->Y where
X:InvLerp<F>, Y:Lerp<F>
{
y0.lerp(y1, x.inv_lerp(x0,x1) )
}
impl<T,Diff,Scaled,Factor:Copy> Lerp<Factor> for T where
for<'u,'v> &'u T:Sub<&'v T,Output=Diff>,
for<'u,'v> &'u Diff:Mul<Factor,Output=Scaled>,
for<'u,'v,'w> &'u T:Add<&'v Scaled,Output=T>,
{
fn lerp(&self,b:&Self,factor:Factor)->Self{
let diff=b.sub(self);
let scaled=diff.mul(factor);
self.add(&scaled)
}
}
impl<T,Diff,Factor> InvLerp<Factor> for T where
for <'u,'v> &'u T:Sub<&'v T,Output=Diff>,
for <'u,'v> &'u Diff:Div<&'v Diff, Output=Factor>
{
fn inv_lerp(&self,a:&Self,b:&Self)->Factor{
let rng=b.sub(a);
let ofs=self.sub(a);
ofs.div(&rng)
}
}
pub fn avr<T:Lerp>(a:&T,b:&T)->T{ a.lerp(b,0.5f32) }