Refined traits for rotation/translation/transformation.

This commit is contained in:
Sébastien Crozet 2013-06-27 16:16:07 +00:00
parent ffbcf4882a
commit 6723693b49
12 changed files with 149 additions and 76 deletions

View File

@ -5,7 +5,7 @@ use traits::rlmul::{RMul, LMul};
use traits::dim::Dim; use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::transpose::Transpose; use traits::transpose::Transpose;
use traits::rotation::Rotation; use traits::rotation::{Rotation, Rotatable};
use traits::delta_transform::{DeltaTransform, DeltaTransformVector}; use traits::delta_transform::{DeltaTransform, DeltaTransformVector};
use dim1::vec1::Vec1; use dim1::vec1::Vec1;
use dim2::mat2::Mat2; use dim2::mat2::Mat2;
@ -57,38 +57,47 @@ pub fn rotmat3<N: Copy + Trigonometric + Neg<N> + One + Sub<N, N> + Add<N, N> +
} }
impl<N: Div<N, N> + Trigonometric + Neg<N> + Mul<N, N> + Add<N, N> + Copy> impl<N: Div<N, N> + Trigonometric + Neg<N> + Mul<N, N> + Add<N, N> + Copy>
Rotation<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>> Rotation<Vec1<N>> for Rotmat<Mat2<N>>
{ {
#[inline(always)] #[inline(always)]
fn rotation(&self) -> Vec1<N> fn rotation(&self) -> Vec1<N>
{ Vec1::new(-(self.submat.m12 / self.submat.m11).atan()) } { Vec1::new(-(self.submat.m12 / self.submat.m11).atan()) }
#[inline(always)]
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
{ rotmat2(copy rot.x) * *self }
#[inline(always)] #[inline(always)]
fn rotate(&mut self, rot: &Vec1<N>) fn rotate(&mut self, rot: &Vec1<N>)
{ *self = self.rotated(rot) } { *self = self.rotated(rot) }
} }
impl<N: Div<N, N> + Trigonometric + Neg<N> + Mul<N, N> + Add<N, N> + Copy>
Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>>
{
#[inline(always)]
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
{ rotmat2(copy rot.x) * *self }
}
impl<N: Div<N, N> + Trigonometric + Neg<N> + Mul<N, N> + Add<N, N> + Copy + impl<N: Div<N, N> + Trigonometric + Neg<N> + Mul<N, N> + Add<N, N> + Copy +
One + Sub<N, N>> One + Sub<N, N>>
Rotation<(Vec3<N>, N), Rotmat<Mat3<N>>> for Rotmat<Mat3<N>> Rotation<(Vec3<N>, N)> for Rotmat<Mat3<N>>
{ {
#[inline(always)] #[inline(always)]
fn rotation(&self) -> (Vec3<N>, N) fn rotation(&self) -> (Vec3<N>, N)
{ fail!("Not yet implemented.") } { fail!("Not yet implemented.") }
#[inline(always)]
fn rotated(&self, &(axis, angle): &(Vec3<N>, N)) -> Rotmat<Mat3<N>>
{ rotmat3(&axis, angle) * *self }
#[inline(always)] #[inline(always)]
fn rotate(&mut self, rot: &(Vec3<N>, N)) fn rotate(&mut self, rot: &(Vec3<N>, N))
{ *self = self.rotated(rot) } { *self = self.rotated(rot) }
} }
impl<N: Div<N, N> + Trigonometric + Neg<N> + Mul<N, N> + Add<N, N> + Copy +
One + Sub<N, N>>
Rotatable<(Vec3<N>, N), Rotmat<Mat3<N>>> for Rotmat<Mat3<N>>
{
#[inline(always)]
fn rotated(&self, &(axis, angle): &(Vec3<N>, N)) -> Rotmat<Mat3<N>>
{ rotmat3(&axis, angle) * *self }
}
impl<N: Copy + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>> impl<N: Copy + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>>
{ {
#[inline(always)] #[inline(always)]

View File

@ -3,8 +3,9 @@ use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use traits::dim::Dim; use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::rotation::Rotation; use traits::rotation::{Rotation, Rotatable};
use traits::translation::Translation; use traits::translation::{Translation, Translatable};
use traits::transformation::{Transformation, Transformable};
use traits::transpose::Transpose; use traits::transpose::Transpose;
use traits::delta_transform::{DeltaTransform, DeltaTransformVector}; use traits::delta_transform::{DeltaTransform, DeltaTransformVector};
use traits::rlmul::{RMul, LMul}; use traits::rlmul::{RMul, LMul};
@ -73,31 +74,51 @@ impl<M: LMul<V>, V: Add<V, V>> LMul<V> for Transform<M, V>
{ self.submat.lmul(other) + self.subtrans } { self.submat.lmul(other) + self.subtrans }
} }
impl<M: Copy, V: Translation<V, Res>, Res> Translation<V, Transform<M, Res>> for Transform<M, V> impl<M, V: Translation<V>> Translation<V> for Transform<M, V>
{ {
#[inline(always)] #[inline(always)]
fn translation(&self) -> V fn translation(&self) -> V
{ self.subtrans.translation() } { self.subtrans.translation() }
#[inline(always)]
fn translated(&self, t: &V) -> Transform<M, Res>
{ Transform::new(copy self.submat, self.subtrans.translated(t)) }
#[inline(always)] #[inline(always)]
fn translate(&mut self, t: &V) fn translate(&mut self, t: &V)
{ self.subtrans.translate(t) } { self.subtrans.translate(t) }
} }
impl<M: Rotation<AV, Res> + One, impl<M: Copy, V: Translatable<V, Res>, Res: Translation<V>>
Res: RMul<V>, Translatable<V, Transform<M, Res>> for Transform<M, V>
{
#[inline(always)]
fn translated(&self, t: &V) -> Transform<M, Res>
{ Transform::new(copy self.submat, self.subtrans.translated(t)) }
}
impl<M: Rotation<AV> + RMul<V> + One,
V, V,
AV> AV>
Rotation<AV, Transform<Res, V>> for Transform<M, V> Rotation<AV> for Transform<M, V>
{ {
#[inline(always)] #[inline(always)]
fn rotation(&self) -> AV fn rotation(&self) -> AV
{ self.submat.rotation() } { self.submat.rotation() }
#[inline(always)]
fn rotate(&mut self, rot: &AV)
{
// FIXME: this does not seem opitmal
let mut delta = One::one::<M>();
delta.rotate(rot);
self.submat.rotate(rot);
self.subtrans = delta.rmul(&self.subtrans);
}
}
impl<M: Rotatable<AV, Res> + One,
Res: Rotation<AV> + RMul<V>,
V,
AV>
Rotatable<AV, Transform<Res, V>> for Transform<M, V>
{
#[inline(always)] #[inline(always)]
fn rotated(&self, rot: &AV) -> Transform<Res, V> fn rotated(&self, rot: &AV) -> Transform<Res, V>
{ {
@ -106,15 +127,24 @@ Rotation<AV, Transform<Res, V>> for Transform<M, V>
Transform::new(self.submat.rotated(rot), delta.rmul(&self.subtrans)) Transform::new(self.submat.rotated(rot), delta.rmul(&self.subtrans))
} }
#[inline(always)]
fn rotate(&mut self, rot: &AV)
{
// FIXME: this does not seem opitmal
let delta = One::one::<M>().rotated(rot);
self.submat.rotate(rot);
self.subtrans = delta.rmul(&self.subtrans);
} }
impl<M: RMul<V> + Mul<M, M> + Copy, V: Add<V, V> + Copy> Transformation<Transform<M, V>> for Transform<M, V>
{
fn transformation(&self) -> Transform<M, V>
{ copy *self }
fn transform_by(&mut self, other: &Transform<M, V>)
{ *self = other * *self; }
}
// FIXME: constraints are too restrictive.
// Should be: Transformable<M2, // Transform<Res, V> ...
impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>>
Transformable<Transform<M, V>, Transform<M, V>> for Transform<M, V>
{
fn transformed(&self, t: &Transform<M, V>) -> Transform<M, V>
{ t * *self }
} }
impl<M: Copy, V> DeltaTransform<M> for Transform<M, V> impl<M: Copy, V> DeltaTransform<M> for Transform<M, V>

View File

@ -5,7 +5,7 @@ use traits::basis::Basis;
use traits::dim::Dim; use traits::dim::Dim;
use traits::dot::Dot; use traits::dot::Dot;
use traits::norm::Norm; use traits::norm::Norm;
use traits::translation::Translation; use traits::translation::{Translation, Translatable};
use traits::sub_dot::SubDot; use traits::sub_dot::SubDot;
use traits::flatten::Flatten; use traits::flatten::Flatten;
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
@ -91,21 +91,24 @@ ScalarSub<N> for Vec1<N>
{ self.x = self.x - *s; } { self.x = self.x - *s; }
} }
impl<N: Copy + Add<N, N>> Translation<Vec1<N>, Vec1<N>> for Vec1<N> impl<N: Copy + Add<N, N>> Translation<Vec1<N>> for Vec1<N>
{ {
#[inline(always)] #[inline(always)]
fn translation(&self) -> Vec1<N> fn translation(&self) -> Vec1<N>
{ copy *self } { copy *self }
#[inline(always)]
fn translated(&self, t: &Vec1<N>) -> Vec1<N>
{ self + *t }
#[inline(always)] #[inline(always)]
fn translate(&mut self, t: &Vec1<N>) fn translate(&mut self, t: &Vec1<N>)
{ *self = *self + *t } { *self = *self + *t }
} }
impl<N: Add<N, N>> Translatable<Vec1<N>, Vec1<N>> for Vec1<N>
{
#[inline(always)]
fn translated(&self, t: &Vec1<N>) -> Vec1<N>
{ self + *t }
}
impl<N: Mul<N, N>> Dot<N> for Vec1<N> impl<N: Mul<N, N>> Dot<N> for Vec1<N>
{ {
#[inline(always)] #[inline(always)]

View File

@ -9,7 +9,7 @@ use traits::dot::Dot;
use traits::sub_dot::SubDot; use traits::sub_dot::SubDot;
use traits::norm::Norm; use traits::norm::Norm;
use traits::flatten::Flatten; use traits::flatten::Flatten;
use traits::translation::Translation; use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[deriving(Eq, Ord, ToStr)] #[deriving(Eq, Ord, ToStr)]
@ -108,21 +108,24 @@ ScalarSub<N> for Vec2<N>
} }
} }
impl<N: Copy + Add<N, N>> Translation<Vec2<N>, Vec2<N>> for Vec2<N> impl<N: Copy + Add<N, N>> Translation<Vec2<N>> for Vec2<N>
{ {
#[inline(always)] #[inline(always)]
fn translation(&self) -> Vec2<N> fn translation(&self) -> Vec2<N>
{ copy *self } { copy *self }
#[inline(always)]
fn translated(&self, t: &Vec2<N>) -> Vec2<N>
{ self + *t }
#[inline(always)] #[inline(always)]
fn translate(&mut self, t: &Vec2<N>) fn translate(&mut self, t: &Vec2<N>)
{ *self = *self + *t; } { *self = *self + *t; }
} }
impl<N: Add<N, N>> Translatable<Vec2<N>, Vec2<N>> for Vec2<N>
{
#[inline(always)]
fn translated(&self, t: &Vec2<N>) -> Vec2<N>
{ self + *t }
}
impl<N: Mul<N, N> + Add<N, N>> Dot<N> for Vec2<N> impl<N: Mul<N, N> + Add<N, N>> Dot<N> for Vec2<N>
{ {
#[inline(always)] #[inline(always)]

View File

@ -8,7 +8,7 @@ use traits::dot::Dot;
use traits::sub_dot::SubDot; use traits::sub_dot::SubDot;
use traits::norm::Norm; use traits::norm::Norm;
use traits::flatten::Flatten; use traits::flatten::Flatten;
use traits::translation::Translation; use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[deriving(Eq, Ord, ToStr)] #[deriving(Eq, Ord, ToStr)]
@ -112,21 +112,24 @@ ScalarSub<N> for Vec3<N>
} }
} }
impl<N: Copy + Add<N, N>> Translation<Vec3<N>, Vec3<N>> for Vec3<N> impl<N: Copy + Add<N, N>> Translation<Vec3<N>> for Vec3<N>
{ {
#[inline(always)] #[inline(always)]
fn translation(&self) -> Vec3<N> fn translation(&self) -> Vec3<N>
{ copy *self } { copy *self }
#[inline(always)]
fn translated(&self, t: &Vec3<N>) -> Vec3<N>
{ self + *t }
#[inline(always)] #[inline(always)]
fn translate(&mut self, t: &Vec3<N>) fn translate(&mut self, t: &Vec3<N>)
{ *self = *self + *t; } { *self = *self + *t; }
} }
impl<N: Add<N, N>> Translatable<Vec3<N>, Vec3<N>> for Vec3<N>
{
#[inline(always)]
fn translated(&self, t: &Vec3<N>) -> Vec3<N>
{ self + *t }
}
impl<N: Neg<N>> Neg<Vec3<N>> for Vec3<N> impl<N: Neg<N>> Neg<Vec3<N>> for Vec3<N>

View File

@ -64,6 +64,7 @@ pub mod traits
pub mod norm; pub mod norm;
pub mod rotation; pub mod rotation;
pub mod translation; pub mod translation;
pub mod transformation;
pub mod delta_transform; pub mod delta_transform;
pub mod vector_space; pub mod vector_space;
pub mod ring; pub mod ring;

View File

@ -8,7 +8,7 @@ use traits::division_ring::DivisionRing;
use traits::dot::Dot; use traits::dot::Dot;
use traits::sub_dot::SubDot; use traits::sub_dot::SubDot;
use traits::norm::Norm; use traits::norm::Norm;
use traits::translation::Translation; use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[deriving(Eq, Ord, ToStr, Clone)] #[deriving(Eq, Ord, ToStr, Clone)]
@ -196,21 +196,24 @@ ScalarSub<N> for DVec<N>
} }
} }
impl<N: Clone + Copy + Add<N, N>> Translation<DVec<N>, DVec<N>> for DVec<N> impl<N: Clone + Copy + Add<N, N>> Translation<DVec<N>> for DVec<N>
{ {
#[inline(always)] #[inline(always)]
fn translation(&self) -> DVec<N> fn translation(&self) -> DVec<N>
{ self.clone() } { self.clone() }
#[inline(always)]
fn translated(&self, t: &DVec<N>) -> DVec<N>
{ self + *t }
#[inline(always)] #[inline(always)]
fn translate(&mut self, t: &DVec<N>) fn translate(&mut self, t: &DVec<N>)
{ *self = *self + *t; } { *self = *self + *t; }
} }
impl<N: Add<N, N> + Copy> Translatable<DVec<N>, DVec<N>> for DVec<N>
{
#[inline(always)]
fn translated(&self, t: &DVec<N>) -> DVec<N>
{ self + *t }
}
impl<N: Copy + DivisionRing + Algebraic + Clone> impl<N: Copy + DivisionRing + Algebraic + Clone>
Norm<N> for DVec<N> Norm<N> for DVec<N>
{ {

View File

@ -11,7 +11,7 @@ use traits::dim::Dim;
use traits::dot::Dot; use traits::dot::Dot;
use traits::sub_dot::SubDot; use traits::sub_dot::SubDot;
use traits::norm::Norm; use traits::norm::Norm;
use traits::translation::Translation; use traits::translation::{Translation, Translatable};
use traits::flatten::Flatten; use traits::flatten::Flatten;
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
@ -123,21 +123,24 @@ ScalarSub<N> for NVec<D, N>
{ self.at.scalar_sub_inplace(s) } { self.at.scalar_sub_inplace(s) }
} }
impl<D: Dim, N: Clone + Copy + Add<N, N>> Translation<NVec<D, N>, NVec<D, N>> for NVec<D, N> impl<D: Dim, N: Clone + Copy + Add<N, N>> Translation<NVec<D, N>> for NVec<D, N>
{ {
#[inline(always)] #[inline(always)]
fn translation(&self) -> NVec<D, N> fn translation(&self) -> NVec<D, N>
{ self.clone() } { self.clone() }
#[inline(always)]
fn translated(&self, t: &NVec<D, N>) -> NVec<D, N>
{ self + *t }
#[inline(always)] #[inline(always)]
fn translate(&mut self, t: &NVec<D, N>) fn translate(&mut self, t: &NVec<D, N>)
{ *self = *self + *t; } { *self = *self + *t; }
} }
impl<D: Dim, N: Add<N, N> + Copy> Translatable<NVec<D, N>, NVec<D, N>> for NVec<D, N>
{
#[inline(always)]
fn translated(&self, t: &NVec<D, N>) -> NVec<D, N>
{ self + *t }
}
impl<D: Dim, N: Copy + DivisionRing + Algebraic + Clone> impl<D: Dim, N: Copy + DivisionRing + Algebraic + Clone>
Norm<N> for NVec<D, N> Norm<N> for NVec<D, N>
{ {

View File

@ -3,13 +3,13 @@ use std::vec;
#[test] #[test]
use std::num::{Real, Zero, One, abs}; use std::num::{Real, Zero, One, abs};
#[test] #[test]
use std::rand::{random}; use std::rand::random;
#[test] #[test]
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
#[test] #[test]
use traits::inv::Inv; use traits::inv::Inv;
#[test] #[test]
use traits::rotation::Rotation; use traits::rotation::{Rotation, Rotatable};
#[test] #[test]
use traits::dim::d7; use traits::dim::d7;
#[test] #[test]

View File

@ -1,19 +1,22 @@
use traits::translation::Translation; use traits::translation::{Translation, Translatable};
/// Trait of object which represent a rotation, and to wich new rotations can /// Trait of object which represent a rotation, and to wich new rotations can
/// be appended. A rotation is assumed to be an isomitry without translation /// be appended. A rotation is assumed to be an isomitry without translation
/// and without reflexion. /// and without reflexion.
pub trait Rotation<V, Res> pub trait Rotation<V>
{ {
/// Gets the rotation associated with this object. /// Gets the rotation associated with this object.
fn rotation(&self) -> V; fn rotation(&self) -> V;
/// In-place version of `rotated`.
fn rotate(&mut self, &V);
}
pub trait Rotatable<V, Res: Rotation<V>>
{
/// Appends a rotation from an alternative representation. Such /// Appends a rotation from an alternative representation. Such
/// representation has the same format as the one returned by `rotation`. /// representation has the same format as the one returned by `rotation`.
fn rotated(&self, &V) -> Res; fn rotated(&self, &V) -> Res;
/// In-place version of `rotated`.
fn rotate(&mut self, &V);
} }
/** /**
@ -24,13 +27,11 @@ pub trait Rotation<V, Res>
* - `point`: the center of rotation. * - `point`: the center of rotation.
*/ */
#[inline(always)] #[inline(always)]
pub fn rotate_wrt_point<M: Translation<LV, ResT>, pub fn rotate_wrt_point<M: Translatable<LV, M2>,
ResT: Rotation<AV, Res> + Translation<LV, ResT2>, M2: Rotation<AV> + Translation<LV>,
ResT2,
Res,
LV: Neg<LV>, LV: Neg<LV>,
AV> AV>
(m: &M, ammount: &AV, center: &LV) -> ResT (m: &M, ammount: &AV, center: &LV) -> M2
{ {
let mut res = m.translated(&-center); let mut res = m.translated(&-center);

View File

@ -0,0 +1,13 @@
pub trait Transformation<M>
{
fn transformation(&self) -> M;
// XXX: we must use "transform_by" instead of "transform" because of a
// conflict with some iterator function…
fn transform_by(&mut self, &M);
}
pub trait Transformable<M, Res: Transformation<M>>
{
fn transformed(&self, &M) -> Res;
}

View File

@ -1,14 +1,18 @@
/// Trait of object which represent a translation, and to wich new translation /// Trait of object which represent a translation, and to wich new translation
/// can be appended. /// can be appended.
pub trait Translation<V, Res> pub trait Translation<V>
{ {
// FIXME: add a "from translation: translantion(V) -> Self ?
/// Gets the translation associated with this object. /// Gets the translation associated with this object.
fn translation(&self) -> V; fn translation(&self) -> V;
/// Appends a translation from an alternative representation. Such
/// representation has the same format as the one returned by `translation`.
fn translated(&self, &V) -> Res;
/// In-place version of `translate`. /// In-place version of `translate`.
fn translate(&mut self, &V); fn translate(&mut self, &V);
} }
pub trait Translatable<V, Res: Translation<V>>
{
/// Appends a translation from an alternative representation. Such
/// representation has the same format as the one returned by `translation`.
fn translated(&self, &V) -> Res;
}