Impl ApproxEq for vectors, matrices and points
This commit is contained in:
parent
b84e154898
commit
2b8e36d4a3
4 changed files with 118 additions and 27 deletions
|
@ -103,27 +103,26 @@ macro_rules! array(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
macro_rules! array_op(
|
macro_rules! approx_eq(
|
||||||
(impl<$S:ident> ($Op:ident, $op:ident) for ($Self:ty, $Other:ty) -> $Result:ty) => (
|
(impl<$S:ident> $Self:ty) => (
|
||||||
impl<$S: Field> $Op<$Other, $Result> for $Self {
|
impl<$S: Clone + ApproxEq<$S>> ApproxEq<$S> for $Self {
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
fn $op(&self, other: &$Other) -> $Result {
|
fn approx_epsilon() -> $S {
|
||||||
self.bimap(other, |a, b| a.$op(b))
|
// TODO: fix this after static methods are fixed in rustc
|
||||||
|
fail!(~"Doesn't work!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn approx_eq(&self, other: &$Self) -> bool {
|
||||||
|
self.iter().zip(other.iter())
|
||||||
|
.all(|(a, b)| a.approx_eq(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn approx_eq_eps(&self, other: &$Self, approx_epsilon: &$S) -> bool {
|
||||||
|
self.iter().zip(other.iter())
|
||||||
|
.all(|(a, b)| a.approx_eq_eps(b, approx_epsilon))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
(impl<$S:ident> ($Op:ident, $op:ident) for $Self:ty -> $Result:ty) => (
|
|
||||||
impl<$S: Field> $Op<$Result> for $Self {
|
|
||||||
#[inline(always)]
|
|
||||||
fn $op(&self) -> $Result {
|
|
||||||
self.map(|a| a.$op())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
(impl<$S:ident> -$Self:ty -> $Result:ty) => (array_op!(impl<$S> (Neg, neg) for $Self -> $Result));
|
|
||||||
(impl<$S:ident> $Self:ty + $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Add, add) for ($Self, $Other) -> $Result));
|
|
||||||
(impl<$S:ident> $Self:ty - $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Sub, sub) for ($Self, $Other) -> $Result));
|
|
||||||
(impl<$S:ident> $Self:ty * $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Mul, mul) for ($Self, $Other) -> $Result));
|
|
||||||
(impl<$S:ident> $Self:ty / $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Div, div) for ($Self, $Other) -> $Result));
|
|
||||||
(impl<$S:ident> $Self:ty % $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Rem, rem) for ($Self, $Other) -> $Result));
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -34,6 +34,10 @@ pub struct Mat3<S> { x: Vec3<S>, y: Vec3<S>, z: Vec3<S> }
|
||||||
#[deriving(Clone, Eq, Zero)]
|
#[deriving(Clone, Eq, Zero)]
|
||||||
pub struct Mat4<S> { x: Vec4<S>, y: Vec4<S>, z: Vec4<S>, w: Vec4<S> }
|
pub struct Mat4<S> { x: Vec4<S>, y: Vec4<S>, z: Vec4<S>, w: Vec4<S> }
|
||||||
|
|
||||||
|
approx_eq!(impl<S> Mat2<S>)
|
||||||
|
approx_eq!(impl<S> Mat3<S>)
|
||||||
|
approx_eq!(impl<S> Mat4<S>)
|
||||||
|
|
||||||
// Conversion traits
|
// Conversion traits
|
||||||
pub trait ToMat2<S: Clone + Num> { fn to_mat2(&self) -> Mat2<S>; }
|
pub trait ToMat2<S: Clone + Num> { fn to_mat2(&self) -> Mat2<S>; }
|
||||||
pub trait ToMat3<S: Clone + Num> { fn to_mat3(&self) -> Mat3<S>; }
|
pub trait ToMat3<S: Clone + Num> { fn to_mat3(&self) -> Mat3<S>; }
|
||||||
|
@ -175,6 +179,7 @@ pub trait Matrix
|
||||||
: Array<V, Slice>
|
: Array<V, Slice>
|
||||||
+ Neg<Self>
|
+ Neg<Self>
|
||||||
+ Zero + One
|
+ Zero + One
|
||||||
|
+ ApproxEq<S>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn c<'a>(&'a self, c: uint) -> &'a V { self.i(c) }
|
fn c<'a>(&'a self, c: uint) -> &'a V { self.i(c) }
|
||||||
|
@ -237,13 +242,21 @@ pub trait Matrix
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_invertible(&self) -> bool {
|
fn is_invertible(&self) -> bool {
|
||||||
!self.determinant().approx_eq(&zero::<S>())
|
!self.determinant().approx_eq(&zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn is_identity(&self) -> bool;
|
#[inline]
|
||||||
// pub fn is_diagonal(&self) -> bool;
|
fn is_identity(&self) -> bool {
|
||||||
// pub fn is_rotated(&self) -> bool;
|
self.approx_eq(&one())
|
||||||
// pub fn is_symmetric(&self) -> bool;
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_rotated(&self) -> bool {
|
||||||
|
!self.approx_eq(&one())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_diagonal(&self) -> bool;
|
||||||
|
fn is_symmetric(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Clone + Float> Neg<Mat2<S>> for Mat2<S> { #[inline] fn neg(&self) -> Mat2<S> { self.map(|c| c.neg()) } }
|
impl<S: Clone + Float> Neg<Mat2<S>> for Mat2<S> { #[inline] fn neg(&self) -> Mat2<S> { self.map(|c| c.neg()) } }
|
||||||
|
@ -280,6 +293,7 @@ for Mat2<S>
|
||||||
*self.cr(0, 0) * *self.cr(1, 1) - *self.cr(1, 0) * *self.cr(0, 1)
|
*self.cr(0, 0) * *self.cr(1, 1) - *self.cr(1, 0) * *self.cr(0, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn invert(&self) -> Option<Mat2<S>> {
|
fn invert(&self) -> Option<Mat2<S>> {
|
||||||
let det = self.determinant();
|
let det = self.determinant();
|
||||||
if det.approx_eq(&zero()) {
|
if det.approx_eq(&zero()) {
|
||||||
|
@ -289,6 +303,19 @@ for Mat2<S>
|
||||||
-self.cr(1, 0) / det, self.cr(0, 0) / det))
|
-self.cr(1, 0) / det, self.cr(0, 0) / det))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_diagonal(&self) -> bool {
|
||||||
|
self.cr(0, 1).approx_eq(&zero()) &&
|
||||||
|
self.cr(1, 0).approx_eq(&zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_symmetric(&self) -> bool {
|
||||||
|
self.cr(0, 1).approx_eq(self.cr(1, 0)) &&
|
||||||
|
self.cr(1, 0).approx_eq(self.cr(0, 1))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Clone + Float>
|
impl<S: Clone + Float>
|
||||||
|
@ -336,6 +363,28 @@ for Mat3<S>
|
||||||
self.c(0).cross(self.c(1)).div_s(det.clone())).transpose())
|
self.c(0).cross(self.c(1)).div_s(det.clone())).transpose())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_diagonal(&self) -> bool {
|
||||||
|
self.cr(0, 1).approx_eq(&zero()) &&
|
||||||
|
self.cr(0, 2).approx_eq(&zero()) &&
|
||||||
|
|
||||||
|
self.cr(1, 0).approx_eq(&zero()) &&
|
||||||
|
self.cr(1, 2).approx_eq(&zero()) &&
|
||||||
|
|
||||||
|
self.cr(2, 0).approx_eq(&zero()) &&
|
||||||
|
self.cr(2, 1).approx_eq(&zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_symmetric(&self) -> bool {
|
||||||
|
self.cr(0, 1).approx_eq(self.cr(1, 0)) &&
|
||||||
|
self.cr(0, 2).approx_eq(self.cr(2, 0)) &&
|
||||||
|
|
||||||
|
self.cr(1, 0).approx_eq(self.cr(0, 1)) &&
|
||||||
|
self.cr(1, 2).approx_eq(self.cr(2, 1)) &&
|
||||||
|
|
||||||
|
self.cr(2, 0).approx_eq(self.cr(0, 2)) &&
|
||||||
|
self.cr(2, 1).approx_eq(self.cr(1, 2))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Clone + Float>
|
impl<S: Clone + Float>
|
||||||
|
@ -357,7 +406,6 @@ for Mat4<S>
|
||||||
self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone())
|
self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transpose_self(&mut self) {
|
fn transpose_self(&mut self) {
|
||||||
self.swap_cr((0, 1), (1, 0));
|
self.swap_cr((0, 1), (1, 0));
|
||||||
self.swap_cr((0, 2), (2, 0));
|
self.swap_cr((0, 2), (2, 0));
|
||||||
|
@ -435,6 +483,42 @@ for Mat4<S>
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_diagonal(&self) -> bool {
|
||||||
|
self.cr(0, 1).approx_eq(&zero()) &&
|
||||||
|
self.cr(0, 2).approx_eq(&zero()) &&
|
||||||
|
self.cr(0, 3).approx_eq(&zero()) &&
|
||||||
|
|
||||||
|
self.cr(1, 0).approx_eq(&zero()) &&
|
||||||
|
self.cr(1, 2).approx_eq(&zero()) &&
|
||||||
|
self.cr(1, 3).approx_eq(&zero()) &&
|
||||||
|
|
||||||
|
self.cr(2, 0).approx_eq(&zero()) &&
|
||||||
|
self.cr(2, 1).approx_eq(&zero()) &&
|
||||||
|
self.cr(2, 3).approx_eq(&zero()) &&
|
||||||
|
|
||||||
|
self.cr(3, 0).approx_eq(&zero()) &&
|
||||||
|
self.cr(3, 1).approx_eq(&zero()) &&
|
||||||
|
self.cr(3, 2).approx_eq(&zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_symmetric(&self) -> bool {
|
||||||
|
self.cr(0, 1).approx_eq(self.cr(1, 0)) &&
|
||||||
|
self.cr(0, 2).approx_eq(self.cr(2, 0)) &&
|
||||||
|
self.cr(0, 3).approx_eq(self.cr(3, 0)) &&
|
||||||
|
|
||||||
|
self.cr(1, 0).approx_eq(self.cr(0, 1)) &&
|
||||||
|
self.cr(1, 2).approx_eq(self.cr(2, 1)) &&
|
||||||
|
self.cr(1, 3).approx_eq(self.cr(3, 1)) &&
|
||||||
|
|
||||||
|
self.cr(2, 0).approx_eq(self.cr(0, 2)) &&
|
||||||
|
self.cr(2, 1).approx_eq(self.cr(1, 2)) &&
|
||||||
|
self.cr(2, 3).approx_eq(self.cr(3, 2)) &&
|
||||||
|
|
||||||
|
self.cr(3, 0).approx_eq(self.cr(0, 3)) &&
|
||||||
|
self.cr(3, 1).approx_eq(self.cr(1, 3)) &&
|
||||||
|
self.cr(3, 2).approx_eq(self.cr(2, 3))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S:Clone + Float> ToQuat<S> for Mat3<S> {
|
impl<S:Clone + Float> ToQuat<S> for Mat3<S> {
|
||||||
|
|
|
@ -30,6 +30,9 @@ struct Point2<S> { x: S, y: S }
|
||||||
#[deriving(Eq, Zero, Clone)]
|
#[deriving(Eq, Zero, Clone)]
|
||||||
struct Point3<S> { x: S, y: S, z: S }
|
struct Point3<S> { x: S, y: S, z: S }
|
||||||
|
|
||||||
|
approx_eq!(impl<S> Point2<S>)
|
||||||
|
approx_eq!(impl<S> Point3<S>)
|
||||||
|
|
||||||
impl<S: Num> Point2<S> {
|
impl<S: Num> Point2<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(x: S, y: S) -> Point2<S> {
|
pub fn new(x: S, y: S) -> Point2<S> {
|
||||||
|
|
|
@ -35,6 +35,10 @@ pub trait ToVec2<S: Clone + Num> { fn to_vec2(&self) -> Vec2<S>; }
|
||||||
pub trait ToVec3<S: Clone + Num> { fn to_vec3(&self) -> Vec3<S>; }
|
pub trait ToVec3<S: Clone + Num> { fn to_vec3(&self) -> Vec3<S>; }
|
||||||
pub trait ToVec4<S: Clone + Num> { fn to_vec4(&self) -> Vec4<S>; }
|
pub trait ToVec4<S: Clone + Num> { fn to_vec4(&self) -> Vec4<S>; }
|
||||||
|
|
||||||
|
approx_eq!(impl<S> Vec2<S>)
|
||||||
|
approx_eq!(impl<S> Vec3<S>)
|
||||||
|
approx_eq!(impl<S> Vec4<S>)
|
||||||
|
|
||||||
// Utility macro for generating associated functions for the vectors
|
// Utility macro for generating associated functions for the vectors
|
||||||
macro_rules! vec(
|
macro_rules! vec(
|
||||||
(impl $Self:ident <$S:ident> { $($field:ident),+ }) => (
|
(impl $Self:ident <$S:ident> { $($field:ident),+ }) => (
|
||||||
|
@ -166,6 +170,7 @@ pub trait EuclideanVector
|
||||||
Slice
|
Slice
|
||||||
>
|
>
|
||||||
: Vector<S, Slice>
|
: Vector<S, Slice>
|
||||||
|
+ ApproxEq<S>
|
||||||
{
|
{
|
||||||
/// Returns `true` if the vector is perpendicular (at right angles to)
|
/// Returns `true` if the vector is perpendicular (at right angles to)
|
||||||
/// the other vector.
|
/// the other vector.
|
||||||
|
|
Loading…
Reference in a new issue