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::inv::Inv;
use traits::transpose::Transpose;
use traits::rotation::Rotation;
use traits::rotation::{Rotation, Rotatable};
use traits::delta_transform::{DeltaTransform, DeltaTransformVector};
use dim1::vec1::Vec1;
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>
Rotation<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>>
Rotation<Vec1<N>> for Rotmat<Mat2<N>>
{
#[inline(always)]
fn rotation(&self) -> Vec1<N>
{ 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)]
fn rotate(&mut self, rot: &Vec1<N>)
{ *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 +
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)]
fn rotation(&self) -> (Vec3<N>, N)
{ fail!("Not yet implemented.") }
#[inline(always)]
fn rotated(&self, &(axis, angle): &(Vec3<N>, N)) -> Rotmat<Mat3<N>>
{ rotmat3(&axis, angle) * *self }
#[inline(always)]
fn rotate(&mut self, rot: &(Vec3<N>, N))
{ *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>>
{
#[inline(always)]

View File

@ -3,8 +3,9 @@ use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::rotation::Rotation;
use traits::translation::Translation;
use traits::rotation::{Rotation, Rotatable};
use traits::translation::{Translation, Translatable};
use traits::transformation::{Transformation, Transformable};
use traits::transpose::Transpose;
use traits::delta_transform::{DeltaTransform, DeltaTransformVector};
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 }
}
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)]
fn translation(&self) -> V
{ self.subtrans.translation() }
#[inline(always)]
fn translated(&self, t: &V) -> Transform<M, Res>
{ Transform::new(copy self.submat, self.subtrans.translated(t)) }
#[inline(always)]
fn translate(&mut self, t: &V)
{ self.subtrans.translate(t) }
}
impl<M: Rotation<AV, Res> + One,
Res: RMul<V>,
impl<M: Copy, V: Translatable<V, Res>, Res: Translation<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,
AV>
Rotation<AV, Transform<Res, V>> for Transform<M, V>
Rotation<AV> for Transform<M, V>
{
#[inline(always)]
fn rotation(&self) -> AV
{ 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)]
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))
}
}
#[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>

View File

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

View File

@ -9,7 +9,7 @@ use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::flatten::Flatten;
use traits::translation::Translation;
use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[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)]
fn translation(&self) -> Vec2<N>
{ copy *self }
#[inline(always)]
fn translated(&self, t: &Vec2<N>) -> Vec2<N>
{ self + *t }
#[inline(always)]
fn translate(&mut self, t: &Vec2<N>)
{ *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>
{
#[inline(always)]

View File

@ -8,7 +8,7 @@ use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::flatten::Flatten;
use traits::translation::Translation;
use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[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)]
fn translation(&self) -> Vec3<N>
{ copy *self }
#[inline(always)]
fn translated(&self, t: &Vec3<N>) -> Vec3<N>
{ self + *t }
#[inline(always)]
fn translate(&mut self, t: &Vec3<N>)
{ *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>

View File

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

View File

@ -8,7 +8,7 @@ use traits::division_ring::DivisionRing;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::translation::Translation;
use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[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)]
fn translation(&self) -> DVec<N>
{ self.clone() }
#[inline(always)]
fn translated(&self, t: &DVec<N>) -> DVec<N>
{ self + *t }
#[inline(always)]
fn translate(&mut self, t: &DVec<N>)
{ *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>
Norm<N> for DVec<N>
{

View File

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

View File

@ -3,13 +3,13 @@ use std::vec;
#[test]
use std::num::{Real, Zero, One, abs};
#[test]
use std::rand::{random};
use std::rand::random;
#[test]
use std::cmp::ApproxEq;
#[test]
use traits::inv::Inv;
#[test]
use traits::rotation::Rotation;
use traits::rotation::{Rotation, Rotatable};
#[test]
use traits::dim::d7;
#[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
/// be appended. A rotation is assumed to be an isomitry without translation
/// and without reflexion.
pub trait Rotation<V, Res>
pub trait Rotation<V>
{
/// Gets the rotation associated with this object.
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
/// representation has the same format as the one returned by `rotation`.
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.
*/
#[inline(always)]
pub fn rotate_wrt_point<M: Translation<LV, ResT>,
ResT: Rotation<AV, Res> + Translation<LV, ResT2>,
ResT2,
Res,
pub fn rotate_wrt_point<M: Translatable<LV, M2>,
M2: Rotation<AV> + Translation<LV>,
LV: Neg<LV>,
AV>
(m: &M, ammount: &AV, center: &LV) -> ResT
(m: &M, ammount: &AV, center: &LV) -> M2
{
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
/// 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.
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`.
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;
}