Merge branch 'master' of https://github.com/kvark/cgmath-rs into kvark-master

Conflicts:
	src/tests/plane.rs
	src/tests/vector.rs
This commit is contained in:
Brendan Zabarauskas 2013-11-03 14:59:28 +11:00
commit 9e053f22f8
13 changed files with 376 additions and 136 deletions

View file

@ -44,6 +44,18 @@ pub trait Array
fn each_mut(&mut self, f: &fn(i: uint, x: &mut T)); fn each_mut(&mut self, f: &fn(i: uint, x: &mut T));
} }
/*impl //TODO
<
T: Clone,
Slice,
A: Array<T,Slice>
>
Clone for A {
fn clone(&self) -> A {
self.build(|i| self.i(i).clone())
}
}*/
macro_rules! array( macro_rules! array(
(impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr] $_n:ident) => ( (impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr] $_n:ident) => (
impl<$S: Clone> Array<$T, [$T,..$n]> for $Self { impl<$S: Clone> Array<$T, [$T,..$n]> for $Self {

View file

@ -14,6 +14,7 @@
// limitations under the License. // limitations under the License.
use std::cast::transmute; use std::cast::transmute;
use std::fmt;
use intersect::Intersect; use intersect::Intersect;
use point::{Point, Point3}; use point::{Point, Point3};
@ -21,8 +22,6 @@ use ray::Ray3;
use vector::{Vec3, Vec4}; use vector::{Vec3, Vec4};
use vector::{Vector, EuclideanVector}; use vector::{Vector, EuclideanVector};
use std::fmt;
/// A 3-dimendional plane formed from the equation: `a*x + b*y + c*z - d = 0`. /// A 3-dimendional plane formed from the equation: `a*x + b*y + c*z - d = 0`.
/// ///
/// # Fields /// # Fields

View file

@ -18,7 +18,7 @@
//! not have a fixed position. //! not have a fixed position.
use std::fmt; use std::fmt;
use std::num::zero; use std::num::{one,zero};
use array::*; use array::*;
use vector::*; use vector::*;
@ -54,6 +54,19 @@ impl<S: Num> Point3<S> {
pub fn origin() -> Point3<S> { zero() } pub fn origin() -> Point3<S> { zero() }
} }
impl<S: Clone + Num + Primitive> Point3<S> {
#[inline]
pub fn from_homogeneous(v: &Vec4<S>) -> Point3<S> {
let _1 :S = one();
let e = v.truncate().mul_s( _1 / v.w );
Point3::new(e.x.clone(), e.y.clone(), e.z.clone()) //FIXME
}
#[inline]
pub fn to_homogeneous(&self) -> Vec4<S> {
Vec4::new(self.x.clone(), self.y.clone(), self.z.clone(), one())
}
}
/// Specifies the numeric operations for point types. /// Specifies the numeric operations for point types.
pub trait Point pub trait Point
< <

View file

@ -13,33 +13,29 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use point::{Point2, Point3}; use point::{Point, Point2, Point3};
use vector::{Vec2, Vec3}; use vector::{Vector, Vec2, Vec3};
/// A generic ray
#[deriving(Clone, Eq)] #[deriving(Clone, Eq)]
pub struct Ray2<S> { pub struct Ray<P,V>
origin: Point2<S>, {
direction: Vec2<S>, origin: P,
direction: V,
} }
impl<S> Ray2<S> { impl
/// Creates a new ray from a position coordinate and a direction vector <
#[inline] S: Primitive,
pub fn new(origin: Point2<S>, direction: Vec2<S>) -> Ray2<S> { Slice,
Ray2 { origin: origin, direction: direction } V: Vector<S,Slice>,
P: Point<S,V,Slice>
> Ray<P,V>
{
pub fn new(origin: P, direction: V) -> Ray<P,V> {
Ray { origin:origin, direction:direction }
} }
} }
#[deriving(Clone, Eq)] pub type Ray2<S> = Ray<Point2<S>,Vec2<S>>;
pub struct Ray3<S> { pub type Ray3<S> = Ray<Point3<S>,Vec3<S>>;
origin: Point3<S>,
direction: Vec3<S>,
}
impl<S> Ray3<S> {
/// Creates a new ray from a position coordinate and a direction vector
#[inline]
pub fn new(origin: Point3<S>, direction: Vec3<S>) -> Ray3<S> {
Ray3 { origin: origin, direction: direction }
}
}

View file

@ -14,52 +14,72 @@
// limitations under the License. // limitations under the License.
use angle::Rad; use angle::Rad;
use array::Array;
use matrix::Matrix; use matrix::Matrix;
use matrix::{Mat2, ToMat2}; use matrix::{Mat2, ToMat2};
use matrix::{Mat3, ToMat3}; use matrix::{Mat3, ToMat3};
use point::{Point2, Point3}; use point::{Point, Point2, Point3};
use quaternion::{Quat, ToQuat}; use quaternion::{Quat, ToQuat};
use ray::{Ray2, Ray3}; use ray::{Ray, Ray2, Ray3};
use vector::{Vector, Vec2, Vec3}; use vector::{Vector, Vec2, Vec3};
/// A trait for generic rotation
pub trait Rotation
<
S: Primitive,
Slice,
V: Vector<S,Slice>,
P: Point<S,V,Slice>
>
: Eq
+ ApproxEq<S>
{
fn identity() -> Self;
fn rotate_point(&self, point: &P) -> P;
fn rotate_vec(&self, vec: &V) -> V;
#[inline]
fn rotate_ray(&self, ray: &Ray<P,V>) -> Ray<P,V> {
Ray::new( //FIXME: use clone derived from Array
Array::build(|i| ray.origin.i(i).clone()),
self.rotate_vec(&ray.direction) )
}
fn concat(&self, other: &Self) -> Self;
fn invert(&self) -> Self;
#[inline]
fn concat_self(&mut self, other: &Self) {
*self = self.concat(other);
}
#[inline]
fn invert_self(&mut self) {
*self = self.invert();
}
}
/// A two-dimensional rotation /// A two-dimensional rotation
pub trait Rotation2 pub trait Rotation2
< <
S S
> >
: Eq : Rotation<S, [S, ..2], Vec2<S>, Point2<S>>
+ ApproxEq<S>
+ ToMat2<S> + ToMat2<S>
+ ToBasis2<S> + ToBasis2<S>
{ {}
fn rotate_point2(&self, point: &Point2<S>) -> Point2<S>;
fn rotate_vec2(&self, vec: &Vec2<S>) -> Vec2<S>;
fn rotate_ray2(&self, ray: &Ray2<S>) -> Ray2<S>;
fn concat(&self, other: &Self) -> Self;
fn concat_self(&mut self, other: &Self);
fn invert(&self) -> Self;
fn invert_self(&mut self);
}
/// A three-dimensional rotation /// A three-dimensional rotation
pub trait Rotation3 pub trait Rotation3
< <
S S
> >
: Eq : Rotation<S, [S, ..3], Vec3<S>, Point3<S>>
+ ApproxEq<S>
+ ToMat3<S> + ToMat3<S>
+ ToBasis3<S> + ToBasis3<S>
+ ToQuat<S> + ToQuat<S>
{ {}
fn rotate_point3(&self, point: &Point3<S>) -> Point3<S>;
fn rotate_vec3(&self, vec: &Vec3<S>) -> Vec3<S>;
fn rotate_ray3(&self, ray: &Ray3<S>) -> Ray3<S>;
fn concat(&self, other: &Self) -> Self;
fn concat_self(&mut self, other: &Self);
fn invert(&self) -> Self;
fn invert_self(&mut self);
}
/// A two-dimensional rotation matrix. /// A two-dimensional rotation matrix.
/// ///
@ -91,15 +111,18 @@ impl<S: Float> ToMat2<S> for Basis2<S> {
fn to_mat2(&self) -> Mat2<S> { self.mat.clone() } fn to_mat2(&self) -> Mat2<S> { self.mat.clone() }
} }
impl<S: Float> Rotation2<S> for Basis2<S> { impl<S: Float> Rotation<S, [S, ..2], Vec2<S>, Point2<S>> for Basis2<S> {
#[inline] #[inline]
fn rotate_point2(&self, _point: &Point2<S>) -> Point2<S> { fail!("Not yet implemented") } fn identity() -> Basis2<S> { Basis2{ mat: Mat2::identity() } }
#[inline]
fn rotate_point(&self, _point: &Point2<S>) -> Point2<S> { fail!("Not yet implemented") }
#[inline] #[inline]
fn rotate_vec2(&self, vec: &Vec2<S>) -> Vec2<S> { self.mat.mul_v(vec) } fn rotate_vec(&self, vec: &Vec2<S>) -> Vec2<S> { self.mat.mul_v(vec) }
#[inline] #[inline]
fn rotate_ray2(&self, _ray: &Ray2<S>) -> Ray2<S> { fail!("Not yet implemented") } fn rotate_ray(&self, _ray: &Ray2<S>) -> Ray2<S> { fail!("Not yet implemented") }
#[inline] #[inline]
fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat.mul_m(&other.mat) } } fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat.mul_m(&other.mat) } }
@ -136,6 +159,8 @@ impl<S: Float> ApproxEq<S> for Basis2<S> {
} }
} }
impl<S: Float> Rotation2<S> for Basis2<S> {}
/// A three-dimensional rotation matrix. /// A three-dimensional rotation matrix.
/// ///
/// The matrix is guaranteed to be orthogonal, so some operations, specifically /// The matrix is guaranteed to be orthogonal, so some operations, specifically
@ -207,15 +232,18 @@ impl<S: Float> ToQuat<S> for Basis3<S> {
fn to_quat(&self) -> Quat<S> { self.mat.to_quat() } fn to_quat(&self) -> Quat<S> { self.mat.to_quat() }
} }
impl<S: Float> Rotation3<S> for Basis3<S> { impl<S: Float> Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Basis3<S> {
#[inline] #[inline]
fn rotate_point3(&self, _point: &Point3<S>) -> Point3<S> { fail!("Not yet implemented") } fn identity() -> Basis3<S> { Basis3{ mat: Mat3::identity() } }
#[inline]
fn rotate_point(&self, _point: &Point3<S>) -> Point3<S> { fail!("Not yet implemented") }
#[inline] #[inline]
fn rotate_vec3(&self, vec: &Vec3<S>) -> Vec3<S> { self.mat.mul_v(vec) } fn rotate_vec(&self, vec: &Vec3<S>) -> Vec3<S> { self.mat.mul_v(vec) }
#[inline] #[inline]
fn rotate_ray3(&self, _ray: &Ray3<S>) -> Ray3<S> { fail!("Not yet implemented") } fn rotate_ray(&self, _ray: &Ray3<S>) -> Ray3<S> { fail!("Not yet implemented") }
#[inline] #[inline]
fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat.mul_m(&other.mat) } } fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat.mul_m(&other.mat) } }
@ -252,6 +280,8 @@ impl<S: Float> ApproxEq<S> for Basis3<S> {
} }
} }
impl<S: Float> Rotation3<S> for Basis3<S> {}
// Quaternion Rotation impls // Quaternion Rotation impls
impl<S: Float> ToBasis3<S> for Quat<S> { impl<S: Float> ToBasis3<S> for Quat<S> {
@ -264,15 +294,18 @@ impl<S: Float> ToQuat<S> for Quat<S> {
fn to_quat(&self) -> Quat<S> { self.clone() } fn to_quat(&self) -> Quat<S> { self.clone() }
} }
impl<S: Float> Rotation3<S> for Quat<S> { impl<S: Float> Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Quat<S> {
#[inline] #[inline]
fn rotate_point3(&self, _point: &Point3<S>) -> Point3<S> { fail!("Not yet implemented") } fn identity() -> Quat<S> { Quat::identity() }
#[inline]
fn rotate_point(&self, _point: &Point3<S>) -> Point3<S> { fail!("Not yet implemented") }
#[inline] #[inline]
fn rotate_vec3(&self, vec: &Vec3<S>) -> Vec3<S> { self.mul_v(vec) } fn rotate_vec(&self, vec: &Vec3<S>) -> Vec3<S> { self.mul_v(vec) }
#[inline] #[inline]
fn rotate_ray3(&self, _ray: &Ray3<S>) -> Ray3<S> { fail!("Not yet implemented") } fn rotate_ray(&self, _ray: &Ray3<S>) -> Ray3<S> { fail!("Not yet implemented") }
#[inline] #[inline]
fn concat(&self, other: &Quat<S>) -> Quat<S> { self.mul_q(other) } fn concat(&self, other: &Quat<S>) -> Quat<S> { self.mul_q(other) }
@ -286,3 +319,5 @@ impl<S: Float> Rotation3<S> for Quat<S> {
#[inline] #[inline]
fn invert_self(&mut self) { *self = self.invert() } fn invert_self(&mut self) { *self = self.invert() }
} }
impl<S: Float> Rotation3<S> for Quat<S> {}

View file

@ -13,51 +13,156 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use matrix::Mat4; use std::num;
use point::{Point,Point3};
use ray::Ray3;
use rotation::Rotation3;
use vector::{Vector,Vec3};
use matrix::{Matrix, Mat4, ToMat4};
use point::{Point, Point3};
use ray::Ray;
use rotation::{Rotation, Rotation3};
use quaternion::Quat;
use vector::{Vector, Vec3};
/// A trait of affine transformation, that can be applied to points or vectors
pub trait Transform
<
S: Primitive,
Slice,
V: Vector<S,Slice>,
P: Point<S,V,Slice>
>
{
fn identity() -> Self;
fn transform_vec(&self, vec: &V) -> V;
fn transform_point(&self, point: &P) -> P;
fn invert(&self) -> Option<Self>;
pub trait Transform3<S> {
fn transform_vec3(&self, vec: &Vec3<S>) -> Vec3<S>;
fn transform_point3(&self, point: &Point3<S>) -> Point3<S>;
#[inline] #[inline]
fn transform_ray3(&self, ray: &Ray3<S>) -> Ray3<S> { fn transform_ray(&self, ray: &Ray<P,V>) -> Ray<P,V> {
Ray3::new( self.transform_point3(&ray.origin), self.transform_vec3(&ray.direction) ) Ray::new( self.transform_point(&ray.origin), self.transform_vec(&ray.direction) )
}
#[inline]
fn invert_self(&mut self)-> bool {
match self.invert() {
Some(t) => {*self = t; true},
None => false,
}
} }
} }
/// A generic transformation consisting of a rotation,
/// displacement vector and scale amount.
pub struct Decomposed<S,V,R> {
scale: S,
rot: R,
disp: V,
}
impl
<
S: Float,
Slice,
V: Vector<S, Slice>,
P: Point<S, V, Slice>,
R: Rotation<S, Slice, V, P>
>
Transform<S, Slice, V, P> for Decomposed<S,V,R> {
#[inline]
fn identity() -> Decomposed<S,V,R> {
Decomposed {
scale: num::one(),
rot: Rotation::identity(),
disp: num::zero(),
}
}
#[inline]
fn transform_vec(&self, vec: &V) -> V {
self.rot.rotate_vec( &vec.mul_s( self.scale.clone() ))
}
#[inline]
fn transform_point(&self, point: &P) -> P {
self.rot.rotate_point( &point.mul_s( self.scale.clone() )).add_v( &self.disp )
}
#[inline]
fn invert(&self) -> Option<Decomposed<S,V,R>> {
if self.scale.approx_eq( &num::zero() ) {
None
}else {
let _1 : S = num::one();
let s = _1 / self.scale;
let r = self.rot.invert();
let d = r.rotate_vec( &self.disp ).mul_s( -s );
Some( Decomposed {
scale: s,
rot: r,
disp: d,
})
}
}
}
pub trait Transform3<S>
: Transform<S, [S, ..3], Vec3<S>, Point3<S>>
+ ToMat4<S>
{}
impl<S: Float + Clone, R: Rotation3<S>>
ToMat4<S> for Decomposed<S, Vec3<S>, R> {
fn to_mat4(&self) -> Mat4<S> {
let mut m = self.rot.to_mat3().mul_s( self.scale.clone() ).to_mat4();
m.w = self.disp.extend( num::one() );
m
}
}
impl<S: Float, R: Rotation3<S>>
Transform3<S> for Decomposed<S,Vec3<S>,R> {}
/// A homogeneous transformation matrix. /// A homogeneous transformation matrix.
pub struct AffineMatrix3<S> { pub struct AffineMatrix3<S> {
mat: Mat4<S>, mat: Mat4<S>,
} }
impl<S : Clone + Float>
Transform<S, [S, ..3], Vec3<S>, Point3<S>> for AffineMatrix3<S> {
#[inline]
fn identity() -> AffineMatrix3<S> {
AffineMatrix3 { mat: Mat4::identity() }
}
#[inline]
fn transform_vec(&self, vec: &Vec3<S>) -> Vec3<S> {
self.mat.mul_v( &vec.extend(num::zero()) ).truncate()
}
#[inline]
fn transform_point(&self, point: &Point3<S>) -> Point3<S> {
Point3::from_homogeneous( &self.mat.mul_v( &point.to_homogeneous() ))
}
#[inline]
fn invert(&self) -> Option<AffineMatrix3<S>> {
self.mat.invert().map(|m| AffineMatrix3{ mat: m })
}
}
impl<S: Clone + Primitive>
ToMat4<S> for AffineMatrix3<S> {
#[inline] fn to_mat4(&self) -> Mat4<S> { self.mat.clone() }
}
/// A transformation in three dimensions consisting of a rotation, /// A transformation in three dimensions consisting of a rotation,
/// displacement vector and scale amount. /// displacement vector and scale amount.
pub struct Transform3D<S, R> { pub struct Transform3D<S>( Decomposed<S,Vec3<S>,Quat<S>> );
rot: R,
disp: Vec3<S>,
scale: S,
}
impl<S: Float, R: Rotation3<S>> Transform3D<S, R> { impl<S: Float> Transform3D<S> {
#[inline] #[inline]
pub fn new(rot: R, disp: Vec3<S>, scale: S) -> Transform3D<S, R> { pub fn new(scale: S, rot: Quat<S>, disp: Vec3<S>) -> Transform3D<S> {
Transform3D { rot: rot, disp: disp, scale: scale } Transform3D( Decomposed { scale: scale, rot: rot, disp: disp })
}
}
impl <S: Float, R: Rotation3<S>> Transform3<S> for Transform3D<S,R> {
#[inline]
fn transform_vec3(&self, vec: &Vec3<S>) -> Vec3<S> {
self.rot.rotate_vec3( &vec.mul_s( self.scale.clone() ))
}
#[inline]
fn transform_point3(&self, point: &Point3<S>) -> Point3<S> {
self.rot.rotate_point3( &point.mul_s( self.scale.clone() )).add_v( &self.disp )
} }
} }

View file

@ -31,7 +31,7 @@ pub struct Vec3<S> { x: S, y: S, z: S }
#[deriving(Eq, Clone, Zero)] #[deriving(Eq, Clone, Zero)]
pub struct Vec4<S> { x: S, y: S, z: S, w: S } pub struct Vec4<S> { x: S, y: S, z: S, w: S }
// Conversion traits // Conversion traits //FIXME: not used anywhere?
pub trait ToVec2<S: Primitive> { fn to_vec2(&self) -> Vec2<S>; } pub trait ToVec2<S: Primitive> { fn to_vec2(&self) -> Vec2<S>; }
pub trait ToVec3<S: Primitive> { fn to_vec3(&self) -> Vec3<S>; } pub trait ToVec3<S: Primitive> { fn to_vec3(&self) -> Vec3<S>; }
pub trait ToVec4<S: Primitive> { fn to_vec4(&self) -> Vec4<S>; } pub trait ToVec4<S: Primitive> { fn to_vec4(&self) -> Vec4<S>; }
@ -55,7 +55,7 @@ macro_rules! vec(
#[inline] #[inline]
pub fn zero() -> $Self<$S> { $Self::from_value(zero()) } pub fn zero() -> $Self<$S> { $Self::from_value(zero()) }
/// The additive identity of the vector. /// The multiplicative identity of the vector.
#[inline] #[inline]
pub fn ident() -> $Self<$S> { $Self::from_value(one()) } pub fn ident() -> $Self<$S> { $Self::from_value(one()) }
} }
@ -70,12 +70,28 @@ impl<S: Primitive> Vec2<S> {
#[inline] pub fn unit_x() -> Vec2<S> { Vec2::new(one(), zero()) } #[inline] pub fn unit_x() -> Vec2<S> { Vec2::new(one(), zero()) }
#[inline] pub fn unit_y() -> Vec2<S> { Vec2::new(zero(), one()) } #[inline] pub fn unit_y() -> Vec2<S> { Vec2::new(zero(), one()) }
} }
impl<S: Primitive + Clone> Vec2<S> {
#[inline]
pub fn extend(&self, z: S)-> Vec3<S> {
Vec3::new(self.x.clone(), self.y.clone(), z)
}
}
impl<S: Primitive> Vec3<S> { impl<S: Primitive> Vec3<S> {
#[inline] pub fn unit_x() -> Vec3<S> { Vec3::new(one(), zero(), zero()) } #[inline] pub fn unit_x() -> Vec3<S> { Vec3::new(one(), zero(), zero()) }
#[inline] pub fn unit_y() -> Vec3<S> { Vec3::new(zero(), one(), zero()) } #[inline] pub fn unit_y() -> Vec3<S> { Vec3::new(zero(), one(), zero()) }
#[inline] pub fn unit_z() -> Vec3<S> { Vec3::new(zero(), zero(), one()) } #[inline] pub fn unit_z() -> Vec3<S> { Vec3::new(zero(), zero(), one()) }
} }
impl<S: Primitive + Clone> Vec3<S> {
#[inline]
pub fn extend(&self, w: S)-> Vec4<S> {
Vec4::new(self.x.clone(), self.y.clone(), self.z.clone(), w)
}
#[inline]
pub fn truncate(&self)-> Vec2<S> {
Vec2::new(self.x.clone(), self.y.clone()) //ignore Z
}
}
impl<S: Primitive> Vec4<S> { impl<S: Primitive> Vec4<S> {
#[inline] pub fn unit_x() -> Vec4<S> { Vec4::new(one(), zero(), zero(), zero()) } #[inline] pub fn unit_x() -> Vec4<S> { Vec4::new(one(), zero(), zero(), zero()) }
@ -83,6 +99,12 @@ impl<S: Primitive> Vec4<S> {
#[inline] pub fn unit_z() -> Vec4<S> { Vec4::new(zero(), zero(), one(), zero()) } #[inline] pub fn unit_z() -> Vec4<S> { Vec4::new(zero(), zero(), one(), zero()) }
#[inline] pub fn unit_w() -> Vec4<S> { Vec4::new(zero(), zero(), zero(), one()) } #[inline] pub fn unit_w() -> Vec4<S> { Vec4::new(zero(), zero(), zero(), one()) }
} }
impl<S: Primitive + Clone> Vec4<S> {
#[inline]
pub fn truncate(&self)-> Vec3<S> {
Vec3::new(self.x.clone(), self.y.clone(), self.z.clone()) //ignore W
}
}
array!(impl<S> Vec2<S> -> [S, ..2] _2) array!(impl<S> Vec2<S> -> [S, ..2] _2)
array!(impl<S> Vec3<S> -> [S, ..3] _3) array!(impl<S> Vec3<S> -> [S, ..3] _3)

View file

@ -15,10 +15,12 @@
use cgmath::matrix::*; use cgmath::matrix::*;
use cgmath::vector::*; use cgmath::vector::*;
type float = f64;
pub mod mat2 { pub mod mat2 {
use cgmath::matrix::*; use cgmath::matrix::*;
use cgmath::vector::*; use cgmath::vector::*;
type float = f64;
pub static A: Mat2<f64> = Mat2 { x: Vec2 { x: 1.0, y: 3.0 }, pub static A: Mat2<f64> = Mat2 { x: Vec2 { x: 1.0, y: 3.0 },
y: Vec2 { x: 2.0, y: 4.0 } }; y: Vec2 { x: 2.0, y: 4.0 } };
@ -34,6 +36,7 @@ pub mod mat2 {
pub mod mat3 { pub mod mat3 {
use cgmath::matrix::*; use cgmath::matrix::*;
use cgmath::vector::*; use cgmath::vector::*;
type float = f64;
pub static A: Mat3<f64> = Mat3 { x: Vec3 { x: 1.0, y: 4.0, z: 7.0 }, pub static A: Mat3<f64> = Mat3 { x: Vec3 { x: 1.0, y: 4.0, z: 7.0 },
y: Vec3 { x: 2.0, y: 5.0, z: 8.0 }, y: Vec3 { x: 2.0, y: 5.0, z: 8.0 },
@ -55,6 +58,7 @@ pub mod mat3 {
pub mod mat4 { pub mod mat4 {
use cgmath::matrix::*; use cgmath::matrix::*;
use cgmath::vector::*; use cgmath::vector::*;
type float = f64;
pub static A: Mat4<f64> = Mat4 { x: Vec4 { x: 1.0, y: 5.0, z: 9.0, w: 13.0 }, pub static A: Mat4<f64> = Mat4 { x: Vec4 { x: 1.0, y: 5.0, z: 9.0, w: 13.0 },
y: Vec4 { x: 2.0, y: 6.0, z: 10.0, w: 14.0 }, y: Vec4 { x: 2.0, y: 6.0, z: 10.0, w: 14.0 },

View file

@ -18,11 +18,13 @@ use cgmath::point::*;
#[test] #[test]
fn test_from_points() { fn test_from_points() {
assert_eq!(Plane::from_points(Point3::new(5f64, 0f64, 5f64), assert_eq!(Plane::from_points(Point3::new(5.0, 0.0, 5.0),
Point3::new(5f64, 5f64, 5f64), Point3::new(5.0, 5.0, 5.0),
Point3::new(5f64, 0f64, -1f64)), Some(Plane::from_abcd(-1f64, 0f64, 0f64, 5f64))); Point3::new(5.0, 0.0, -1.0)),
Some(Plane::from_abcd(-1.0, 0.0, 0.0, 5.0)));
assert_eq!(Plane::from_points(Point3::new(0f64, 5f64, -5f64), assert_eq!(Plane::from_points(Point3::new(0.0, 5.0, -5.0),
Point3::new(0f64, 5f64, 0f64), Point3::new(0.0, 5.0, 0.0),
Point3::new(0f64, 5f64, 5f64)), None); // The points are parallel Point3::new(0.0, 5.0, 5.0)),
None); // The points are parallel
} }

22
src/tests/point.rs Normal file
View file

@ -0,0 +1,22 @@
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use cgmath::point::*;
#[test]
fn test_homogeneous() {
let p = Point3::new(1.0, 2.0, 3.0);
assert_approx_eq!(p, Point3::from_homogeneous( &p.to_homogeneous() ));
}

View file

@ -14,6 +14,8 @@
// limitations under the License. // limitations under the License.
#[feature(globs)]; #[feature(globs)];
#[feature(globs)];
extern mod cgmath; extern mod cgmath;
// pub mod array; // pub mod array;
@ -23,9 +25,10 @@ pub mod vector;
pub mod angle; pub mod angle;
pub mod plane; pub mod plane;
// pub mod point; pub mod point;
// pub mod ray; // pub mod ray;
// pub mod rotation; // pub mod rotation;
pub mod transform;
// pub mod projection; // pub mod projection;

27
src/tests/transform.rs Normal file
View file

@ -0,0 +1,27 @@
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use cgmath::quaternion::*;
use cgmath::transform::*;
use cgmath::vector::*;
#[test]
fn test_invert() {
let v = Vec3::new(1.0, 2.0, 3.0);
let t = Transform3D::new( 1.5, Quat::new(0.5,0.5,0.5,0.5), Vec3::new(6.0,-7.0,8.0) );
let ti = t.invert().expect("Expected successful inversion");
let vt = t.transform_vec( &v );
assert_approx_eq!(v, ti.transform_vec( &vt ));
}

View file

@ -36,9 +36,9 @@ fn test_comp_add() {
assert_eq!(Vec3::new(1, 2, 3).comp_add(), 6); assert_eq!(Vec3::new(1, 2, 3).comp_add(), 6);
assert_eq!(Vec4::new(1, 2, 3, 4).comp_add(), 10); assert_eq!(Vec4::new(1, 2, 3, 4).comp_add(), 10);
assert_eq!(Vec2::new(3f64, 4f64).comp_add(), 7f64); assert_eq!(Vec2::new(3.0, 4.0).comp_add(), 7.0);
assert_eq!(Vec3::new(4f64, 5f64, 6f64).comp_add(), 15f64); assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_add(), 15.0);
assert_eq!(Vec4::new(5f64, 6f64, 7f64, 8f64).comp_add(), 26f64); assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_add(), 26.0);
} }
#[test] #[test]
@ -47,9 +47,9 @@ fn test_comp_mul() {
assert_eq!(Vec3::new(1, 2, 3).comp_mul(), 6); assert_eq!(Vec3::new(1, 2, 3).comp_mul(), 6);
assert_eq!(Vec4::new(1, 2, 3, 4).comp_mul(), 24); assert_eq!(Vec4::new(1, 2, 3, 4).comp_mul(), 24);
assert_eq!(Vec2::new(3f64, 4f64).comp_mul(), 12f64); assert_eq!(Vec2::new(3.0, 4.0).comp_mul(), 12.0);
assert_eq!(Vec3::new(4f64, 5f64, 6f64).comp_mul(), 120f64); assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_mul(), 120.0);
assert_eq!(Vec4::new(5f64, 6f64, 7f64, 8f64).comp_mul(), 1680f64); assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_mul(), 1680.0);
} }
#[test] #[test]
@ -58,9 +58,9 @@ fn test_comp_min() {
assert_eq!(Vec3::new(1, 2, 3).comp_min(), 1); assert_eq!(Vec3::new(1, 2, 3).comp_min(), 1);
assert_eq!(Vec4::new(1, 2, 3, 4).comp_min(), 1); assert_eq!(Vec4::new(1, 2, 3, 4).comp_min(), 1);
assert_eq!(Vec2::new(3f64, 4f64).comp_min(), 3f64); assert_eq!(Vec2::new(3.0, 4.0).comp_min(), 3.0);
assert_eq!(Vec3::new(4f64, 5f64, 6f64).comp_min(), 4f64); assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_min(), 4.0);
assert_eq!(Vec4::new(5f64, 6f64, 7f64, 8f64).comp_min(), 5f64); assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_min(), 5.0);
} }
#[test] #[test]
@ -69,9 +69,9 @@ fn test_comp_max() {
assert_eq!(Vec3::new(1, 2, 3).comp_max(), 3); assert_eq!(Vec3::new(1, 2, 3).comp_max(), 3);
assert_eq!(Vec4::new(1, 2, 3, 4).comp_max(), 4); assert_eq!(Vec4::new(1, 2, 3, 4).comp_max(), 4);
assert_eq!(Vec2::new(3f64, 4f64).comp_max(), 4f64); assert_eq!(Vec2::new(3.0, 4.0).comp_max(), 4.0);
assert_eq!(Vec3::new(4f64, 5f64, 6f64).comp_max(), 6f64); assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_max(), 6.0);
assert_eq!(Vec4::new(5f64, 6f64, 7f64, 8f64).comp_max(), 8f64); assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_max(), 8.0);
} }
#[test] #[test]
@ -88,9 +88,9 @@ fn test_cross() {
#[test] #[test]
fn test_is_perpendicular() { fn test_is_perpendicular() {
assert!(Vec2::new(1f64, 0f64).is_perpendicular(&Vec2::new(0f64, 1f64))); assert!(Vec2::new(1.0, 0.0).is_perpendicular(&Vec2::new(0.0, 1.0)));
assert!(Vec3::new(0f64, 1f64, 0f64).is_perpendicular(&Vec3::new(0f64, 0f64, 1f64))); assert!(Vec3::new(0.0, 1.0, 0.0).is_perpendicular(&Vec3::new(0.0, 0.0, 1.0)));
assert!(Vec4::new(1f64, 0f64, 0f64, 0f64).is_perpendicular(&Vec4::new(0f64, 0f64, 0f64, 1f64))); assert!(Vec4::new(1.0, 0.0, 0.0, 0.0).is_perpendicular(&Vec4::new(0.0, 0.0, 0.0, 1.0)));
} }
#[cfg(test)] #[cfg(test)]
@ -99,8 +99,8 @@ mod test_length {
#[test] #[test]
fn test_vec2(){ fn test_vec2(){
let (a, a_res) = (Vec2::new(3f64, 4f64), 5f64); // (3, 4, 5) Pythagorean triple let (a, a_res) = (Vec2::new(3.0, 4.0), 5.0); // (3, 4, 5) Pythagorean triple
let (b, b_res) = (Vec2::new(5f64, 12f64), 13f64); // (5, 12, 13) Pythagorean triple let (b, b_res) = (Vec2::new(5.0, 12.0), 13.0); // (5, 12, 13) Pythagorean triple
assert_eq!(a.length2(), a_res * a_res); assert_eq!(a.length2(), a_res * a_res);
assert_eq!(b.length2(), b_res * b_res); assert_eq!(b.length2(), b_res * b_res);
@ -111,8 +111,8 @@ mod test_length {
#[test] #[test]
fn test_vec3(){ fn test_vec3(){
let (a, a_res) = (Vec3::new(2f64, 3f64, 6f64), 7f64); // (2, 3, 6, 7) Pythagorean quadruple let (a, a_res) = (Vec3::new(2.0, 3.0, 6.0), 7.0); // (2, 3, 6, 7) Pythagorean quadruple
let (b, b_res) = (Vec3::new(1f64, 4f64, 8f64), 9f64); // (1, 4, 8, 9) Pythagorean quadruple let (b, b_res) = (Vec3::new(1.0, 4.0, 8.0), 9.0); // (1, 4, 8, 9) Pythagorean quadruple
assert_eq!(a.length2(), a_res * a_res); assert_eq!(a.length2(), a_res * a_res);
assert_eq!(b.length2(), b_res * b_res); assert_eq!(b.length2(), b_res * b_res);
@ -123,8 +123,8 @@ mod test_length {
#[test] #[test]
fn test_vec4(){ fn test_vec4(){
let (a, a_res) = (Vec4::new(1f64, 2f64, 4f64, 10f64), 11f64); // (1, 2, 4, 10, 11) Pythagorean quintuple let (a, a_res) = (Vec4::new(1.0, 2.0, 4.0, 10.0), 11.0); // (1, 2, 4, 10, 11) Pythagorean quintuple
let (b, b_res) = (Vec4::new(1f64, 2f64, 8f64, 10f64), 13f64); // (1, 2, 8, 10, 13) Pythagorean quintuple let (b, b_res) = (Vec4::new(1.0, 2.0, 8.0, 10.0), 13.0); // (1, 2, 8, 10, 13) Pythagorean quintuple
assert_eq!(a.length2(), a_res * a_res); assert_eq!(a.length2(), a_res * a_res);
assert_eq!(b.length2(), b_res * b_res); assert_eq!(b.length2(), b_res * b_res);
@ -136,23 +136,23 @@ mod test_length {
#[test] #[test]
fn test_angle() { fn test_angle() {
assert_approx_eq!(Vec2::new(1f64, 0f64).angle(&Vec2::new(0f64, 1f64)), rad(Real::frac_pi_2())); assert_approx_eq!(Vec2::new(1.0, 0.0).angle(&Vec2::new(0.0, 1.0)), rad(Real::frac_pi_2()));
assert_approx_eq!(Vec2::new(10f64, 0f64).angle(&Vec2::new(0f64, 5f64)), rad(Real::frac_pi_2())); assert_approx_eq!(Vec2::new(10.0, 0.0).angle(&Vec2::new(0.0, 5.0)), rad(Real::frac_pi_2()));
assert_approx_eq!(Vec2::new(-1f64, 0f64).angle(&Vec2::new(0f64, 1f64)), -rad(Real::frac_pi_2())); assert_approx_eq!(Vec2::new(-1.0, 0.0).angle(&Vec2::new(0.0, 1.0)), -rad(Real::frac_pi_2()));
assert_approx_eq!(Vec3::new(1f64, 0f64, 1f64).angle(&Vec3::new(1f64, 1f64, 0f64)), rad(Real::frac_pi_3())); assert_approx_eq!(Vec3::new(1.0, 0.0, 1.0).angle(&Vec3::new(1.0, 1.0, 0.0)), rad(Real::frac_pi_3()));
assert_approx_eq!(Vec3::new(10f64, 0f64, 10f64).angle(&Vec3::new(5f64, 5f64, 0f64)), rad(Real::frac_pi_3())); assert_approx_eq!(Vec3::new(10.0, 0.0, 10.0).angle(&Vec3::new(5.0, 5.0, 0.0)), rad(Real::frac_pi_3()));
assert_approx_eq!(Vec3::new(-1f64, 0f64, -1f64).angle(&Vec3::new(1f64, -1f64, 0f64)), rad(2f64 * Real::frac_pi_3())); assert_approx_eq!(Vec3::new(-1.0, 0.0, -1.0).angle(&Vec3::new(1.0, -1.0, 0.0)), rad(2.0 * Real::frac_pi_3()));
assert_approx_eq!(Vec4::new(1f64, 0f64, 1f64, 0f64).angle(&Vec4::new(0f64, 1f64, 0f64, 1f64)), rad(Real::frac_pi_2())); assert_approx_eq!(Vec4::new(1.0, 0.0, 1.0, 0.0).angle(&Vec4::new(0.0, 1.0, 0.0, 1.0)), rad(Real::frac_pi_2()));
assert_approx_eq!(Vec4::new(10f64, 0f64, 10f64, 0f64).angle(&Vec4::new(0f64, 5f64, 0f64, 5f64)), rad(Real::frac_pi_2())); assert_approx_eq!(Vec4::new(10.0, 0.0, 10.0, 0.0).angle(&Vec4::new(0.0, 5.0, 0.0, 5.0)), rad(Real::frac_pi_2()));
assert_approx_eq!(Vec4::new(-1f64, 0f64, -1f64, 0f64).angle(&Vec4::new(0f64, 1f64, 0f64, 1f64)), rad(Real::frac_pi_2())); assert_approx_eq!(Vec4::new(-1.0, 0.0, -1.0, 0.0).angle(&Vec4::new(0.0, 1.0, 0.0, 1.0)), rad(Real::frac_pi_2()));
} }
#[test] #[test]
fn test_normalize() { fn test_normalize() {
// TODO: test normalize_to, normalize_self, and normalize_self_to // TODO: test normalize_to, normalize_sel.0, and normalize_self_to
assert_approx_eq!(Vec2::new(3f64, 4f64).normalize(), Vec2::new(3f64/5f64, 4f64/5f64)); assert_approx_eq!(Vec2::new(3.0, 4.0).normalize(), Vec2::new(3.0/5.0, 4.0/5.0));
assert_approx_eq!(Vec3::new(2f64, 3f64, 6f64).normalize(), Vec3::new(2f64/7f64, 3f64/7f64, 6f64/7f64)); assert_approx_eq!(Vec3::new(2.0, 3.0, 6.0).normalize(), Vec3::new(2.0/7.0, 3.0/7.0, 6.0/7.0));
assert_approx_eq!(Vec4::new(1f64, 2f64, 4f64, 10f64).normalize(), Vec4::new(1f64/11f64, 2f64/11f64, 4f64/11f64, 10f64/11f64)); assert_approx_eq!(Vec4::new(1.0, 2.0, 4.0, 10.0).normalize(), Vec4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0));
} }