pub fn lerp_4d(a: &[f64; 4], b: &[f64; 4], t: f64) -> [f64; 4] {
[
a[0] + t * (b[0] - a[0]),
a[1] + t * (b[1] - a[1]),
a[2] + t * (b[2] - a[2]),
a[3] + t * (b[3] - a[3]),
]
}
pub fn bilinear_4d(
p00: &[f64; 4],
p01: &[f64; 4],
p10: &[f64; 4],
p11: &[f64; 4],
u: f64,
v: f64,
) -> [f64; 4] {
let p0 = lerp_4d(p00, p01, v);
let p1 = lerp_4d(p10, p11, v);
lerp_4d(&p0, &p1, u)
}
#[allow(clippy::too_many_arguments)]
pub fn trilinear_4d(
p000: &[f64; 4],
p001: &[f64; 4],
p010: &[f64; 4],
p011: &[f64; 4],
p100: &[f64; 4],
p101: &[f64; 4],
p110: &[f64; 4],
p111: &[f64; 4],
u: f64,
v: f64,
w: f64,
) -> [f64; 4] {
let p00 = lerp_4d(p000, p001, w);
let p01 = lerp_4d(p010, p011, w);
let p10 = lerp_4d(p100, p101, w);
let p11 = lerp_4d(p110, p111, w);
bilinear_4d(&p00, &p01, &p10, &p11, u, v)
}
#[allow(clippy::too_many_arguments)]
pub fn quadrilinear_4d(points: &[[f64; 4]; 16], u: f64, v: f64, w: f64, t: f64) -> [f64; 4] {
let slice0 = trilinear_4d(
&points[0], &points[1], &points[2], &points[3], &points[4], &points[5], &points[6],
&points[7], u, v, w,
);
let slice1 = trilinear_4d(
&points[8],
&points[9],
&points[10],
&points[11],
&points[12],
&points[13],
&points[14],
&points[15],
u,
v,
w,
);
lerp_4d(&slice0, &slice1, t)
}
pub fn cosine_interp_4d(a: &[f64; 4], b: &[f64; 4], t: f64) -> [f64; 4] {
let mu = (1.0 - (t * std::f64::consts::PI).cos()) / 2.0;
lerp_4d(a, b, mu)
}
pub fn cubic_hermite_4d(
p0: &[f64; 4],
m0: &[f64; 4],
p1: &[f64; 4],
m1: &[f64; 4],
t: f64,
) -> [f64; 4] {
let t2 = t * t;
let t3 = t2 * t;
let h00 = 2.0 * t3 - 3.0 * t2 + 1.0;
let h10 = t3 - 2.0 * t2 + t;
let h01 = -2.0 * t3 + 3.0 * t2;
let h11 = t3 - t2;
[
h00 * p0[0] + h10 * m0[0] + h01 * p1[0] + h11 * m1[0],
h00 * p0[1] + h10 * m0[1] + h01 * p1[1] + h11 * m1[1],
h00 * p0[2] + h10 * m0[2] + h01 * p1[2] + h11 * m1[2],
h00 * p0[3] + h10 * m0[3] + h01 * p1[3] + h11 * m1[3],
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lerp_4d() {
let a = [0.0, 0.0, 0.0, 0.0];
let b = [1.0, 1.0, 1.0, 1.0];
let mid = lerp_4d(&a, &b, 0.5);
assert_eq!(mid, [0.5, 0.5, 0.5, 0.5]);
let start = lerp_4d(&a, &b, 0.0);
assert_eq!(start, a);
let end = lerp_4d(&a, &b, 1.0);
assert_eq!(end, b);
}
#[test]
fn test_bilinear_4d() {
let p00 = [0.0, 0.0, 0.0, 0.0];
let p01 = [0.0, 1.0, 0.0, 0.0];
let p10 = [1.0, 0.0, 0.0, 0.0];
let p11 = [1.0, 1.0, 0.0, 0.0];
let center = bilinear_4d(&p00, &p01, &p10, &p11, 0.5, 0.5);
assert_eq!(center, [0.5, 0.5, 0.0, 0.0]);
}
#[test]
fn test_cosine_interp() {
let a = [0.0, 0.0, 0.0, 0.0];
let b = [1.0, 1.0, 1.0, 1.0];
let result = cosine_interp_4d(&a, &b, 0.5);
assert!((result[0] - 0.5).abs() < 0.01);
}
}