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.
This commit is contained in:
Jason Smith 2015-12-01 15:48:02 -05:00
parent 7ae702fd5c
commit 7fd08542e9
10 changed files with 770 additions and 6 deletions

View File

@ -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
{
}

0
src/line.rs Normal file
View File

View File

@ -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<T, VT> : Sized where T: Number, VT: Vector<T>
{
/// 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<T>
{
$(pub $fieldName: $fieldType),+
}
}
}
define_matrix!(Matrix2<T>, Vector2<T> {x, y});
define_matrix!(Matrix3<T>, Vector3<T> {x, y, z});
define_matrix!(Matrix4<T>, Vector4<T> {x, y, z, w});

0
src/plane.rs Normal file
View File

0
src/point.rs Normal file
View File

View File

@ -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<T> where T: Real
{
/// TODO: Describe this.
pub scalar: T,
/// TODO: Describe this.
pub vector: Vector3<T>
}
/// 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<T> $traitName<T> for $structName<T> where T: Real
{
type Output = $structName<T>;
fn $funcName(self, scalar: T) -> $structName<T>
{
$structName::new(self.scalar.$funcName(scalar),
self.vector.$funcName(scalar))
}
}
impl<'a, T> $traitName<T> for &'a $structName<T> where T: Real
{
type Output = $structName<T>;
fn $funcName(self, scalar: T) -> $structName<T>
{
$structName::new(self.scalar.$funcName(scalar),
self.vector.$funcName(scalar))
}
}
impl<'a, T> $traitName<&'a T> for $structName<T> where T: Real
{
type Output = $structName<T>;
fn $funcName(self, scalar: &'a T) -> $structName<T>
{
$structName::new(self.scalar.$funcName(*scalar),
self.vector.$funcName(*scalar))
}
}
impl<'a, 'b, T> $traitName<&'b T> for &'a $structName<T> where T: Real
{
type Output = $structName<T>;
fn $funcName(self, scalar: &'b T) -> $structName<T>
{
$structName::new(self.scalar.$funcName(*scalar),
self.vector.$funcName(*scalar))
}
}
}
}
// Implement the Quaternion's methods.
impl<T> Quaternion<T> where T: Real
{
/// Create a new Quaternion from a given scalar and Vector.
///
///```
/// // Create a new Quaternion<f64> where all
/// // the components are 5.5f64.
/// use sigils::vector::*;
/// use sigils::quaternion::*;
///
/// let quaternion =
/// Quaternion::<f64>::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<T>) -> Quaternion<T>
{
Quaternion {scalar: s, vector: v}
}
/// Create a new Quaternion from the given values.
///
///```
/// // Create a new Quaternion<f32> where all
/// // the components are 5.5f32.
/// use sigils::quaternion::*;
///
/// let quaternion =
/// Quaternion::<f32>::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<T>
{
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<f32>.
/// use sigils::quaternion::*;
///
/// let quaternion =
/// Quaternion::<f32>::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<T>
{
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<f64> where all
/// // the components are 5.5f64 and get its
/// // squared magnitude.
/// use sigils::vector::*;
/// use sigils::quaternion::*;
///
/// let quaternion =
/// Quaternion::<f64>::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<f32> where all
/// // the components are 5.5f32 and get its
/// // magnitude.
/// use sigils::quaternion::*;
///
/// let quaternion =
/// Quaternion::<f32>::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<T>
{
// 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<T>
{
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<T>
{
self.conjugate().normalize()
}
// TODO: Add binary operations for editing self.
}
// Implement the Zero and One traits for the Quaternion.
impl<T> Zero for Quaternion<T> where T: Real
{
fn zero() -> Quaternion<T>
{
Quaternion::new(T::zero(), Vector3::zero())
}
}
impl<T> One for Quaternion<T> where T: Real
{
fn one() -> Quaternion<T>
{
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<T> Neg for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn neg(self) -> Quaternion<T>
{
Quaternion::new(-self.scalar, -self.vector)
}
}
impl<'a, T> Neg for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn neg(self) -> Quaternion<T>
{
Quaternion::new(-self.scalar, -self.vector)
}
}
// Implement Adding Quaternions.
impl<T> Add<Quaternion<T>> for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn add(self, _rhs: Quaternion<T>) -> Quaternion<T>
{
Quaternion::new(self.scalar + _rhs.scalar,
self.vector + _rhs.vector)
}
}
impl<'a, T> Add<Quaternion<T>> for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn add(self, _rhs: Quaternion<T>) -> Quaternion<T>
{
Quaternion::new(self.scalar + _rhs.scalar,
self.vector + _rhs.vector)
}
}
impl<'a, T> Add<&'a Quaternion<T>> for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn add(self, _rhs: &'a Quaternion<T>) -> Quaternion<T>
{
Quaternion::new(self.scalar + _rhs.scalar,
self.vector + _rhs.vector)
}
}
impl<'a, 'b, T> Add<&'b Quaternion<T>> for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn add(self, _rhs: &'b Quaternion<T>) -> Quaternion<T>
{
Quaternion::new(self.scalar + _rhs.scalar,
self.vector + _rhs.vector)
}
}
// Implement subtracting Quaternions.
impl<T> Sub<Quaternion<T>> for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn sub(self, _rhs: Quaternion<T>) -> Quaternion<T>
{
Quaternion::new(self.scalar - _rhs.scalar,
self.vector - _rhs.vector)
}
}
impl<'a, T> Sub<Quaternion<T>> for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn sub(self, _rhs: Quaternion<T>) -> Quaternion<T>
{
Quaternion::new(self.scalar - _rhs.scalar,
self.vector - _rhs.vector)
}
}
impl<'a, T> Sub<&'a Quaternion<T>> for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn sub(self, _rhs: &'a Quaternion<T>) -> Quaternion<T>
{
Quaternion::new(self.scalar - _rhs.scalar,
self.vector - _rhs.vector)
}
}
impl<'a, 'b, T> Sub<&'b Quaternion<T>> for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn sub(self, _rhs: &'b Quaternion<T>) -> Quaternion<T>
{
Quaternion::new(self.scalar - _rhs.scalar,
self.vector - _rhs.vector)
}
}
// Implement Dividing Quaternions.
impl<T> Div<Quaternion<T>> for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn div(self, _rhs: Quaternion<T>) -> Quaternion<T>
{
self * _rhs.invert()
}
}
impl<'a, T> Div<Quaternion<T>> for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn div(self, _rhs: Quaternion<T>) -> Quaternion<T>
{
self * _rhs.invert()
}
}
impl<'a, T> Div<&'a Quaternion<T>> for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn div(self, _rhs: &'a Quaternion<T>) -> Quaternion<T>
{
self * _rhs.invert()
}
}
impl<'a, 'b, T> Div<&'b Quaternion<T>> for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn div(self, _rhs: &'b Quaternion<T>) -> Quaternion<T>
{
self * _rhs.invert()
}
}
// Implement multiplying Quaternions and Vectors.
impl<T> Mul<Quaternion<T>> for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn mul(self, _rhs: Quaternion<T>) -> Quaternion<T>
{
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<Quaternion<T>> for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn mul(self, _rhs: Quaternion<T>) -> Quaternion<T>
{
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<T>> for Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn mul(self, _rhs: &'a Quaternion<T>) -> Quaternion<T>
{
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<T>> for &'a Quaternion<T> where T: Real
{
type Output = Quaternion<T>;
fn mul(self, _rhs: &'b Quaternion<T>) -> Quaternion<T>
{
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<T>(sa: T, xa: T, ya: T, za: T,
sb: T, xb: T, yb: T, zb: T)
-> Quaternion<T> 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))
}

0
src/ray.rs Normal file
View File

View File

@ -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<Output=Self>
{
/// Returns the `NaN` value.
///

View File

@ -268,12 +268,35 @@ pub trait Vector<T> : Clone where T: Number
pub trait EuclideanVector<T> : Vector<T> where T: Real
{
/// Get the length of the Vector.
///
///```
/// // Get the length of the Vector.
/// use sigils::vector::*;
///
/// let vector = Vector4::<f32>::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::<f32>::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<T> : Vector<T> 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::<f32>::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<T> : Vector<T> 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::<f32>::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<T> : Vector<T> 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<T> : Vector<T> 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<T> : Vector<T> 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<T> {x, y, z, w});
impl<T> Vector2<T> where T: Number
{
/// Create a unit Vector in the X direction.
///
///```
/// // Create a new X unit Vector.
/// use sigils::vector::*;
///
/// let vector = Vector2::<f64>::unit_x();
/// # assert_eq!(vector.x, 1.0f64);
/// # assert_eq!(vector.y, 0.0f64);
///```
pub fn unit_x() -> Vector2<T>
{
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::<f64>::unit_y();
/// # assert_eq!(vector.x, 0.0f64);
/// # assert_eq!(vector.y, 1.0f64);
///```
pub fn unit_y() -> Vector2<T>
{
Vector2::new(T::zero(), T::one())
}
/// Calculate the perpendicular dot product.
// TODO: Add an example.
pub fn perpendicular_dot(&self, vector: &Vector2<T>) -> 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::<f32>::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<T>
{
Vector3::new(self.x, self.y, val)
@ -651,18 +733,48 @@ impl<T> Vector2<T> where T: Number
impl<T> Vector3<T> where T: Number
{
/// Create a unit Vector in the X direction.
///
///```
/// // Create a new X unit Vector.
/// use sigils::vector::*;
///
/// let vector = Vector3::<f64>::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<T>
{
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::<f64>::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<T>
{
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::<f64>::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<T>
{
Vector3::new(T::zero(), T::zero(), T::one())
@ -687,6 +799,19 @@ impl<T> Vector3<T> 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::<f32>::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<T>
{
Vector4::new(self.x, self.y, self.z, val)
@ -714,24 +839,68 @@ impl<T> Vector3<T> where T: Number
impl<T> Vector4<T> where T: Number
{
/// Create a unit Vector in the X direction.
///
///```
/// // Create a new X unit Vector.
/// use sigils::vector::*;
///
/// let vector = Vector4::<f64>::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<T>
{
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::<f64>::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<T>
{
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::<f64>::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<T>
{
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::<f64>::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<T>
{
Vector4::new(T::zero(), T::zero(), T::zero(), T::one())
@ -762,7 +931,6 @@ impl<T> EuclideanVector<T> for Vector2<T> where T: Real
{
fn angle(&self, vector: &Vector2<T>) -> T
{
//unimplemented!();
atan2(self.perpendicular_dot(vector), self.dot(vector))
}
}
@ -771,7 +939,6 @@ impl<T> EuclideanVector<T> for Vector3<T> where T: Real
{
fn angle(&self, vector: &Vector3<T>) -> T
{
//unimplemented!();
atan2(self.cross(vector).get_length(), self.dot(vector))
}
}
@ -780,7 +947,6 @@ impl<T> EuclideanVector<T> for Vector4<T> where T: Real
{
fn angle(&self, vector: &Vector4<T>) -> T
{
//unimplemented!();
acos(self.dot(vector) / (self.get_length() * vector.get_length()))
}
}

View File

@ -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
{
}