diff --git a/src/structure.rs b/src/structure.rs index 49c271c..dc808ae 100644 --- a/src/structure.rs +++ b/src/structure.rs @@ -246,6 +246,15 @@ pub trait InnerSpace: VectorSpace where fn lerp(self, other: Self, amount: Self::Scalar) -> Self { self + ((other - self) * amount) } + + /// Returns the + /// [vector projection](https://en.wikipedia.org/wiki/Vector_projection) + /// of the current inner space projected onto the supplied argument. + #[inline] + #[must_use] + fn project_on(self, other: Self) -> Self { + other * (self.dot(other) / other.magnitude2()) + } } /// Points in a [Euclidean space](https://en.wikipedia.org/wiki/Euclidean_space) diff --git a/tests/vector.rs b/tests/vector.rs index 7cb799b..852dede 100644 --- a/tests/vector.rs +++ b/tests/vector.rs @@ -248,6 +248,13 @@ fn test_normalize() { assert_ulps_eq!(Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64).normalize(), &Vector4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0)); } +#[test] +fn test_project_on() { + assert_ulps_eq!(Vector2::new(-1.0f64, 5.0).project_on(Vector2::new(2.0, 4.0)), &Vector2::new(9.0/5.0, 18.0/5.0)); + assert_ulps_eq!(Vector3::new(5.0f64, 6.0, 7.0).project_on(Vector3::new(1.0, 1.0, 1.0)), &Vector3::new(6.0, 6.0, 6.0)); + assert_ulps_eq!(Vector4::new(0.0f64, -5.0, 5.0, 5.0).project_on(Vector4::new(0.0, 1.0, 0.0, 0.5)), &Vector4::new(0.0, -2.0, 0.0, -1.0)); +} + #[test] fn test_cast() { assert_ulps_eq!(Vector2::new(0.9f64, 1.5).cast(), Vector2::new(0.9f32, 1.5));