//! Isometric transformations. #![allow(missing_docs)] use std::ops::{Add, Sub, Mul, Neg}; use rand::{Rand, Rng}; use num::One; use structs::mat::{Mat3, Mat4, Mat5}; use traits::structure::{Cast, Dim, Col, BaseFloat, BaseNum}; use traits::operations::{Inv, ApproxEq}; use traits::geometry::{RotationMatrix, Rotation, Rotate, AbsoluteRotate, Transform, Transformation, Translate, Translation, ToHomogeneous}; use structs::vec::{Vec1, Vec2, Vec3, Vec4}; use structs::pnt::{Pnt2, Pnt3, Pnt4}; use structs::rot::{Rot2, Rot3, Rot4}; #[cfg(feature="arbitrary")] use quickcheck::{Arbitrary, Gen}; /// Two dimensional isometry. /// /// This is the composition of a rotation followed by a translation. /// Isometries conserve angles and distances, hence do not allow shearing nor scaling. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)] pub struct Iso2 { /// The rotation applicable by this isometry. pub rotation: Rot2, /// The translation applicable by this isometry. pub translation: Vec2 } /// Three dimensional isometry. /// /// This is the composition of a rotation followed by a translation. /// Isometries conserve angles and distances, hence do not allow shearing nor scaling. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)] pub struct Iso3 { /// The rotation applicable by this isometry. pub rotation: Rot3, /// The translation applicable by this isometry. pub translation: Vec3 } /// Four dimensional isometry. /// /// Isometries conserve angles and distances, hence do not allow shearing nor scaling. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)] pub struct Iso4 { /// The rotation applicable by this isometry. pub rotation: Rot4, /// The translation applicable by this isometry. pub translation: Vec4 } impl Iso3 { /// Reorient and translate this transformation such that its local `x` axis points to a given /// direction. Note that the usually known `look_at` function does the same thing but with the /// `z` axis. See `look_at_z` for that. /// /// # Arguments /// * eye - The new translation of the transformation. /// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be /// aligned with. /// * up - Vector pointing up. The only requirement of this parameter is to not be colinear /// with `at`. Non-colinearity is not checked. pub fn look_at(&mut self, eye: &Pnt3, at: &Pnt3, up: &Vec3) { self.rotation.look_at(&(*at - *eye), up); self.translation = eye.as_vec().clone(); } /// Reorient and translate this transformation such that its local `z` axis points to a given /// direction. /// /// # Arguments /// * eye - The new translation of the transformation. /// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be /// aligned with /// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear /// with `at`. Non-colinearity is not checked. pub fn look_at_z(&mut self, eye: &Pnt3, at: &Pnt3, up: &Vec3) { self.rotation.look_at_z(&(*at - *eye), up); self.translation = eye.as_vec().clone(); } } impl Iso4 { // XXX remove that when iso_impl works for Iso4 /// Creates a new isometry from a rotation matrix and a vector. #[inline] pub fn new_with_rotmat(translation: Vec4, rotation: Rot4) -> Iso4 { Iso4 { rotation: rotation, translation: translation } } } iso_impl!(Iso2, Rot2, Vec2, Vec1); rotation_matrix_impl!(Iso2, Rot2, Vec2, Vec1); rotation_impl!(Iso2, Rot2, Vec1); dim_impl!(Iso2, 2); one_impl!(Iso2); absolute_rotate_impl!(Iso2, Vec2); rand_impl!(Iso2); approx_eq_impl!(Iso2); to_homogeneous_impl!(Iso2, Mat3); inv_impl!(Iso2); transform_impl!(Iso2, Pnt2); transformation_impl!(Iso2); rotate_impl!(Iso2, Vec2); translation_impl!(Iso2, Vec2); translate_impl!(Iso2, Pnt2); iso_mul_iso_impl!(Iso2); iso_mul_pnt_impl!(Iso2, Pnt2); pnt_mul_iso_impl!(Iso2, Pnt2); arbitrary_iso_impl!(Iso2); iso_impl!(Iso3, Rot3, Vec3, Vec3); rotation_matrix_impl!(Iso3, Rot3, Vec3, Vec3); rotation_impl!(Iso3, Rot3, Vec3); dim_impl!(Iso3, 3); one_impl!(Iso3); absolute_rotate_impl!(Iso3, Vec3); rand_impl!(Iso3); approx_eq_impl!(Iso3); to_homogeneous_impl!(Iso3, Mat4); inv_impl!(Iso3); transform_impl!(Iso3, Pnt3); transformation_impl!(Iso3); rotate_impl!(Iso3, Vec3); translation_impl!(Iso3, Vec3); translate_impl!(Iso3, Pnt3); iso_mul_iso_impl!(Iso3); iso_mul_pnt_impl!(Iso3, Pnt3); pnt_mul_iso_impl!(Iso3, Pnt3); arbitrary_iso_impl!(Iso3); // iso_impl!(Iso4, Rot4, Vec4, Vec4); // rotation_matrix_impl!(Iso4, Rot4, Vec4, Vec4); // rotation_impl!(Iso4, Rot4, Vec4); dim_impl!(Iso4, 4); one_impl!(Iso4); absolute_rotate_impl!(Iso4, Vec4); // rand_impl!(Iso4); approx_eq_impl!(Iso4); to_homogeneous_impl!(Iso4, Mat5); inv_impl!(Iso4); transform_impl!(Iso4, Pnt4); transformation_impl!(Iso4); rotate_impl!(Iso4, Vec4); translation_impl!(Iso4, Vec4); translate_impl!(Iso4, Pnt4); iso_mul_iso_impl!(Iso4); iso_mul_pnt_impl!(Iso4, Pnt4); pnt_mul_iso_impl!(Iso4, Pnt4); // FIXME: as soon as Rot4: Arbitrary // arbitrary_iso_impl!(Iso4);