From 70d6cf20813a8cb0e373b2427a9e7b4ee5328fd2 Mon Sep 17 00:00:00 2001 From: Dimitri Sabadie Date: Sun, 21 Apr 2019 18:11:06 +0200 Subject: [PATCH] Implement impl-cgmath. --- Cargo.toml | 2 +- src/cgmath.rs | 52 ++++++++++++++++++++++++++++++++++------------ src/interpolate.rs | 4 ---- src/spline.rs | 10 ++++++--- tests/mod.rs | 18 ++++++++++++++-- 5 files changed, 63 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9b6f6aa..2f72b35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ std = [] [dependencies] alga = { version = "0.9", optional = true } -cgmath = { version = "0.17", optional = true } +cgmath = { version = "0.16", optional = true } nalgebra = { version = ">=0.14, <0.19", optional = true } num-traits = { version = "0.2", optional = true } serde = { version = "1", optional = true } diff --git a/src/cgmath.rs b/src/cgmath.rs index 9cdd459..c1f05c7 100644 --- a/src/cgmath.rs +++ b/src/cgmath.rs @@ -1,26 +1,52 @@ -use cgmath::{BaseNum, InnerSpace, Quaternion, VectorSpace, Vector2, Vector3, Vector4}; -use num_traits::Float; +use cgmath::{BaseFloat, BaseNum, InnerSpace, Quaternion, VectorSpace, Vector1, Vector2, Vector3, Vector4}; -use crate::interpolate::{Interpolate, cubic_hermite_def}; +use crate::interpolate::{Additive, Interpolate, Linear, One, cubic_hermite_def}; macro_rules! impl_interpolate_vec { - ($t:ty, $($q:tt)*) => { - impl Interpolate<$t> for $($q)*<$t> { - fn lerp(a: Self, b: Self, t: $t) -> Self { + ($($t:tt)*) => { + impl Linear for $($t)* where T: BaseNum { + fn outer_mul(self, t: T) -> Self { + self * t + } + + fn outer_div(self, t: T) -> Self { + self / t + } + } + + impl Interpolate for $($t)* where Self: InnerSpace, T: Additive + BaseFloat + One { + fn lerp(a: Self, b: Self, t: T) -> Self { a.lerp(b, t) } - fn cubic_hermite(x: (Self, $t), a: (Self, $t), b: (Self, $t), y: (Self, $t), t: $t) -> Self { + fn cubic_hermite(x: (Self, T), a: (Self, T), b: (Self, T), y: (Self, T), t: T) -> Self { cubic_hermite_def(x, a, b, y, t) } } } } -impl_interpolate_vec!(f32, Vector2); +impl_interpolate_vec!(Vector1); +impl_interpolate_vec!(Vector2); +impl_interpolate_vec!(Vector3); +impl_interpolate_vec!(Vector4); -//impl Interpolate for Quaternion { -// fn lerp(a: Self, b: Self, t: f32) -> Self { -// a.nlerp(b, t) -// } -//} +impl Linear for Quaternion where T: BaseFloat { + fn outer_mul(self, t: T) -> Self { + self * t + } + + fn outer_div(self, t: T) -> Self { + self / t + } +} + +impl Interpolate for Quaternion where Self: InnerSpace, T: Additive + BaseFloat + One { + fn lerp(a: Self, b: Self, t: T) -> Self { + a.nlerp(b, t) + } + + fn cubic_hermite(x: (Self, T), a: (Self, T), b: (Self, T), y: (Self, T), t: T) -> Self { + cubic_hermite_def(x, a, b, y, t) + } +} diff --git a/src/interpolate.rs b/src/interpolate.rs index 314f37c..d4c5460 100644 --- a/src/interpolate.rs +++ b/src/interpolate.rs @@ -27,16 +27,12 @@ pub trait Interpolate: Sized + Copy { /// A trait for anything that supports additions, subtraction, multiplication and division. pub trait Additive: Copy + - PartialEq + - PartialOrd + Add + Sub { } impl Additive for T where T: Copy + - PartialEq + - PartialOrd + Add + Sub { } diff --git a/src/spline.rs b/src/spline.rs index f4e7f16..fa096c4 100644 --- a/src/spline.rs +++ b/src/spline.rs @@ -53,7 +53,9 @@ impl Spline { /// sampling impossible. For instance, `Interpolate::CatmullRom` requires *four* keys. If you’re /// near the beginning of the spline or its end, ensure you have enough keys around to make the /// sampling. - pub fn sample(&self, t: T) -> Option where T: Additive + One + Trigo + Mul + Div, V: Interpolate { + pub fn sample(&self, t: T) -> Option + where T: Additive + One + Trigo + Mul + Div + PartialOrd, + V: Interpolate { let keys = &self.0; let i = search_lower_cp(keys, t)?; let cp0 = &keys[i]; @@ -108,7 +110,9 @@ impl Spline { /// # Error /// /// This function returns `None` if you have no key. - pub fn clamped_sample(&self, t: T) -> Option where T: Additive + One + Trigo + Mul + Div, V: Interpolate { + pub fn clamped_sample(&self, t: T) -> Option + where T: Additive + One + Trigo + Mul + Div + PartialOrd, + V: Interpolate { if self.0.is_empty() { return None; } @@ -136,7 +140,7 @@ pub(crate) fn normalize_time( t: T, cp: &Key, cp1: &Key -) -> T where T: Additive + Div { +) -> T where T: Additive + Div + PartialEq { assert!(cp1.t != cp.t, "overlapping keys"); (t - cp.t) / (cp1.t - cp.t) } diff --git a/tests/mod.rs b/tests/mod.rs index 216bb7d..a73b18b 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -1,7 +1,7 @@ use splines::{Interpolation, Key, Spline}; -#[cfg(feature = "impl-nalgebra")] -use nalgebra as na; +#[cfg(feature = "impl-cgmath")] use cgmath as cg; +#[cfg(feature = "impl-nalgebra")] use nalgebra as na; #[test] fn step_interpolation_f32() { @@ -145,6 +145,20 @@ fn several_interpolations_several_keys() { assert_eq!(spline.clamped_sample(11.), Some(4.)); } +#[cfg(feature = "impl-cgmath")] +#[test] +fn cgmath_vector_interpolation() { + use splines::Interpolate; + + let start = cg::Vector2::new(0.0, 0.0); + let mid = cg::Vector2::new(0.5, 0.5); + let end = cg::Vector2::new(1.0, 1.0); + + assert_eq!(Interpolate::lerp(start, end, 0.0), start); + assert_eq!(Interpolate::lerp(start, end, 1.0), end); + assert_eq!(Interpolate::lerp(start, end, 0.5), mid); +} + #[cfg(feature = "impl-nalgebra")] #[test] fn nalgebra_vector_interpolation() {