use std::num::{One, Zero}; use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; use traits::division_ring::DivisionRing; use traits::rlmul::{RMul, LMul}; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; use traits::rotation::{Rotation, Rotate, Rotatable}; use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable use traits::homogeneous::ToHomogeneous; use traits::indexable::Indexable; use traits::norm::Norm; use vec::Vec1; use mat::{Mat2, Mat3}; use vec::Vec3; #[deriving(Eq, ToStr)] pub struct Rotmat { priv submat: M } impl Rotmat { pub fn submat(&self) -> M { copy self.submat } } pub fn rotmat2>(angle: N) -> Rotmat> { let coa = angle.cos(); let sia = angle.sin(); Rotmat { submat: Mat2::new( [ copy coa, -sia, copy sia, copy coa ] ) } } pub fn rotmat3 (axisangle: Vec3) -> Rotmat> { let mut axis = axisangle; let angle = axis.normalize(); let _1 = One::one::(); let ux = copy axis.at[0]; let uy = copy axis.at[1]; let uz = copy axis.at[2]; let sqx = ux * ux; let sqy = uy * uy; let sqz = uz * uz; let cos = angle.cos(); let one_m_cos = _1 - cos; let sin = angle.sin(); Rotmat { submat: Mat3::new( [ (sqx + (_1 - sqx) * cos), (ux * uy * one_m_cos - uz * sin), (ux * uz * one_m_cos + uy * sin), (ux * uy * one_m_cos + uz * sin), (sqy + (_1 - sqy) * cos), (uy * uz * one_m_cos - ux * sin), (ux * uz * one_m_cos - uy * sin), (uy * uz * one_m_cos + ux * sin), (sqz + (_1 - sqz) * cos) ] ) } } impl Rotation> for Rotmat> { #[inline] fn rotation(&self) -> Vec1 { Vec1::new([ -(self.submat.at((0, 1)) / self.submat.at((0, 0))).atan() ]) } #[inline] fn inv_rotation(&self) -> Vec1 { -self.rotation() } #[inline] fn rotate_by(&mut self, rot: &Vec1) { *self = self.rotated(rot) } } impl Rotatable, Rotmat>> for Rotmat> { #[inline] fn rotated(&self, rot: &Vec1) -> Rotmat> { rotmat2(copy rot.at[0]) * *self } } impl Rotation> for Rotmat> { #[inline] fn rotation(&self) -> Vec3 { fail!("Not yet implemented.") } #[inline] fn inv_rotation(&self) -> Vec3 { fail!("Not yet implemented.") } #[inline] fn rotate_by(&mut self, rot: &Vec3) { *self = self.rotated(rot) } } impl Rotatable, Rotmat>> for Rotmat> { #[inline] fn rotated(&self, axisangle: &Vec3) -> Rotmat> { rotmat3(copy *axisangle) * *self } } impl> Rand for Rotmat> { #[inline] fn rand(rng: &mut R) -> Rotmat> { rotmat2(rng.gen()) } } impl + LMul, V> Rotate for Rotmat { #[inline] fn rotate(&self, v: &V) -> V { self.rmul(v) } #[inline] fn inv_rotate(&self, v: &V) -> V { self.lmul(v) } } impl + LMul, V> Transform for Rotmat { #[inline] fn transform_vec(&self, v: &V) -> V { self.rotate(v) } #[inline] fn inv_transform(&self, v: &V) -> V { self.inv_rotate(v) } } impl Rand for Rotmat> { #[inline] fn rand(rng: &mut R) -> Rotmat> { rotmat3(rng.gen()) } } impl Dim for Rotmat { #[inline] fn dim() -> uint { Dim::dim::() } } impl One for Rotmat { #[inline] fn one() -> Rotmat { Rotmat { submat: One::one() } } } impl> Mul, Rotmat> for Rotmat { #[inline] fn mul(&self, other: &Rotmat) -> Rotmat { Rotmat { submat: self.submat.mul(&other.submat) } } } impl> RMul for Rotmat { #[inline] fn rmul(&self, other: &V) -> V { self.submat.rmul(other) } } impl> LMul for Rotmat { #[inline] fn lmul(&self, other: &V) -> V { self.submat.lmul(other) } } impl Inv for Rotmat { #[inline] fn invert(&mut self) { self.transpose() } #[inline] fn inverse(&self) -> Rotmat { self.transposed() } } impl Transpose for Rotmat { #[inline] fn transposed(&self) -> Rotmat { Rotmat { submat: self.submat.transposed() } } #[inline] fn transpose(&mut self) { self.submat.transpose() } } // we loose the info that we are a rotation matrix impl, M2> ToHomogeneous for Rotmat { fn to_homogeneous(&self) -> M2 { self.submat.to_homogeneous() } } impl, M: ApproxEq> ApproxEq for Rotmat { #[inline] fn approx_epsilon() -> N { ApproxEq::approx_epsilon::() } #[inline] fn approx_eq(&self, other: &Rotmat) -> bool { self.submat.approx_eq(&other.submat) } #[inline] fn approx_eq_eps(&self, other: &Rotmat, epsilon: &N) -> bool { self.submat.approx_eq_eps(&other.submat, epsilon) } }