From 7fd08542e9a47b2b6bfb2346174d6684044d5aaf Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Tue, 1 Dec 2015 15:48:02 -0500 Subject: [PATCH] This commit moves the library into a usable state. There is still some work to do with defining integers and whole numbers better, but for now the library is usable and reasonably tested. --- src/integer.rs | 17 ++ src/line.rs | 0 src/matrix.rs | 41 ++++ src/plane.rs | 0 src/point.rs | 0 src/quaternion.rs | 528 ++++++++++++++++++++++++++++++++++++++++++++++ src/ray.rs | 0 src/real.rs | 3 +- src/vector.rs | 174 ++++++++++++++- src/whole.rs | 13 +- 10 files changed, 770 insertions(+), 6 deletions(-) create mode 100644 src/line.rs create mode 100644 src/plane.rs create mode 100644 src/point.rs create mode 100644 src/ray.rs diff --git a/src/integer.rs b/src/integer.rs index 0559da4..7a60d32 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -4,7 +4,24 @@ use super::number::Number; /// A trait that defines what is required to be considered /// an Integer. [List of types of numbers][1] /// +/// This is meant to have all the similarities between +/// [u8][2], [u16][3], [u32][4], [u64][5], [usize][6], +/// [i8][7], [i16][8], [i32][9], [i64][10], [isize][11]. +/// Most of the comments and documentation were taken +/// from the [rust-lang std docs][12]. +/// /// [1]: https://en.wikipedia.org/wiki/List_of_types_of_numbers +/// [2]: https://doc.rust-lang.org/std/primitive.u8.html +/// [3]: https://doc.rust-lang.org/std/primitive.u16.html +/// [4]: https://doc.rust-lang.org/std/primitive.u32.html +/// [5]: https://doc.rust-lang.org/std/primitive.u64.html +/// [6]: https://doc.rust-lang.org/std/primitive.usize.html +/// [7]: https://doc.rust-lang.org/std/primitive.i8.html +/// [8]: https://doc.rust-lang.org/std/primitive.i16.html +/// [9]: https://doc.rust-lang.org/std/primitive.i32.html +/// [10]: https://doc.rust-lang.org/std/primitive.i64.html +/// [11]: https://doc.rust-lang.org/std/primitive.isize.html +/// [12]: https://doc.rust-lang.org/std/index.html pub trait Integer : Number { } diff --git a/src/line.rs b/src/line.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/matrix.rs b/src/matrix.rs index 44448f3..fc9e016 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -1 +1,42 @@ //! This module defines the 2x2, 3x3, and 4x4 Matrix structures. +use std::num::{Zero, One}; +use std::ops::{Add, Sub, Mul, Div, Rem, Neg}; + +use super::number::Number; +use super::vector::{Vector, Vector2, Vector3, Vector4}; + + +/// A trait that defines the minimum set of +/// functions a [Matrix][1] must implement. +/// +/// [1]: https://en.wikipedia.org/ +pub trait Matrix : Sized where T: Number, VT: Vector +{ + /// Create a Matrix with the given value set + /// for all the diagonal values. + fn from_value(value: T) -> Self; + + /// Create an Identity matrix. It will have 1 set + /// for all the diagonal values. + fn identity() -> Self + { + Self::from_value(T::one()) + } +} + + +macro_rules! define_matrix +{ + ($structName: ident <$T: ident>, $fieldType: ty {$($fieldName: ident),+}) => + { + pub struct $structName + { + $(pub $fieldName: $fieldType),+ + } + } +} + + +define_matrix!(Matrix2, Vector2 {x, y}); +define_matrix!(Matrix3, Vector3 {x, y, z}); +define_matrix!(Matrix4, Vector4 {x, y, z, w}); diff --git a/src/plane.rs b/src/plane.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/point.rs b/src/point.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/quaternion.rs b/src/quaternion.rs index 33f21ba..87d20ec 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -3,3 +3,531 @@ //! //! [1]: https://en.wikipedia.org/wiki/Quaternion //! [2]: https://en.wikipedia.org/wiki/Dual_quaternion +use std::num::{Zero, One}; +use std::ops::{Add, Sub, Mul, Div, Neg}; + +use super::real::Real; +use super::vector::{Vector, EuclideanVector, Vector3}; + + +/// A Quaternion is a combination of a scalar and a vector +/// of complex numbers. +/// +/// [S, V] = [S, Xi + Yj + Zk] +/// +/// Remember that the complex number axes combine +/// in the following manner. +/// +/// i^2 = j^2 = k^2 = -1 +/// +/// | | | +/// |:-------:|:-------:| +/// | ij = 1 | ik = -1 | +/// | jk = 1 | kj = -1 | +/// | ki = 1 | ji = -1 | +#[derive(Clone, Copy)] +pub struct Quaternion where T: Real +{ + /// TODO: Describe this. + pub scalar: T, + + /// TODO: Describe this. + pub vector: Vector3 +} + + +/// A macro that will define a binary operation +/// for a Quaternion and its components for +/// scalar values. +macro_rules! binary_operator_impl +{ + ($traitName: ident :: $funcName: ident, $structName: ident) => + { + impl $traitName for $structName where T: Real + { + type Output = $structName; + + fn $funcName(self, scalar: T) -> $structName + { + $structName::new(self.scalar.$funcName(scalar), + self.vector.$funcName(scalar)) + } + } + + impl<'a, T> $traitName for &'a $structName where T: Real + { + type Output = $structName; + + fn $funcName(self, scalar: T) -> $structName + { + $structName::new(self.scalar.$funcName(scalar), + self.vector.$funcName(scalar)) + } + } + + impl<'a, T> $traitName<&'a T> for $structName where T: Real + { + type Output = $structName; + + fn $funcName(self, scalar: &'a T) -> $structName + { + $structName::new(self.scalar.$funcName(*scalar), + self.vector.$funcName(*scalar)) + } + } + + impl<'a, 'b, T> $traitName<&'b T> for &'a $structName where T: Real + { + type Output = $structName; + + fn $funcName(self, scalar: &'b T) -> $structName + { + $structName::new(self.scalar.$funcName(*scalar), + self.vector.$funcName(*scalar)) + } + } + } +} + + +// Implement the Quaternion's methods. +impl Quaternion where T: Real +{ + /// Create a new Quaternion from a given scalar and Vector. + /// + ///``` + /// // Create a new Quaternion where all + /// // the components are 5.5f64. + /// use sigils::vector::*; + /// use sigils::quaternion::*; + /// + /// let quaternion = + /// Quaternion::::new(5.5f64, Vector3::new(5.5f64, 5.5f64, 5.5f64)); + /// # assert_eq!(quaternion.scalar, 5.5f64); + /// # assert_eq!(quaternion.vector.x, 5.5f64); + /// # assert_eq!(quaternion.vector.y, 5.5f64); + /// # assert_eq!(quaternion.vector.z, 5.5f64); + ///``` + pub fn new(s: T, v: Vector3) -> Quaternion + { + Quaternion {scalar: s, vector: v} + } + + /// Create a new Quaternion from the given values. + /// + ///``` + /// // Create a new Quaternion where all + /// // the components are 5.5f32. + /// use sigils::quaternion::*; + /// + /// let quaternion = + /// Quaternion::::from_values(5.5f32, 5.5f32, 5.5f32, 5.5f32); + /// # assert_eq!(quaternion.scalar, 5.5f32); + /// # assert_eq!(quaternion.vector.x, 5.5f32); + /// # assert_eq!(quaternion.vector.y, 5.5f32); + /// # assert_eq!(quaternion.vector.z, 5.5f32); + ///``` + pub fn from_values(s: T, xi: T, yj: T, zk: T) -> Quaternion + { + Quaternion::new(s, Vector3::new(xi, yj, zk)) + } + + /// Create an identity Quaternion. This is a Quaternion + /// with a zero Vector and a scalar of one. + /// + ///``` + /// // Create a new identity Quaternion. + /// use sigils::quaternion::*; + /// + /// let quaternion = + /// Quaternion::::identity(); + /// # assert_eq!(quaternion.scalar, 1.0f32); + /// # assert_eq!(quaternion.vector.x, 0.0f32); + /// # assert_eq!(quaternion.vector.y, 0.0f32); + /// # assert_eq!(quaternion.vector.z, 0.0f32); + ///``` + pub fn identity() -> Quaternion + { + Quaternion::new(T::one(), Vector3::zero()) + } + + /// Get the squared magnitude of the Quaternion. + /// This is basically a length equation. + /// + /// S^2 + V^2 + /// + ///``` + /// // Create a new Quaternion where all + /// // the components are 5.5f64 and get its + /// // squared magnitude. + /// use sigils::vector::*; + /// use sigils::quaternion::*; + /// + /// let quaternion = + /// Quaternion::::from_values(5.5f64, 5.5f64, 5.5f64, 5.5f64); + /// let magnitude = quaternion.get_magnitude_squared(); + /// # assert_eq!(magnitude, 121.0f64); + ///``` + pub fn get_magnitude_squared(&self) -> T + { + (self.scalar * self.scalar) + self.vector.get_length_squared() + } + + /// Get the magnitude of the Quaternion. + /// This is basically a length equation. + /// + ///``` + /// // Create a new Quaternion where all + /// // the components are 5.5f32 and get its + /// // magnitude. + /// use sigils::quaternion::*; + /// + /// let quaternion = + /// Quaternion::::from_values(5.5f32, 5.5f32, 5.5f32, 5.5f32); + /// let magnitude = quaternion.get_magnitude(); + /// # assert_eq!(magnitude, 11.0f32); + ///``` + pub fn get_magnitude(&self) -> T + { + let magnitude: T; + + // Calculate the magnitude for the Quaternion + // and make sure the magnitude is actually + // a number. + magnitude = self.get_magnitude_squared().sqrt(); + assert!(magnitude.is_finite()); + + // Return the calculated magnitude. + magnitude + } + + /// Set this Quaternion to the identity Quaternion. + /// This is a Quaternion with a zero Vector and + /// a scalar of one. + pub fn set_identity(&mut self) + { + self.scalar = T::one(); + self.vector = Vector3::zero(); + } + + /// Negates only the Vector component. + pub fn conjugate_self(&mut self) + { + self.vector = -self.vector; + } + + /// Normalizes this Quaternions values. + /// + /// [S/magnitude, V/magnitude] + pub fn normalize_self(&mut self) + { + let inverse_mag: T; + + // Get the inverse of the magnitude. + inverse_mag = T::one() / self.get_magnitude(); + + // Multily the scalar and Vector components + // by the inverse magnitude. + self.scalar = self.scalar * inverse_mag; + self.vector = self.vector * inverse_mag; + } + + /// Invert this Quaternion. + pub fn invert_self(&mut self) + { + // Conjugate this Quaternion + // and then normalize it. + self.conjugate_self(); + self.normalize_self(); + } + + /// Create a new Quaternion that is the same + /// as this Quaternion with a negated Vector component. + pub fn conjugate(&self) -> Quaternion + { + // Create a new Quaternion that has + // the same scalar component value and + // a negated version of the Vector component. + Quaternion::new(self.scalar.clone(), -self.vector.clone()) + } + + /// Create a new Quaternion that is a copy of this + /// Quaternion with normalized values. + /// + /// [S/magnitude, V/magnitude] + pub fn normalize(&self) -> Quaternion + { + let inverse_mag: T; + + inverse_mag = T::one() / self.get_magnitude(); + + self * inverse_mag + } + + /// Create a new Quaternion that is a normalized + /// conjugate of this Quaternion. + pub fn invert(&self) -> Quaternion + { + self.conjugate().normalize() + } + + // TODO: Add binary operations for editing self. +} + +// Implement the Zero and One traits for the Quaternion. +impl Zero for Quaternion where T: Real +{ + fn zero() -> Quaternion + { + Quaternion::new(T::zero(), Vector3::zero()) + } +} + +impl One for Quaternion where T: Real +{ + fn one() -> Quaternion + { + Quaternion::identity() + } +} + +// Implement the binary operations for Quaternions and scalars. +binary_operator_impl!(Mul::mul, Quaternion); +//binary_operator_impl!(Div::div, Quaternion); +//binary_operator_impl!(Neg::neg, Quaternion); + +// Implement Negating a Quaternion. +impl Neg for Quaternion where T: Real +{ + type Output = Quaternion; + + fn neg(self) -> Quaternion + { + Quaternion::new(-self.scalar, -self.vector) + } +} + +impl<'a, T> Neg for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn neg(self) -> Quaternion + { + Quaternion::new(-self.scalar, -self.vector) + } +} + +// Implement Adding Quaternions. +impl Add> for Quaternion where T: Real +{ + type Output = Quaternion; + + fn add(self, _rhs: Quaternion) -> Quaternion + { + Quaternion::new(self.scalar + _rhs.scalar, + self.vector + _rhs.vector) + } +} + +impl<'a, T> Add> for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn add(self, _rhs: Quaternion) -> Quaternion + { + Quaternion::new(self.scalar + _rhs.scalar, + self.vector + _rhs.vector) + } +} + +impl<'a, T> Add<&'a Quaternion> for Quaternion where T: Real +{ + type Output = Quaternion; + + fn add(self, _rhs: &'a Quaternion) -> Quaternion + { + Quaternion::new(self.scalar + _rhs.scalar, + self.vector + _rhs.vector) + } +} + +impl<'a, 'b, T> Add<&'b Quaternion> for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn add(self, _rhs: &'b Quaternion) -> Quaternion + { + Quaternion::new(self.scalar + _rhs.scalar, + self.vector + _rhs.vector) + } +} + +// Implement subtracting Quaternions. +impl Sub> for Quaternion where T: Real +{ + type Output = Quaternion; + + fn sub(self, _rhs: Quaternion) -> Quaternion + { + Quaternion::new(self.scalar - _rhs.scalar, + self.vector - _rhs.vector) + } +} + +impl<'a, T> Sub> for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn sub(self, _rhs: Quaternion) -> Quaternion + { + Quaternion::new(self.scalar - _rhs.scalar, + self.vector - _rhs.vector) + } +} + +impl<'a, T> Sub<&'a Quaternion> for Quaternion where T: Real +{ + type Output = Quaternion; + + fn sub(self, _rhs: &'a Quaternion) -> Quaternion + { + Quaternion::new(self.scalar - _rhs.scalar, + self.vector - _rhs.vector) + } +} + +impl<'a, 'b, T> Sub<&'b Quaternion> for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn sub(self, _rhs: &'b Quaternion) -> Quaternion + { + Quaternion::new(self.scalar - _rhs.scalar, + self.vector - _rhs.vector) + } +} + +// Implement Dividing Quaternions. +impl Div> for Quaternion where T: Real +{ + type Output = Quaternion; + + fn div(self, _rhs: Quaternion) -> Quaternion + { + self * _rhs.invert() + } +} + +impl<'a, T> Div> for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn div(self, _rhs: Quaternion) -> Quaternion + { + self * _rhs.invert() + } +} + +impl<'a, T> Div<&'a Quaternion> for Quaternion where T: Real +{ + type Output = Quaternion; + + fn div(self, _rhs: &'a Quaternion) -> Quaternion + { + self * _rhs.invert() + } +} + +impl<'a, 'b, T> Div<&'b Quaternion> for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn div(self, _rhs: &'b Quaternion) -> Quaternion + { + self * _rhs.invert() + } +} + +// Implement multiplying Quaternions and Vectors. +impl Mul> for Quaternion where T: Real +{ + type Output = Quaternion; + + fn mul(self, _rhs: Quaternion) -> Quaternion + { + multiply_quaternions(self.scalar, self.vector.x, + self.vector.y, self.vector.z, + _rhs.scalar, _rhs.vector.x, + _rhs.vector.y, _rhs.vector.z) + } +} + +impl<'a, T> Mul> for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn mul(self, _rhs: Quaternion) -> Quaternion + { + multiply_quaternions(self.scalar, self.vector.x, + self.vector.y, self.vector.z, + _rhs.scalar, _rhs.vector.x, + _rhs.vector.y, _rhs.vector.z) + } +} + +impl<'a, T> Mul<&'a Quaternion> for Quaternion where T: Real +{ + type Output = Quaternion; + + fn mul(self, _rhs: &'a Quaternion) -> Quaternion + { + multiply_quaternions(self.scalar, self.vector.x, + self.vector.y, self.vector.z, + _rhs.scalar, _rhs.vector.x, + _rhs.vector.y, _rhs.vector.z) + } +} + +impl<'a, 'b, T> Mul<&'b Quaternion> for &'a Quaternion where T: Real +{ + type Output = Quaternion; + + fn mul(self, _rhs: &'b Quaternion) -> Quaternion + { + multiply_quaternions(self.scalar, self.vector.x, + self.vector.y, self.vector.z, + _rhs.scalar, _rhs.vector.x, + _rhs.vector.y, _rhs.vector.z) + } +} + + + +/// This is a private function for multiplying the +/// values of two Quaternions. This was created to +/// follow the DRY principle. +/// +/// Qa = [Sa, A] = [Sa, Xai + Yaj + Zak] +/// Qb = [Sb, B] = [Sb, Xbi + Ybj + Zbk] +/// +/// QaQb = [Sa, A][Sb, B] = [Sa, Xai + Yaj + Zak][Sb, Xbi + Ybj + Zbk] +/// QaQb = (SaSb - XaXb - YaYb - ZaZb) + +/// (SaXb + XaSb + YaZb - ZaYb)i + +/// (SaYb - XaZb + SbYa + ZaXb)j + +/// (SaZb + XaYb - YaXb + SbZa)k +fn multiply_quaternions(sa: T, xa: T, ya: T, za: T, + sb: T, xb: T, yb: T, zb: T) + -> Quaternion where T: Real +{ + let i: T; + let j: T; + let k: T; + let scalar: T; + + i = (sa * xb) + (xa * sb) + (ya * zb) - (za * yb); + j = (sa * yb) - (xa * zb) + (ya * sb) + (za * xb); + k = (sa * zb) + (xa * yb) - (ya * xb) + (za * sb); + scalar = (sa * sb) - (xa * xb) - (ya * yb) - (za * zb); + + Quaternion::new(scalar, Vector3::new(i, j, k)) +} diff --git a/src/ray.rs b/src/ray.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/real.rs b/src/real.rs index d6eae8a..c36e338 100644 --- a/src/real.rs +++ b/src/real.rs @@ -1,4 +1,5 @@ use std::num::FpCategory; +use std::ops::Neg; use super::number::Number; @@ -17,7 +18,7 @@ use super::number::Number; /// [2]: https://doc.rust-lang.org/std/primitive.f32.html /// [3]: https://doc.rust-lang.org/std/primitive.f64.html /// [4]: https://doc.rust-lang.org/std/index.html -pub trait Real : Number +pub trait Real : Number + Neg { /// Returns the `NaN` value. /// diff --git a/src/vector.rs b/src/vector.rs index 9bc24fd..943c2f6 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -268,12 +268,35 @@ pub trait Vector : Clone where T: Number pub trait EuclideanVector : Vector where T: Real { /// Get the length of the Vector. + /// + ///``` + /// // Get the length of the Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector4::::new(5.5f32, 5.5f32, 5.5f32, 5.5f32); + /// let length = vector.get_length(); + /// # assert_eq!(length, 11.0f32); + ///``` fn get_length(&self) -> T { - self.dot(self).sqrt() + let length: T; + + length = self.dot(self).sqrt(); + assert!(length.is_finite()); + + length } /// Get the squared length of the Vector. + /// + ///``` + /// // Get the squared length of the Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector4::::new(5.5f32, 5.5f32, 5.5f32, 5.5f32); + /// let length = vector.get_length_squared(); + /// # assert_eq!(length, 121.0f32); + ///``` fn get_length_squared(&self) -> T { self.dot(self) @@ -281,6 +304,18 @@ pub trait EuclideanVector : Vector where T: Real /// Normalizes the Vector by multplying all the /// components by 1/|V|. + /// + ///``` + /// // Creae a Vector and normalize it. + /// use sigils::vector::*; + /// + /// let vector = Vector4::::new(5.0f32, 2.5f32, 5.5f32, 5.5f32); + /// let normal = vector.normalize(); + /// # assert_eq!(normal.x, 0.5219958f32); + /// # assert_eq!(normal.y, 0.2609979f32); + /// # assert_eq!(normal.z, 0.5741953f32); + /// # assert_eq!(normal.w, 0.5741953f32); + ///``` fn normalize(&self) -> Self { let mut new_vector: Self; @@ -292,6 +327,18 @@ pub trait EuclideanVector : Vector where T: Real /// Normalizes the Vector by multplying all the /// components by 1/|V|. + /// + ///``` + /// // Creae a Vector and normalize it. + /// use sigils::vector::*; + /// + /// let mut vector = Vector4::::new(5.0f32, 2.5f32, 5.5f32, 5.5f32); + /// vector.normalize_self(); + /// # assert_eq!(vector.x, 0.5219958f32); + /// # assert_eq!(vector.y, 0.2609979f32); + /// # assert_eq!(vector.z, 0.5741953f32); + /// # assert_eq!(vector.w, 0.5741953f32); + ///``` fn normalize_self(&mut self) { let length: T; @@ -301,6 +348,7 @@ pub trait EuclideanVector : Vector where T: Real } /// Determines if this Vector is perpendicular to another Vector. + // TODO: Add an example here. fn is_perpendicular_to(&self, vector: &Self) -> bool { // TODO: Make this work with a fudge factor since floats @@ -310,10 +358,12 @@ pub trait EuclideanVector : Vector where T: Real /// Calculates the angle between this vector and /// another Vector, in radians. + // TODO: Add an example here. fn angle(&self, vector: &Self) -> T; /// Linearly interpolate the length of this Vector /// towards the length of another Vector by a given amount. + // TODO: Add an example here. fn lerp(&self, vector: &Self, amount: T) -> Self { let mut temp: Self; @@ -330,6 +380,7 @@ pub trait EuclideanVector : Vector where T: Real /// Linearly interpolate the length of this Vector /// towards the length of another Vector by a given amount. + // TODO: Add an example here. fn lerp_self(&mut self, vector: &Self, amount: T) { let mut temp: Self; @@ -624,24 +675,55 @@ define_vector!(Vector4 {x, y, z, w}); impl Vector2 where T: Number { /// Create a unit Vector in the X direction. + /// + ///``` + /// // Create a new X unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector2::::unit_x(); + /// # assert_eq!(vector.x, 1.0f64); + /// # assert_eq!(vector.y, 0.0f64); + ///``` pub fn unit_x() -> Vector2 { Vector2::new(T::one(), T::zero()) } /// Create a unit Vector in the Y direction. + /// + ///``` + /// // Create a new Y unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector2::::unit_y(); + /// # assert_eq!(vector.x, 0.0f64); + /// # assert_eq!(vector.y, 1.0f64); + ///``` pub fn unit_y() -> Vector2 { Vector2::new(T::zero(), T::one()) } /// Calculate the perpendicular dot product. + // TODO: Add an example. pub fn perpendicular_dot(&self, vector: &Vector2) -> T { (self.x * vector.y) - (self.y * vector.x) } /// Adds a z component with the given value to the Vector. + /// + ///``` + /// // Create a new Vector2 X unit Vector and + /// // extend it to a Vector3. + /// use sigils::vector::*; + /// + /// let vector = Vector2::::unit_x(); + /// let biggerVec = vector.extend(6.5f32); + /// # assert_eq!(biggerVec.x, 1.0f32); + /// # assert_eq!(biggerVec.y, 0.0f32); + /// # assert_eq!(biggerVec.z, 6.5f32); + ///``` pub fn extend(&self, val: T) -> Vector3 { Vector3::new(self.x, self.y, val) @@ -651,18 +733,48 @@ impl Vector2 where T: Number impl Vector3 where T: Number { /// Create a unit Vector in the X direction. + /// + ///``` + /// // Create a new X unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector3::::unit_x(); + /// # assert_eq!(vector.x, 1.0f64); + /// # assert_eq!(vector.y, 0.0f64); + /// # assert_eq!(vector.z, 0.0f64); + ///``` pub fn unit_x() -> Vector3 { Vector3::new(T::one(), T::zero(), T::zero()) } /// Create a unit Vector in the Y direction. + /// + ///``` + /// // Create a new Y unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector3::::unit_y(); + /// # assert_eq!(vector.x, 0.0f64); + /// # assert_eq!(vector.y, 1.0f64); + /// # assert_eq!(vector.z, 0.0f64); + ///``` pub fn unit_y() -> Vector3 { Vector3::new(T::zero(), T::one(), T::zero()) } /// Create a unit Vector in the Z direction. + /// + ///``` + /// // Create a new Z unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector3::::unit_z(); + /// # assert_eq!(vector.x, 0.0f64); + /// # assert_eq!(vector.y, 0.0f64); + /// # assert_eq!(vector.z, 1.0f64); + ///``` pub fn unit_z() -> Vector3 { Vector3::new(T::zero(), T::zero(), T::one()) @@ -687,6 +799,19 @@ impl Vector3 where T: Number } /// Adds a w component with the given value to the Vector. + /// + ///``` + /// // Create a new Vector3 X unit Vector and + /// // extend it to a Vector4. + /// use sigils::vector::*; + /// + /// let vector = Vector3::::unit_x(); + /// let biggerVec = vector.extend(6.5f32); + /// # assert_eq!(biggerVec.x, 1.0f32); + /// # assert_eq!(biggerVec.y, 0.0f32); + /// # assert_eq!(biggerVec.z, 0.0f32); + /// # assert_eq!(biggerVec.w, 6.5f32); + ///``` pub fn extend(&self, val: T) -> Vector4 { Vector4::new(self.x, self.y, self.z, val) @@ -714,24 +839,68 @@ impl Vector3 where T: Number impl Vector4 where T: Number { /// Create a unit Vector in the X direction. + /// + ///``` + /// // Create a new X unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector4::::unit_x(); + /// # assert_eq!(vector.x, 1.0f64); + /// # assert_eq!(vector.y, 0.0f64); + /// # assert_eq!(vector.z, 0.0f64); + /// # assert_eq!(vector.w, 0.0f64); + ///``` pub fn unit_x() -> Vector4 { Vector4::new(T::one(), T::zero(), T::zero(), T::zero()) } /// Create a unit Vector in the Y direction. + /// + ///``` + /// // Create a new Y unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector4::::unit_y(); + /// # assert_eq!(vector.x, 0.0f64); + /// # assert_eq!(vector.y, 1.0f64); + /// # assert_eq!(vector.z, 0.0f64); + /// # assert_eq!(vector.w, 0.0f64); + ///``` pub fn unit_y() -> Vector4 { Vector4::new(T::zero(), T::one(), T::zero(), T::zero()) } /// Create a unit Vector in the Z direction. + /// + ///``` + /// // Create a new Z unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector4::::unit_z(); + /// # assert_eq!(vector.x, 0.0f64); + /// # assert_eq!(vector.y, 0.0f64); + /// # assert_eq!(vector.z, 1.0f64); + /// # assert_eq!(vector.w, 0.0f64); + ///``` pub fn unit_z() -> Vector4 { Vector4::new(T::zero(), T::zero(), T::one(), T::zero()) } /// Create a unit Vector in the W direction. + /// + ///``` + /// // Create a new W unit Vector. + /// use sigils::vector::*; + /// + /// let vector = Vector4::::unit_w(); + /// # assert_eq!(vector.x, 0.0f64); + /// # assert_eq!(vector.y, 0.0f64); + /// # assert_eq!(vector.z, 0.0f64); + /// # assert_eq!(vector.w, 1.0f64); + ///``` pub fn unit_w() -> Vector4 { Vector4::new(T::zero(), T::zero(), T::zero(), T::one()) @@ -762,7 +931,6 @@ impl EuclideanVector for Vector2 where T: Real { fn angle(&self, vector: &Vector2) -> T { - //unimplemented!(); atan2(self.perpendicular_dot(vector), self.dot(vector)) } } @@ -771,7 +939,6 @@ impl EuclideanVector for Vector3 where T: Real { fn angle(&self, vector: &Vector3) -> T { - //unimplemented!(); atan2(self.cross(vector).get_length(), self.dot(vector)) } } @@ -780,7 +947,6 @@ impl EuclideanVector for Vector4 where T: Real { fn angle(&self, vector: &Vector4) -> T { - //unimplemented!(); acos(self.dot(vector) / (self.get_length() * vector.get_length())) } } diff --git a/src/whole.rs b/src/whole.rs index f0de073..2eadd7e 100644 --- a/src/whole.rs +++ b/src/whole.rs @@ -4,8 +4,19 @@ use super::number::Number; /// A trait that defines what is required to be considered /// a Whole number. [List of types of numbers][1] /// +/// This is meant to have all the similarities between +/// [u8][2], [u16][3], [u32][4], [u64][5], and [usize][6]. +/// Most of the comments and documentation were taken +/// from the [rust-lang std docs][7]. +/// /// [1]: https://en.wikipedia.org/wiki/List_of_types_of_numbers -trait Whole : Number +/// [2]: https://doc.rust-lang.org/std/primitive.u8.html +/// [3]: https://doc.rust-lang.org/std/primitive.u16.html +/// [4]: https://doc.rust-lang.org/std/primitive.u32.html +/// [5]: https://doc.rust-lang.org/std/primitive.u64.html +/// [6]: https://doc.rust-lang.org/std/primitive.usize.html +/// [7]: https://doc.rust-lang.org/std/index.html +pub trait Whole : Number { }