Skip to content

Commit

Permalink
Add cross and dot for Vector2d and Vector3d (#112)
Browse files Browse the repository at this point in the history
  • Loading branch information
sunsided authored Jul 17, 2024
1 parent e41846f commit 2e01dcc
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 10 deletions.
2 changes: 0 additions & 2 deletions src/quaternion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ impl Quaternion {
C: Component + Into<f32>,
{
// Implementation from http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
use crate::vector::Vector;

let n_uv = F32(u.dot(u).into() * v.dot(v).into()).sqrt();
let mut realpart = n_uv + u.dot(v).into();

Expand Down
64 changes: 62 additions & 2 deletions src/vector/vector2d.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! 2-dimensional vector

use super::{Component, Vector};
use super::{Component, Vector, Vector3d};
use core::{
iter::FromIterator,
ops::{Add, AddAssign, Index, Mul, MulAssign, Sub, SubAssign},
Expand Down Expand Up @@ -46,6 +46,31 @@ where
pub fn to_array(&self) -> [C; 2] {
[self.x, self.y]
}

/// Calculates the inner product.
pub fn dot(self, rhs: Self) -> C {
(self.x * rhs.x) + (self.y * rhs.y)
}

/// Calculates the perpendicular dot product.
///
/// This value can be understood as the `z` component of the [`cross`](Self::cross) product
/// between two `Vector2d` instances in 3D space, or the signed area of the parallelogram
/// formed by the two vectors.
///
/// This value can be used to perform side tests without having to promote the vectors
/// into [`Vector3d`] instances.
pub fn perpendicular_dot(self, rhs: Self) -> C {
(self.x * rhs.y) - (self.y * rhs.x)
}

/// Calculates the outer product.
///
/// Note that due to tye type of operation, the result is a [`Vector3d`], not a `Vector2d`.
/// See also [`perpendicular_dot`](Self::perpendicular_dot) for a simplified version.
pub fn cross(&self, rhs: Self) -> Vector3d<C> {
Vector3d::from(*self) * Vector3d::from(rhs)
}
}

impl<C> FromIterator<C> for Vector2d<C>
Expand Down Expand Up @@ -85,7 +110,7 @@ where
}

fn dot(self, rhs: Self) -> C {
(self.x * rhs.x) + (self.y * rhs.y)
self.dot(rhs)
}
}

Expand Down Expand Up @@ -206,6 +231,17 @@ where
}
}

impl<C> Mul<Vector2d<C>> for Vector2d<C>
where
C: Component,
{
type Output = Vector3d<C>;

fn mul(self, rhs: Vector2d<C>) -> Vector3d<C> {
self.cross(rhs)
}
}

impl<C> MulAssign<C> for Vector2d<C>
where
C: Component,
Expand Down Expand Up @@ -287,4 +323,28 @@ mod tests {
assert_eq!(arr[0], 1);
assert_eq!(arr[1], 2);
}

#[test]
fn cross() {
let lhs = Vector2d { x: 1, y: 2 };
let rhs = Vector2d { x: 3, y: 4 };
let cross = lhs.cross(rhs);
assert_eq!(cross.x, 0);
assert_eq!(cross.y, 0);
assert_eq!(cross.z, -2);

let mul = lhs * rhs;
assert_eq!(mul, cross);

let perp_dot = lhs.perpendicular_dot(rhs);
assert_eq!(perp_dot, cross.z);
}

#[test]
fn dot() {
let lhs = Vector2d { x: 1, y: 2 };
let rhs = Vector2d { x: 3, y: 4 };
let dot = lhs.dot(rhs);
assert_eq!(dot, 11);
}
}
57 changes: 51 additions & 6 deletions src/vector/vector3d.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! 3-dimensional vector

use super::{Component, Vector};
use super::{Component, Vector, Vector2d};
use crate::F32;
use core::{
iter::FromIterator,
Expand Down Expand Up @@ -50,6 +50,20 @@ where
pub fn to_array(&self) -> [C; 3] {
[self.x, self.y, self.z]
}

/// Calculates the inner product.
pub fn dot(self, rhs: Self) -> C {
(self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
}

/// Calculates the outer product.
pub fn cross(&self, rhs: Self) -> Vector3d<C> {
Self {
x: (self.y * rhs.z) - (self.z * rhs.y),
y: (self.z * rhs.x) - (self.x * rhs.z),
z: (self.x * rhs.y) - (self.y * rhs.x),
}
}
}

impl<C> FromIterator<C> for Vector3d<C>
Expand Down Expand Up @@ -95,6 +109,20 @@ where
}
}

impl<C> From<Vector2d<C>> for Vector3d<C>
where
C: Component,
{
fn from(vector: Vector2d<C>) -> Self {
let zero = C::default();
Self {
x: vector.x,
y: vector.y,
z: zero,
}
}
}

impl<C> From<(C, C, C)> for Vector3d<C>
where
C: Component,
Expand Down Expand Up @@ -211,11 +239,7 @@ where
type Output = Self;

fn mul(self, rhs: Self) -> Self {
Self {
x: (self.y * rhs.z) - (self.z * rhs.y),
y: (self.z * rhs.x) - (self.x * rhs.z),
z: (self.x * rhs.y) - (self.y * rhs.x),
}
self.cross(rhs)
}
}

Expand Down Expand Up @@ -334,4 +358,25 @@ mod tests {
assert_eq!(arr[1], 2);
assert_eq!(arr[2], 3);
}

#[test]
fn cross() {
let lhs = Vector3d { x: 1, y: 2, z: 3 };
let rhs = Vector3d { x: 4, y: 5, z: 6 };
let cross = lhs.cross(rhs);
assert_eq!(cross.x, -3);
assert_eq!(cross.y, 6);
assert_eq!(cross.z, -3);

let mul = lhs * rhs;
assert_eq!(mul, cross);
}

#[test]
fn dot() {
let lhs = Vector3d { x: 1, y: 2, z: 3 };
let rhs = Vector3d { x: 4, y: 5, z: 6 };
let dot = lhs.dot(rhs);
assert_eq!(dot, 32);
}
}

0 comments on commit 2e01dcc

Please sign in to comment.