2013-06-02 02:50:00 +08:00
|
|
|
use std::num::{One, Zero};
|
|
|
|
use std::rand::{Rand, Rng, RngUtil};
|
|
|
|
use std::cmp::ApproxEq;
|
2013-06-29 06:55:09 +08:00
|
|
|
use traits::division_ring::DivisionRing;
|
2013-06-16 04:16:44 +08:00
|
|
|
use traits::rlmul::{RMul, LMul};
|
2013-05-17 05:30:39 +08:00
|
|
|
use traits::dim::Dim;
|
|
|
|
use traits::inv::Inv;
|
|
|
|
use traits::transpose::Transpose;
|
2013-06-29 05:03:40 +08:00
|
|
|
use traits::rotation::{Rotation, Rotate, Rotatable};
|
|
|
|
use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable
|
2013-06-29 19:40:31 +08:00
|
|
|
use traits::homogeneous::ToHomogeneous;
|
|
|
|
use traits::indexable::Indexable;
|
2013-06-29 23:32:56 +08:00
|
|
|
use traits::norm::Norm;
|
2013-06-29 05:03:40 +08:00
|
|
|
use vec::Vec1;
|
2013-06-29 06:55:09 +08:00
|
|
|
use mat::{Mat2, Mat3};
|
2013-06-29 05:03:40 +08:00
|
|
|
use vec::Vec3;
|
2013-05-17 05:30:39 +08:00
|
|
|
|
2013-05-26 02:30:03 +08:00
|
|
|
#[deriving(Eq, ToStr)]
|
2013-05-17 05:30:39 +08:00
|
|
|
pub struct Rotmat<M>
|
2013-06-27 04:56:30 +08:00
|
|
|
{ priv submat: M }
|
2013-05-20 03:45:30 +08:00
|
|
|
|
2013-06-30 02:37:01 +08:00
|
|
|
impl<M: Copy> Rotmat<M>
|
|
|
|
{
|
|
|
|
pub fn submat(&self) -> M
|
|
|
|
{ copy self.submat }
|
|
|
|
}
|
|
|
|
|
2013-06-10 07:36:47 +08:00
|
|
|
pub fn rotmat2<N: Copy + Trigonometric + Neg<N>>(angle: N) -> Rotmat<Mat2<N>>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-05-20 18:02:02 +08:00
|
|
|
let coa = angle.cos();
|
|
|
|
let sia = angle.sin();
|
2013-05-17 05:30:39 +08:00
|
|
|
|
|
|
|
Rotmat
|
2013-06-29 06:55:09 +08:00
|
|
|
{ submat: Mat2::new( [ copy coa, -sia, copy sia, copy coa ] ) }
|
2013-05-17 05:30:39 +08:00
|
|
|
}
|
|
|
|
|
2013-06-29 23:32:56 +08:00
|
|
|
pub fn rotmat3<N: Copy + Trigonometric + DivisionRing + Algebraic>
|
|
|
|
(axisangle: Vec3<N>) -> Rotmat<Mat3<N>>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-29 23:32:56 +08:00
|
|
|
let mut axis = axisangle;
|
|
|
|
let angle = axis.normalize();
|
2013-06-10 07:36:47 +08:00
|
|
|
let _1 = One::one::<N>();
|
2013-06-29 05:03:40 +08:00
|
|
|
let ux = copy axis.at[0];
|
|
|
|
let uy = copy axis.at[1];
|
|
|
|
let uz = copy axis.at[2];
|
2013-05-17 05:30:39 +08:00
|
|
|
let sqx = ux * ux;
|
|
|
|
let sqy = uy * uy;
|
|
|
|
let sqz = uz * uz;
|
2013-05-20 18:02:02 +08:00
|
|
|
let cos = angle.cos();
|
2013-05-17 05:30:39 +08:00
|
|
|
let one_m_cos = _1 - cos;
|
2013-05-20 18:02:02 +08:00
|
|
|
let sin = angle.sin();
|
2013-05-17 05:30:39 +08:00
|
|
|
|
|
|
|
Rotmat {
|
2013-06-29 06:55:09 +08:00
|
|
|
submat: Mat3::new( [
|
2013-05-17 05:30:39 +08:00
|
|
|
(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),
|
2013-06-29 06:55:09 +08:00
|
|
|
(sqz + (_1 - sqz) * cos) ] )
|
2013-05-17 05:30:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-29 06:55:09 +08:00
|
|
|
impl<N: Trigonometric + DivisionRing + Copy>
|
2013-06-28 00:16:07 +08:00
|
|
|
Rotation<Vec1<N>> for Rotmat<Mat2<N>>
|
2013-05-19 19:44:27 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-10 07:36:47 +08:00
|
|
|
fn rotation(&self) -> Vec1<N>
|
2013-06-29 19:40:31 +08:00
|
|
|
{ Vec1::new([ -(self.submat.at((0, 1)) / self.submat.at((0, 0))).atan() ]) }
|
2013-05-19 19:44:27 +08:00
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-29 05:03:40 +08:00
|
|
|
fn inv_rotation(&self) -> Vec1<N>
|
|
|
|
{ -self.rotation() }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn rotate_by(&mut self, rot: &Vec1<N>)
|
2013-05-19 19:44:27 +08:00
|
|
|
{ *self = self.rotated(rot) }
|
|
|
|
}
|
|
|
|
|
2013-06-29 06:55:09 +08:00
|
|
|
impl<N: Trigonometric + DivisionRing + Copy>
|
2013-06-28 00:16:07 +08:00
|
|
|
Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-28 00:16:07 +08:00
|
|
|
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
|
2013-06-29 05:03:40 +08:00
|
|
|
{ rotmat2(copy rot.at[0]) * *self }
|
2013-06-28 00:16:07 +08:00
|
|
|
}
|
|
|
|
|
2013-06-29 23:32:56 +08:00
|
|
|
impl<N: Copy + Trigonometric + DivisionRing + Algebraic>
|
|
|
|
Rotation<Vec3<N>> for Rotmat<Mat3<N>>
|
2013-05-19 19:44:27 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-29 23:32:56 +08:00
|
|
|
fn rotation(&self) -> Vec3<N>
|
2013-05-19 19:44:27 +08:00
|
|
|
{ fail!("Not yet implemented.") }
|
2013-06-29 05:03:40 +08:00
|
|
|
#[inline]
|
|
|
|
|
2013-06-29 23:32:56 +08:00
|
|
|
fn inv_rotation(&self) -> Vec3<N>
|
2013-06-29 05:03:40 +08:00
|
|
|
{ fail!("Not yet implemented.") }
|
|
|
|
|
2013-05-19 19:44:27 +08:00
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-29 23:32:56 +08:00
|
|
|
fn rotate_by(&mut self, rot: &Vec3<N>)
|
2013-05-19 19:44:27 +08:00
|
|
|
{ *self = self.rotated(rot) }
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:32:56 +08:00
|
|
|
impl<N: Copy + Trigonometric + DivisionRing + Algebraic>
|
|
|
|
Rotatable<Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>>
|
2013-06-28 00:16:07 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-29 23:32:56 +08:00
|
|
|
fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>>
|
|
|
|
{ rotmat3(copy *axisangle) * *self }
|
2013-06-28 00:16:07 +08:00
|
|
|
}
|
|
|
|
|
2013-06-10 07:36:47 +08:00
|
|
|
impl<N: Copy + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>>
|
2013-05-18 08:11:59 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-10 07:36:47 +08:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>>
|
2013-05-19 04:03:45 +08:00
|
|
|
{ rotmat2(rng.gen()) }
|
2013-05-18 08:11:59 +08:00
|
|
|
}
|
|
|
|
|
2013-06-29 05:03:40 +08:00
|
|
|
impl<M: RMul<V> + LMul<V>, V> Rotate<V> for Rotmat<M>
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
fn rotate(&self, v: &V) -> V
|
|
|
|
{ self.rmul(v) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn inv_rotate(&self, v: &V) -> V
|
|
|
|
{ self.lmul(v) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<M: RMul<V> + LMul<V>, V> Transform<V> for Rotmat<M>
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
fn transform_vec(&self, v: &V) -> V
|
|
|
|
{ self.rotate(v) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn inv_transform(&self, v: &V) -> V
|
|
|
|
{ self.inv_rotate(v) }
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:32:56 +08:00
|
|
|
impl<N: Copy + Rand + Trigonometric + DivisionRing + Algebraic>
|
2013-06-10 07:36:47 +08:00
|
|
|
Rand for Rotmat<Mat3<N>>
|
2013-05-18 08:11:59 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-10 07:36:47 +08:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat3<N>>
|
2013-06-29 23:32:56 +08:00
|
|
|
{ rotmat3(rng.gen()) }
|
2013-05-18 08:11:59 +08:00
|
|
|
}
|
|
|
|
|
2013-05-17 05:30:39 +08:00
|
|
|
impl<M: Dim> Dim for Rotmat<M>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn dim() -> uint
|
|
|
|
{ Dim::dim::<M>() }
|
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M: One + Zero> One for Rotmat<M>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn one() -> Rotmat<M>
|
|
|
|
{ Rotmat { submat: One::one() } }
|
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M: Mul<M, M>> Mul<Rotmat<M>, Rotmat<M>> for Rotmat<M>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn mul(&self, other: &Rotmat<M>) -> Rotmat<M>
|
|
|
|
{ Rotmat { submat: self.submat.mul(&other.submat) } }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<V, M: RMul<V>> RMul<V> for Rotmat<M>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn rmul(&self, other: &V) -> V
|
|
|
|
{ self.submat.rmul(other) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<V, M: LMul<V>> LMul<V> for Rotmat<M>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn lmul(&self, other: &V) -> V
|
|
|
|
{ self.submat.lmul(other) }
|
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M: Transpose> Inv for Rotmat<M>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn invert(&mut self)
|
|
|
|
{ self.transpose() }
|
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn inverse(&self) -> Rotmat<M>
|
|
|
|
{ self.transposed() }
|
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M: Transpose>
|
2013-05-17 05:30:39 +08:00
|
|
|
Transpose for Rotmat<M>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn transposed(&self) -> Rotmat<M>
|
|
|
|
{ Rotmat { submat: self.submat.transposed() } }
|
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn transpose(&mut self)
|
|
|
|
{ self.submat.transpose() }
|
|
|
|
}
|
|
|
|
|
2013-06-29 19:40:31 +08:00
|
|
|
// we loose the info that we are a rotation matrix
|
|
|
|
impl<M: ToHomogeneous<M2>, M2> ToHomogeneous<M2> for Rotmat<M>
|
|
|
|
{
|
|
|
|
fn to_homogeneous(&self) -> M2
|
|
|
|
{ self.submat.to_homogeneous() }
|
|
|
|
}
|
|
|
|
|
2013-06-10 07:36:47 +08:00
|
|
|
impl<N: ApproxEq<N>, M: ApproxEq<N>> ApproxEq<N> for Rotmat<M>
|
2013-05-17 06:23:25 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-10 07:36:47 +08:00
|
|
|
fn approx_epsilon() -> N
|
|
|
|
{ ApproxEq::approx_epsilon::<N, N>() }
|
2013-05-17 06:23:25 +08:00
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-21 23:25:01 +08:00
|
|
|
fn approx_eq(&self, other: &Rotmat<M>) -> bool
|
|
|
|
{ self.submat.approx_eq(&other.submat) }
|
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-10 07:36:47 +08:00
|
|
|
fn approx_eq_eps(&self, other: &Rotmat<M>, epsilon: &N) -> bool
|
2013-05-21 23:25:01 +08:00
|
|
|
{ self.submat.approx_eq_eps(&other.submat, epsilon) }
|
2013-05-17 06:23:25 +08:00
|
|
|
}
|