From 6723693b49147398f5e23b1456005ac04ab90b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Thu, 27 Jun 2013 16:16:07 +0000 Subject: [PATCH] Refined traits for rotation/translation/transformation. --- src/adaptors/rotmat.rs | 31 +++++++++++------ src/adaptors/transform.rs | 66 ++++++++++++++++++++++++++---------- src/dim1/vec1.rs | 15 ++++---- src/dim2/vec2.rs | 15 ++++---- src/dim3/vec3.rs | 15 ++++---- src/nalgebra.rc | 1 + src/ndim/dvec.rs | 15 ++++---- src/ndim/nvec.rs | 15 ++++---- src/tests/mat.rs | 4 +-- src/traits/rotation.rs | 21 ++++++------ src/traits/transformation.rs | 13 +++++++ src/traits/translation.rs | 14 +++++--- 12 files changed, 149 insertions(+), 76 deletions(-) create mode 100644 src/traits/transformation.rs diff --git a/src/adaptors/rotmat.rs b/src/adaptors/rotmat.rs index e6708def..162eb1a9 100644 --- a/src/adaptors/rotmat.rs +++ b/src/adaptors/rotmat.rs @@ -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 + One + Sub + Add + } impl + Trigonometric + Neg + Mul + Add + Copy> -Rotation, Rotmat>> for Rotmat> +Rotation> for Rotmat> { #[inline(always)] fn rotation(&self) -> Vec1 { Vec1::new(-(self.submat.m12 / self.submat.m11).atan()) } - #[inline(always)] - fn rotated(&self, rot: &Vec1) -> Rotmat> - { rotmat2(copy rot.x) * *self } - #[inline(always)] fn rotate(&mut self, rot: &Vec1) { *self = self.rotated(rot) } } +impl + Trigonometric + Neg + Mul + Add + Copy> +Rotatable, Rotmat>> for Rotmat> +{ + #[inline(always)] + fn rotated(&self, rot: &Vec1) -> Rotmat> + { rotmat2(copy rot.x) * *self } +} + impl + Trigonometric + Neg + Mul + Add + Copy + One + Sub> -Rotation<(Vec3, N), Rotmat>> for Rotmat> +Rotation<(Vec3, N)> for Rotmat> { #[inline(always)] fn rotation(&self) -> (Vec3, N) { fail!("Not yet implemented.") } - #[inline(always)] - fn rotated(&self, &(axis, angle): &(Vec3, N)) -> Rotmat> - { rotmat3(&axis, angle) * *self } - #[inline(always)] fn rotate(&mut self, rot: &(Vec3, N)) { *self = self.rotated(rot) } } +impl + Trigonometric + Neg + Mul + Add + Copy + + One + Sub> +Rotatable<(Vec3, N), Rotmat>> for Rotmat> +{ + #[inline(always)] + fn rotated(&self, &(axis, angle): &(Vec3, N)) -> Rotmat> + { rotmat3(&axis, angle) * *self } +} + impl> Rand for Rotmat> { #[inline(always)] diff --git a/src/adaptors/transform.rs b/src/adaptors/transform.rs index 0ae2e6bf..78019a2c 100644 --- a/src/adaptors/transform.rs +++ b/src/adaptors/transform.rs @@ -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, V: Add> LMul for Transform { self.submat.lmul(other) + self.subtrans } } -impl, Res> Translation> for Transform +impl> Translation for Transform { #[inline(always)] fn translation(&self) -> V { self.subtrans.translation() } - #[inline(always)] - fn translated(&self, t: &V) -> Transform - { Transform::new(copy self.submat, self.subtrans.translated(t)) } - #[inline(always)] fn translate(&mut self, t: &V) { self.subtrans.translate(t) } } -impl + One, - Res: RMul, +impl, Res: Translation> +Translatable> for Transform +{ + #[inline(always)] + fn translated(&self, t: &V) -> Transform + { Transform::new(copy self.submat, self.subtrans.translated(t)) } +} + +impl + RMul + One, V, AV> -Rotation> for Transform +Rotation for Transform { #[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::(); + delta.rotate(rot); + self.submat.rotate(rot); + self.subtrans = delta.rmul(&self.subtrans); + } +} + +impl + One, + Res: Rotation + RMul, + V, + AV> +Rotatable> for Transform +{ #[inline(always)] fn rotated(&self, rot: &AV) -> Transform { @@ -106,15 +127,24 @@ Rotation> for Transform 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::().rotated(rot); - self.submat.rotate(rot); - self.subtrans = delta.rmul(&self.subtrans); - } +impl + Mul + Copy, V: Add + Copy> Transformation> for Transform +{ + fn transformation(&self) -> Transform + { copy *self } + + fn transform_by(&mut self, other: &Transform) + { *self = other * *self; } +} + +// FIXME: constraints are too restrictive. +// Should be: Transformable ... +impl + Mul, V: Add> +Transformable, Transform> for Transform +{ + fn transformed(&self, t: &Transform) -> Transform + { t * *self } } impl DeltaTransform for Transform diff --git a/src/dim1/vec1.rs b/src/dim1/vec1.rs index 919768ab..9259820c 100644 --- a/src/dim1/vec1.rs +++ b/src/dim1/vec1.rs @@ -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 for Vec1 { self.x = self.x - *s; } } -impl> Translation, Vec1> for Vec1 +impl> Translation> for Vec1 { #[inline(always)] fn translation(&self) -> Vec1 { copy *self } - #[inline(always)] - fn translated(&self, t: &Vec1) -> Vec1 - { self + *t } - #[inline(always)] fn translate(&mut self, t: &Vec1) { *self = *self + *t } } +impl> Translatable, Vec1> for Vec1 +{ + #[inline(always)] + fn translated(&self, t: &Vec1) -> Vec1 + { self + *t } +} + impl> Dot for Vec1 { #[inline(always)] diff --git a/src/dim2/vec2.rs b/src/dim2/vec2.rs index bfa7cbcb..fbddbe23 100644 --- a/src/dim2/vec2.rs +++ b/src/dim2/vec2.rs @@ -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 for Vec2 } } -impl> Translation, Vec2> for Vec2 +impl> Translation> for Vec2 { #[inline(always)] fn translation(&self) -> Vec2 { copy *self } - #[inline(always)] - fn translated(&self, t: &Vec2) -> Vec2 - { self + *t } - #[inline(always)] fn translate(&mut self, t: &Vec2) { *self = *self + *t; } } +impl> Translatable, Vec2> for Vec2 +{ + #[inline(always)] + fn translated(&self, t: &Vec2) -> Vec2 + { self + *t } +} + impl + Add> Dot for Vec2 { #[inline(always)] diff --git a/src/dim3/vec3.rs b/src/dim3/vec3.rs index 1955d0e4..42054899 100644 --- a/src/dim3/vec3.rs +++ b/src/dim3/vec3.rs @@ -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 for Vec3 } } -impl> Translation, Vec3> for Vec3 +impl> Translation> for Vec3 { #[inline(always)] fn translation(&self) -> Vec3 { copy *self } - #[inline(always)] - fn translated(&self, t: &Vec3) -> Vec3 - { self + *t } - #[inline(always)] fn translate(&mut self, t: &Vec3) { *self = *self + *t; } } +impl> Translatable, Vec3> for Vec3 +{ + #[inline(always)] + fn translated(&self, t: &Vec3) -> Vec3 + { self + *t } +} + impl> Neg> for Vec3 diff --git a/src/nalgebra.rc b/src/nalgebra.rc index 86832a48..aeb28824 100644 --- a/src/nalgebra.rc +++ b/src/nalgebra.rc @@ -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; diff --git a/src/ndim/dvec.rs b/src/ndim/dvec.rs index fdd51baf..09bb8e89 100644 --- a/src/ndim/dvec.rs +++ b/src/ndim/dvec.rs @@ -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 for DVec } } -impl> Translation, DVec> for DVec +impl> Translation> for DVec { #[inline(always)] fn translation(&self) -> DVec { self.clone() } - #[inline(always)] - fn translated(&self, t: &DVec) -> DVec - { self + *t } - #[inline(always)] fn translate(&mut self, t: &DVec) { *self = *self + *t; } } +impl + Copy> Translatable, DVec> for DVec +{ + #[inline(always)] + fn translated(&self, t: &DVec) -> DVec + { self + *t } +} + impl Norm for DVec { diff --git a/src/ndim/nvec.rs b/src/ndim/nvec.rs index fccd6dd9..93a1b309 100644 --- a/src/ndim/nvec.rs +++ b/src/ndim/nvec.rs @@ -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 for NVec { self.at.scalar_sub_inplace(s) } } -impl> Translation, NVec> for NVec +impl> Translation> for NVec { #[inline(always)] fn translation(&self) -> NVec { self.clone() } - #[inline(always)] - fn translated(&self, t: &NVec) -> NVec - { self + *t } - #[inline(always)] fn translate(&mut self, t: &NVec) { *self = *self + *t; } } +impl + Copy> Translatable, NVec> for NVec +{ + #[inline(always)] + fn translated(&self, t: &NVec) -> NVec + { self + *t } +} + impl Norm for NVec { diff --git a/src/tests/mat.rs b/src/tests/mat.rs index c4ff87fd..ace9df27 100644 --- a/src/tests/mat.rs +++ b/src/tests/mat.rs @@ -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] diff --git a/src/traits/rotation.rs b/src/traits/rotation.rs index ce89bc25..101da942 100644 --- a/src/traits/rotation.rs +++ b/src/traits/rotation.rs @@ -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 +pub trait Rotation { /// Gets the rotation associated with this object. fn rotation(&self) -> V; + /// In-place version of `rotated`. + fn rotate(&mut self, &V); +} + +pub trait Rotatable> +{ /// 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 * - `point`: the center of rotation. */ #[inline(always)] -pub fn rotate_wrt_point, - ResT: Rotation + Translation, - ResT2, - Res, +pub fn rotate_wrt_point, + M2: Rotation + Translation, LV: Neg, AV> - (m: &M, ammount: &AV, center: &LV) -> ResT + (m: &M, ammount: &AV, center: &LV) -> M2 { let mut res = m.translated(&-center); diff --git a/src/traits/transformation.rs b/src/traits/transformation.rs new file mode 100644 index 00000000..62cff98f --- /dev/null +++ b/src/traits/transformation.rs @@ -0,0 +1,13 @@ +pub trait Transformation +{ + 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> +{ + fn transformed(&self, &M) -> Res; +} diff --git a/src/traits/translation.rs b/src/traits/translation.rs index ead1bdfb..705f5d3b 100644 --- a/src/traits/translation.rs +++ b/src/traits/translation.rs @@ -1,14 +1,18 @@ /// Trait of object which represent a translation, and to wich new translation /// can be appended. -pub trait Translation +pub trait Translation { + // 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> +{ + /// Appends a translation from an alternative representation. Such + /// representation has the same format as the one returned by `translation`. + fn translated(&self, &V) -> Res; +}