use std::num::{One, Zero}; use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; use traits::rlmul::{RMul, LMul}; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; use traits::rotation::{Rotation, Rotatable}; use traits::delta_transform::{DeltaTransform, DeltaTransformVector}; use dim1::vec1::Vec1; use dim2::mat2::Mat2; use dim3::mat3::Mat3; use dim3::vec3::{Vec3}; #[deriving(Eq, ToStr)] pub struct Rotmat { priv submat: M } 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 + One + Sub + Add + Mul> (axis: &Vec3, angle: N) -> Rotmat> { let _1 = One::one::(); let ux = copy axis.x; let uy = copy axis.y; let uz = copy axis.z; 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 + Trigonometric + Neg + Mul + Add + Copy> Rotation> for Rotmat> { #[inline] fn rotation(&self) -> Vec1 { Vec1::new(-(self.submat.m12 / self.submat.m11).atan()) } #[inline] fn rotate(&mut self, rot: &Vec1) { *self = self.rotated(rot) } } impl + Trigonometric + Neg + Mul + Add + Copy> Rotatable, Rotmat>> for Rotmat> { #[inline] fn rotated(&self, rot: &Vec1) -> Rotmat> { rotmat2(copy rot.x) * *self } } impl + Trigonometric + Neg + Mul + Add + Copy + One + Sub> Rotation<(Vec3, N)> for Rotmat> { #[inline] fn rotation(&self) -> (Vec3, N) { fail!("Not yet implemented.") } #[inline] 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] fn rotated(&self, &(axis, angle): &(Vec3, N)) -> Rotmat> { rotmat3(&axis, angle) * *self } } impl> Rand for Rotmat> { #[inline] fn rand(rng: &mut R) -> Rotmat> { rotmat2(rng.gen()) } } impl + One + Sub + Add + Mul> Rand for Rotmat> { #[inline] fn rand(rng: &mut R) -> Rotmat> { rotmat3(&rng.gen(), 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 DeltaTransform for Rotmat { #[inline] fn delta_transform(&self) -> M { copy self.submat } } impl, V> DeltaTransformVector for Rotmat { #[inline] fn delta_transform_vector(&self, v: &V) -> V { self.submat.rmul(v) } } 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() } } 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) } }