use std::num::{One, Zero}; 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::transpose::Transpose; use traits::delta_transform::{DeltaTransform, DeltaTransformVector}; use traits::rlmul::{RMul, LMul}; #[deriving(Eq, ToStr)] pub struct Transform { priv submat : M, priv subtrans : V } impl Transform { #[inline(always)] pub fn new(mat: M, trans: V) -> Transform { Transform { submat: mat, subtrans: trans } } } impl Dim for Transform { #[inline(always)] fn dim() -> uint { Dim::dim::() } } impl One for Transform { #[inline(always)] fn one() -> Transform { Transform { submat: One::one(), subtrans: Zero::zero() } } } impl Zero for Transform { #[inline(always)] fn zero() -> Transform { Transform { submat: Zero::zero(), subtrans: Zero::zero() } } #[inline(always)] fn is_zero(&self) -> bool { self.submat.is_zero() && self.subtrans.is_zero() } } impl + Mul, V:Copy + Add> Mul, Transform> for Transform { #[inline(always)] fn mul(&self, other: &Transform) -> Transform { Transform { submat: self.submat * other.submat, subtrans: self.subtrans + self.submat.rmul(&other.subtrans) } } } impl, V: Add> RMul for Transform { #[inline(always)] fn rmul(&self, other: &V) -> V { self.submat.rmul(other) + self.subtrans } } impl, V: Add> LMul for Transform { #[inline(always)] fn lmul(&self, other: &V) -> V { self.submat.lmul(other) + self.subtrans } } 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 + Copy + RMul + One, V: Copy, AV> Rotation for Transform { #[inline(always)] fn rotation(&self) -> AV { self.submat.rotation() } #[inline(always)] fn rotated(&self, rot: &AV) -> Transform { // FIXME: this does not seem opitmal let delta = One::one::().rotated(rot); 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 DeltaTransform for Transform { #[inline(always)] fn delta_transform(&self) -> M { copy self.submat } } impl + Copy, V> DeltaTransformVector for Transform { #[inline(always)] fn delta_transform_vector(&self, v: &V) -> V { self.submat.rmul(v) } } impl, V:Copy + Neg> Inv for Transform { #[inline(always)] fn invert(&mut self) { self.submat.invert(); self.subtrans = self.submat.rmul(&-self.subtrans); } #[inline(always)] fn inverse(&self) -> Transform { let mut res = copy *self; res.invert(); res } } impl, M:ApproxEq, V:ApproxEq> ApproxEq for Transform { #[inline(always)] fn approx_epsilon() -> N { ApproxEq::approx_epsilon::() } #[inline(always)] fn approx_eq(&self, other: &Transform) -> bool { self.submat.approx_eq(&other.submat) && self.subtrans.approx_eq(&other.subtrans) } #[inline(always)] fn approx_eq_eps(&self, other: &Transform, epsilon: &N) -> bool { self.submat.approx_eq_eps(&other.submat, epsilon) && self.subtrans.approx_eq_eps(&other.subtrans, epsilon) } } impl Rand for Transform { #[inline(always)] fn rand(rng: &mut R) -> Transform { Transform::new(rng.gen(), rng.gen()) } }