use std::fmt;
use std::iter;
use std::ops::*;
use structure::*;
use angle::Rad;
use approx;
use euler::Euler;
use matrix::{Matrix2, Matrix3};
use num::BaseFloat;
use point::{Point2, Point3};
use quaternion::Quaternion;
use vector::{Vector2, Vector3};
pub trait Rotation<P: EuclideanSpace>: Sized + Copy + One
where
Self: approx::AbsDiffEq<Epsilon = P::Scalar>,
Self: approx::RelativeEq<Epsilon = P::Scalar>,
Self: approx::UlpsEq<Epsilon = P::Scalar>,
P::Scalar: BaseFloat,
Self: iter::Product<Self>,
{
fn look_at(dir: P::Diff, up: P::Diff) -> Self;
fn between_vectors(a: P::Diff, b: P::Diff) -> Self;
fn rotate_vector(&self, vec: P::Diff) -> P::Diff;
#[inline]
fn rotate_point(&self, point: P) -> P {
P::from_vec(self.rotate_vector(point.to_vec()))
}
fn invert(&self) -> Self;
}
pub trait Rotation2<S: BaseFloat>
: Rotation<Point2<S>> + Into<Matrix2<S>> + Into<Basis2<S>> {
fn from_angle<A: Into<Rad<S>>>(theta: A) -> Self;
}
pub trait Rotation3<S: BaseFloat>
: Rotation<Point3<S>> + Into<Matrix3<S>> + Into<Basis3<S>> + Into<Quaternion<S>> + From<Euler<Rad<S>>>
{
fn from_axis_angle<A: Into<Rad<S>>>(axis: Vector3<S>, angle: A) -> Self;
#[inline]
fn from_angle_x<A: Into<Rad<S>>>(theta: A) -> Self {
Rotation3::from_axis_angle(Vector3::unit_x(), theta)
}
#[inline]
fn from_angle_y<A: Into<Rad<S>>>(theta: A) -> Self {
Rotation3::from_axis_angle(Vector3::unit_y(), theta)
}
#[inline]
fn from_angle_z<A: Into<Rad<S>>>(theta: A) -> Self {
Rotation3::from_axis_angle(Vector3::unit_z(), theta)
}
}
#[derive(PartialEq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Basis2<S> {
mat: Matrix2<S>,
}
impl<S: BaseFloat> AsRef<Matrix2<S>> for Basis2<S> {
#[inline]
fn as_ref(&self) -> &Matrix2<S> {
&self.mat
}
}
impl<S: BaseFloat> From<Basis2<S>> for Matrix2<S> {
#[inline]
fn from(b: Basis2<S>) -> Matrix2<S> {
b.mat
}
}
impl<S: BaseFloat> iter::Product<Basis2<S>> for Basis2<S> {
#[inline]
fn product<I: Iterator<Item = Basis2<S>>>(iter: I) -> Basis2<S> {
iter.fold(Basis2::one(), Mul::mul)
}
}
impl<'a, S: 'a + BaseFloat> iter::Product<&'a Basis2<S>> for Basis2<S> {
#[inline]
fn product<I: Iterator<Item = &'a Basis2<S>>>(iter: I) -> Basis2<S> {
iter.fold(Basis2::one(), Mul::mul)
}
}
impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
#[inline]
fn look_at(dir: Vector2<S>, up: Vector2<S>) -> Basis2<S> {
Basis2 {
mat: Matrix2::look_at(dir, up),
}
}
#[inline]
fn between_vectors(a: Vector2<S>, b: Vector2<S>) -> Basis2<S> {
Rotation2::from_angle(Rad::acos(a.dot(b)))
}
#[inline]
fn rotate_vector(&self, vec: Vector2<S>) -> Vector2<S> {
self.mat * vec
}
#[inline]
fn invert(&self) -> Basis2<S> {
Basis2 {
mat: self.mat.invert().unwrap(),
}
}
}
impl<S: BaseFloat> One for Basis2<S> {
#[inline]
fn one() -> Basis2<S> {
Basis2 {
mat: Matrix2::one(),
}
}
}
impl_operator!(<S: BaseFloat> Mul<Basis2<S> > for Basis2<S> {
fn mul(lhs, rhs) -> Basis2<S> { Basis2 { mat: lhs.mat * rhs.mat } }
});
impl<S: BaseFloat> approx::AbsDiffEq for Basis2<S> {
type Epsilon = S::Epsilon;
#[inline]
fn default_epsilon() -> S::Epsilon {
S::default_epsilon()
}
#[inline]
fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool {
Matrix2::abs_diff_eq(&self.mat, &other.mat, epsilon)
}
}
impl<S: BaseFloat> approx::RelativeEq for Basis2<S> {
#[inline]
fn default_max_relative() -> S::Epsilon {
S::default_max_relative()
}
#[inline]
fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool {
Matrix2::relative_eq(&self.mat, &other.mat, epsilon, max_relative)
}
}
impl<S: BaseFloat> approx::UlpsEq for Basis2<S> {
#[inline]
fn default_max_ulps() -> u32 {
S::default_max_ulps()
}
#[inline]
fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool {
Matrix2::ulps_eq(&self.mat, &other.mat, epsilon, max_ulps)
}
}
impl<S: BaseFloat> Rotation2<S> for Basis2<S> {
fn from_angle<A: Into<Rad<S>>>(theta: A) -> Basis2<S> {
Basis2 {
mat: Matrix2::from_angle(theta),
}
}
}
impl<S: fmt::Debug> fmt::Debug for Basis2<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "Basis2 "));
<[[S; 2]; 2] as fmt::Debug>::fmt(self.mat.as_ref(), f)
}
}
#[derive(PartialEq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Basis3<S> {
mat: Matrix3<S>,
}
impl<S: BaseFloat> Basis3<S> {
#[inline]
pub fn from_quaternion(quaternion: &Quaternion<S>) -> Basis3<S> {
Basis3 {
mat: quaternion.clone().into(),
}
}
}
impl<S> AsRef<Matrix3<S>> for Basis3<S> {
#[inline]
fn as_ref(&self) -> &Matrix3<S> {
&self.mat
}
}
impl<S: BaseFloat> From<Basis3<S>> for Matrix3<S> {
#[inline]
fn from(b: Basis3<S>) -> Matrix3<S> {
b.mat
}
}
impl<S: BaseFloat> From<Basis3<S>> for Quaternion<S> {
#[inline]
fn from(b: Basis3<S>) -> Quaternion<S> {
b.mat.into()
}
}
impl<S: BaseFloat> iter::Product<Basis3<S>> for Basis3<S> {
#[inline]
fn product<I: Iterator<Item = Basis3<S>>>(iter: I) -> Basis3<S> {
iter.fold(Basis3::one(), Mul::mul)
}
}
impl<'a, S: 'a + BaseFloat> iter::Product<&'a Basis3<S>> for Basis3<S> {
#[inline]
fn product<I: Iterator<Item = &'a Basis3<S>>>(iter: I) -> Basis3<S> {
iter.fold(Basis3::one(), Mul::mul)
}
}
impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
#[inline]
fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Basis3<S> {
Basis3 {
mat: Matrix3::look_at(dir, up),
}
}
#[inline]
fn between_vectors(a: Vector3<S>, b: Vector3<S>) -> Basis3<S> {
let q: Quaternion<S> = Rotation::between_vectors(a, b);
q.into()
}
#[inline]
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> {
self.mat * vec
}
#[inline]
fn invert(&self) -> Basis3<S> {
Basis3 {
mat: self.mat.invert().unwrap(),
}
}
}
impl<S: BaseFloat> One for Basis3<S> {
#[inline]
fn one() -> Basis3<S> {
Basis3 {
mat: Matrix3::one(),
}
}
}
impl_operator!(<S: BaseFloat> Mul<Basis3<S> > for Basis3<S> {
fn mul(lhs, rhs) -> Basis3<S> { Basis3 { mat: lhs.mat * rhs.mat } }
});
impl<S: BaseFloat> approx::AbsDiffEq for Basis3<S> {
type Epsilon = S::Epsilon;
#[inline]
fn default_epsilon() -> S::Epsilon {
S::default_epsilon()
}
#[inline]
fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool {
Matrix3::abs_diff_eq(&self.mat, &other.mat, epsilon)
}
}
impl<S: BaseFloat> approx::RelativeEq for Basis3<S> {
#[inline]
fn default_max_relative() -> S::Epsilon {
S::default_max_relative()
}
#[inline]
fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool {
Matrix3::relative_eq(&self.mat, &other.mat, epsilon, max_relative)
}
}
impl<S: BaseFloat> approx::UlpsEq for Basis3<S> {
#[inline]
fn default_max_ulps() -> u32 {
S::default_max_ulps()
}
#[inline]
fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool {
Matrix3::ulps_eq(&self.mat, &other.mat, epsilon, max_ulps)
}
}
impl<S: BaseFloat> Rotation3<S> for Basis3<S> {
fn from_axis_angle<A: Into<Rad<S>>>(axis: Vector3<S>, angle: A) -> Basis3<S> {
Basis3 {
mat: Matrix3::from_axis_angle(axis, angle),
}
}
fn from_angle_x<A: Into<Rad<S>>>(theta: A) -> Basis3<S> {
Basis3 {
mat: Matrix3::from_angle_x(theta),
}
}
fn from_angle_y<A: Into<Rad<S>>>(theta: A) -> Basis3<S> {
Basis3 {
mat: Matrix3::from_angle_y(theta),
}
}
fn from_angle_z<A: Into<Rad<S>>>(theta: A) -> Basis3<S> {
Basis3 {
mat: Matrix3::from_angle_z(theta),
}
}
}
impl<A: Angle> From<Euler<A>> for Basis3<A::Unitless>
where
A: Into<Rad<<A as Angle>::Unitless>>,
{
fn from(src: Euler<A>) -> Basis3<A::Unitless> {
Basis3 {
mat: Matrix3::from(src),
}
}
}
impl<S: fmt::Debug> fmt::Debug for Basis3<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "Basis3 "));
<[[S; 3]; 3] as fmt::Debug>::fmt(self.mat.as_ref(), f)
}
}