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