Add similarity transformations Sim2 and Sim3 (uniform scale followed by a rotation followed by a translation).
This commit is contained in:
parent
f8f4924e47
commit
0c8b8bfcdb
12
README.md
12
README.md
@ -44,15 +44,17 @@ fn main() {
|
|||||||
**nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with
|
**nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with
|
||||||
an optimized set of tools for computer graphics and physics. Those features include:
|
an optimized set of tools for computer graphics and physics. Those features include:
|
||||||
|
|
||||||
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
|
* Vectors with predefined static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
|
||||||
|
* Vector with a user-defined static size: `VecN`.
|
||||||
* Points with static sizes: `Pnt0`, `Pnt1`, `Pnt2`, `Pnt3`, `Pnt4`, `Pnt5`, `Pnt6`.
|
* Points with static sizes: `Pnt0`, `Pnt1`, `Pnt2`, `Pnt3`, `Pnt4`, `Pnt5`, `Pnt6`.
|
||||||
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
|
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
|
||||||
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
|
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
|
||||||
* Quaternions: `Quat`, `UnitQuat`.
|
* Quaternions: `Quat`, `UnitQuat`.
|
||||||
* Isometries: `Iso2`, `Iso3`, `Iso4`.
|
* Isometries (translation * rotation): `Iso2`, `Iso3`, `Iso4`.
|
||||||
|
* Similarities (translation * rotation * uniform scale): `Sim2`, `Sim3`.
|
||||||
* 3D projections for computer graphics: `Persp3`, `PerspMat3`, `Ortho3`, `OrthoMat3`.
|
* 3D projections for computer graphics: `Persp3`, `PerspMat3`, `Ortho3`, `OrthoMat3`.
|
||||||
* Dynamically sized vector: `DVec`.
|
* Dynamically sized heap-allocated vector: `DVec`.
|
||||||
* Dynamically sized (square or rectangular) matrix: `DMat`.
|
* Dynamically sized stack-allocated vectors with a maximum size: `DVec1` to `DVec6`.
|
||||||
|
* Dynamically sized heap-allocated (square or rectangular) matrix: `DMat`.
|
||||||
* A few methods for data analysis: `Cov`, `Mean`.
|
* A few methods for data analysis: `Cov`, `Mean`.
|
||||||
* Almost one trait per functionality: useful for generic programming.
|
* Almost one trait per functionality: useful for generic programming.
|
||||||
* Operator overloading using multidispatch.
|
|
||||||
|
13
src/lib.rs
13
src/lib.rs
@ -41,18 +41,20 @@ fn main() {
|
|||||||
**nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with
|
**nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with
|
||||||
an optimized set of tools for computer graphics and physics. Those features include:
|
an optimized set of tools for computer graphics and physics. Those features include:
|
||||||
|
|
||||||
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
|
* Vectors with predefined static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
|
||||||
|
* Vector with a user-defined static size: `VecN`.
|
||||||
* Points with static sizes: `Pnt0`, `Pnt1`, `Pnt2`, `Pnt3`, `Pnt4`, `Pnt5`, `Pnt6`.
|
* Points with static sizes: `Pnt0`, `Pnt1`, `Pnt2`, `Pnt3`, `Pnt4`, `Pnt5`, `Pnt6`.
|
||||||
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
|
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
|
||||||
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
|
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
|
||||||
* Quaternions: `Quat`, `UnitQuat`.
|
* Quaternions: `Quat`, `UnitQuat`.
|
||||||
* Isometries: `Iso2`, `Iso3`, `Iso4`.
|
* Isometries (translation * rotation): `Iso2`, `Iso3`, `Iso4`.
|
||||||
|
* Similarity transformations (translation * rotation * uniform scale): `Sim2`, `Sim3`.
|
||||||
* 3D projections for computer graphics: `Persp3`, `PerspMat3`, `Ortho3`, `OrthoMat3`.
|
* 3D projections for computer graphics: `Persp3`, `PerspMat3`, `Ortho3`, `OrthoMat3`.
|
||||||
* Dynamically sized vector: `DVec`.
|
* Dynamically sized heap-allocated vector: `DVec`.
|
||||||
* Dynamically sized (square or rectangular) matrix: `DMat`.
|
* Dynamically sized stack-allocated vectors with a maximum size: `DVec1` to `DVec6`.
|
||||||
|
* Dynamically sized heap-allocated (square or rectangular) matrix: `DMat`.
|
||||||
* A few methods for data analysis: `Cov`, `Mean`.
|
* A few methods for data analysis: `Cov`, `Mean`.
|
||||||
* Almost one trait per functionality: useful for generic programming.
|
* Almost one trait per functionality: useful for generic programming.
|
||||||
* Operator overloading using multidispatch.
|
|
||||||
|
|
||||||
|
|
||||||
## **nalgebra** in use
|
## **nalgebra** in use
|
||||||
@ -139,6 +141,7 @@ pub use structs::{
|
|||||||
DMat, DMat1, DMat2, DMat3, DMat4, DMat5, DMat6,
|
DMat, DMat1, DMat2, DMat3, DMat4, DMat5, DMat6,
|
||||||
DVec, DVec1, DVec2, DVec3, DVec4, DVec5, DVec6,
|
DVec, DVec1, DVec2, DVec3, DVec4, DVec5, DVec6,
|
||||||
Iso2, Iso3, Iso4,
|
Iso2, Iso3, Iso4,
|
||||||
|
Sim2, Sim3,
|
||||||
Mat1, Mat2, Mat3, Mat4,
|
Mat1, Mat2, Mat3, Mat4,
|
||||||
Mat5, Mat6,
|
Mat5, Mat6,
|
||||||
Rot2, Rot3, Rot4,
|
Rot2, Rot3, Rot4,
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
//! Isometric transformations.
|
|
||||||
|
|
||||||
#![allow(missing_docs)]
|
|
||||||
|
|
||||||
use std::ops::{Add, Sub, Mul, Neg};
|
use std::ops::{Add, Sub, Mul, Neg};
|
||||||
|
|
||||||
use rand::{Rand, Rng};
|
use rand::{Rand, Rng};
|
||||||
@ -22,7 +18,8 @@ use quickcheck::{Arbitrary, Gen};
|
|||||||
|
|
||||||
/// Two dimensional isometry.
|
/// Two dimensional isometry.
|
||||||
///
|
///
|
||||||
/// This is the composition of a rotation followed by a translation.
|
/// This is the composition of a rotation followed by a translation. Vectors `Vec2` are not
|
||||||
|
/// affected by the translational component of this transformation while points `Pnt2` are.
|
||||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||||
@ -35,7 +32,8 @@ pub struct Iso2<N> {
|
|||||||
|
|
||||||
/// Three dimensional isometry.
|
/// Three dimensional isometry.
|
||||||
///
|
///
|
||||||
/// This is the composition of a rotation followed by a translation.
|
/// This is the composition of a rotation followed by a translation. Vectors `Vec3` are not
|
||||||
|
/// affected by the translational component of this transformation while points `Pnt3` are.
|
||||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||||
@ -48,6 +46,8 @@ pub struct Iso3<N> {
|
|||||||
|
|
||||||
/// Four dimensional isometry.
|
/// Four dimensional isometry.
|
||||||
///
|
///
|
||||||
|
/// This is the composition of a rotation followed by a translation. Vectors `Vec4` are not
|
||||||
|
/// affected by the translational component of this transformation while points `Pnt4` are.
|
||||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||||
@ -117,6 +117,8 @@ translate_impl!(Iso2, Pnt2);
|
|||||||
iso_mul_iso_impl!(Iso2);
|
iso_mul_iso_impl!(Iso2);
|
||||||
iso_mul_pnt_impl!(Iso2, Pnt2);
|
iso_mul_pnt_impl!(Iso2, Pnt2);
|
||||||
pnt_mul_iso_impl!(Iso2, Pnt2);
|
pnt_mul_iso_impl!(Iso2, Pnt2);
|
||||||
|
iso_mul_vec_impl!(Iso2, Vec2);
|
||||||
|
vec_mul_iso_impl!(Iso2, Vec2);
|
||||||
arbitrary_iso_impl!(Iso2);
|
arbitrary_iso_impl!(Iso2);
|
||||||
|
|
||||||
iso_impl!(Iso3, Rot3, Vec3, Vec3);
|
iso_impl!(Iso3, Rot3, Vec3, Vec3);
|
||||||
@ -137,6 +139,8 @@ translate_impl!(Iso3, Pnt3);
|
|||||||
iso_mul_iso_impl!(Iso3);
|
iso_mul_iso_impl!(Iso3);
|
||||||
iso_mul_pnt_impl!(Iso3, Pnt3);
|
iso_mul_pnt_impl!(Iso3, Pnt3);
|
||||||
pnt_mul_iso_impl!(Iso3, Pnt3);
|
pnt_mul_iso_impl!(Iso3, Pnt3);
|
||||||
|
iso_mul_vec_impl!(Iso3, Vec3);
|
||||||
|
vec_mul_iso_impl!(Iso3, Vec3);
|
||||||
arbitrary_iso_impl!(Iso3);
|
arbitrary_iso_impl!(Iso3);
|
||||||
|
|
||||||
// iso_impl!(Iso4, Rot4, Vec4, Vec4);
|
// iso_impl!(Iso4, Rot4, Vec4, Vec4);
|
||||||
@ -157,5 +161,7 @@ translate_impl!(Iso4, Pnt4);
|
|||||||
iso_mul_iso_impl!(Iso4);
|
iso_mul_iso_impl!(Iso4);
|
||||||
iso_mul_pnt_impl!(Iso4, Pnt4);
|
iso_mul_pnt_impl!(Iso4, Pnt4);
|
||||||
pnt_mul_iso_impl!(Iso4, Pnt4);
|
pnt_mul_iso_impl!(Iso4, Pnt4);
|
||||||
|
iso_mul_vec_impl!(Iso4, Vec4);
|
||||||
|
vec_mul_iso_impl!(Iso4, Vec4);
|
||||||
// FIXME: as soon as Rot4<N>: Arbitrary
|
// FIXME: as soon as Rot4<N>: Arbitrary
|
||||||
// arbitrary_iso_impl!(Iso4);
|
// arbitrary_iso_impl!(Iso4);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
macro_rules! iso_impl(
|
macro_rules! iso_impl(
|
||||||
($t: ident, $submat: ident, $subvec: ident, $subrotvec: ident) => (
|
($t: ident, $submat: ident, $subvec: ident, $subrotvec: ident) => (
|
||||||
impl<N: BaseFloat> $t<N> {
|
impl<N: BaseFloat> $t<N> {
|
||||||
/// Creates a new isometry from a rotation matrix and a vector.
|
/// Creates a new isometry from an axis-angle rotation, and a vector.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>) -> $t<N> {
|
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>) -> $t<N> {
|
||||||
$t {
|
$t {
|
||||||
@ -89,6 +89,19 @@ macro_rules! iso_mul_pnt_impl(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
macro_rules! iso_mul_vec_impl(
|
||||||
|
($t: ident, $tv: ident) => (
|
||||||
|
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||||
|
type Output = $tv<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, right: $tv<N>) -> $tv<N> {
|
||||||
|
self.rotation * right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
macro_rules! pnt_mul_iso_impl(
|
macro_rules! pnt_mul_iso_impl(
|
||||||
($t: ident, $tv: ident) => (
|
($t: ident, $tv: ident) => (
|
||||||
impl<N: BaseNum> Mul<$t<N>> for $tv<N> {
|
impl<N: BaseNum> Mul<$t<N>> for $tv<N> {
|
||||||
@ -101,6 +114,18 @@ macro_rules! pnt_mul_iso_impl(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
macro_rules! vec_mul_iso_impl(
|
||||||
|
($t: ident, $tv: ident) => (
|
||||||
|
impl<N: BaseNum> Mul<$t<N>> for $tv<N> {
|
||||||
|
type Output = $tv<N>;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, right: $t<N>) -> $tv<N> {
|
||||||
|
self * right.rotation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
macro_rules! translation_impl(
|
macro_rules! translation_impl(
|
||||||
($t: ident, $tv: ident) => (
|
($t: ident, $tv: ident) => (
|
||||||
impl<N: BaseFloat> Translation<$tv<N>> for $t<N> {
|
impl<N: BaseFloat> Translation<$tv<N>> for $t<N> {
|
||||||
|
@ -8,6 +8,7 @@ pub use self::pnt::{Pnt0, Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6};
|
|||||||
pub use self::mat::{Identity, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
|
pub use self::mat::{Identity, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
|
||||||
pub use self::rot::{Rot2, Rot3, Rot4};
|
pub use self::rot::{Rot2, Rot3, Rot4};
|
||||||
pub use self::iso::{Iso2, Iso3, Iso4};
|
pub use self::iso::{Iso2, Iso3, Iso4};
|
||||||
|
pub use self::sim::{Sim2, Sim3};
|
||||||
pub use self::persp::{Persp3, PerspMat3};
|
pub use self::persp::{Persp3, PerspMat3};
|
||||||
pub use self::ortho::{Ortho3, OrthoMat3};
|
pub use self::ortho::{Ortho3, OrthoMat3};
|
||||||
pub use self::quat::{Quat, UnitQuat};
|
pub use self::quat::{Quat, UnitQuat};
|
||||||
@ -29,6 +30,8 @@ mod rot_macros;
|
|||||||
mod rot;
|
mod rot;
|
||||||
mod iso_macros;
|
mod iso_macros;
|
||||||
mod iso;
|
mod iso;
|
||||||
|
mod sim_macros;
|
||||||
|
mod sim;
|
||||||
mod persp;
|
mod persp;
|
||||||
mod ortho;
|
mod ortho;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//! Points with dimensions known at compile-time.
|
//! Points with dimension known at compile-time.
|
||||||
|
|
||||||
#![allow(missing_docs)] // we allow missing to avoid having to document the point components.
|
#![allow(missing_docs)] // we allow missing to avoid having to document the point components.
|
||||||
|
|
||||||
@ -19,6 +19,9 @@ use quickcheck::{Arbitrary, Gen};
|
|||||||
|
|
||||||
|
|
||||||
/// Point of dimension 0.
|
/// Point of dimension 0.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
||||||
pub struct Pnt0<N>(pub PhantomData<N>);
|
pub struct Pnt0<N>(pub PhantomData<N>);
|
||||||
@ -39,6 +42,9 @@ impl<N> Repeat<N> for Pnt0<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Point of dimension 1.
|
/// Point of dimension 1.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Pnt1<N> {
|
pub struct Pnt1<N> {
|
||||||
@ -79,6 +85,9 @@ arbitrary_pnt_impl!(Pnt1, x);
|
|||||||
rand_impl!(Pnt1, x);
|
rand_impl!(Pnt1, x);
|
||||||
|
|
||||||
/// Point of dimension 2.
|
/// Point of dimension 2.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Pnt2<N> {
|
pub struct Pnt2<N> {
|
||||||
@ -121,6 +130,9 @@ arbitrary_pnt_impl!(Pnt2, x, y);
|
|||||||
rand_impl!(Pnt2, x, y);
|
rand_impl!(Pnt2, x, y);
|
||||||
|
|
||||||
/// Point of dimension 3.
|
/// Point of dimension 3.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Pnt3<N> {
|
pub struct Pnt3<N> {
|
||||||
@ -165,6 +177,9 @@ arbitrary_pnt_impl!(Pnt3, x, y, z);
|
|||||||
rand_impl!(Pnt3, x, y, z);
|
rand_impl!(Pnt3, x, y, z);
|
||||||
|
|
||||||
/// Point of dimension 4.
|
/// Point of dimension 4.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Pnt4<N> {
|
pub struct Pnt4<N> {
|
||||||
@ -211,6 +226,9 @@ arbitrary_pnt_impl!(Pnt4, x, y, z, w);
|
|||||||
rand_impl!(Pnt4, x, y, z, w);
|
rand_impl!(Pnt4, x, y, z, w);
|
||||||
|
|
||||||
/// Point of dimension 5.
|
/// Point of dimension 5.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Pnt5<N> {
|
pub struct Pnt5<N> {
|
||||||
@ -259,6 +277,9 @@ arbitrary_pnt_impl!(Pnt5, x, y, z, w, a);
|
|||||||
rand_impl!(Pnt5, x, y, z, w, a);
|
rand_impl!(Pnt5, x, y, z, w, a);
|
||||||
|
|
||||||
/// Point of dimension 6.
|
/// Point of dimension 6.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Pnt6<N> {
|
pub struct Pnt6<N> {
|
||||||
|
80
src/structs/sim.rs
Normal file
80
src/structs/sim.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
use std::ops::{Mul, Neg};
|
||||||
|
|
||||||
|
use rand::{Rand, Rng};
|
||||||
|
use num::One;
|
||||||
|
use structs::mat::{Mat3, Mat4};
|
||||||
|
use traits::structure::{Dim, Col, BaseFloat, BaseNum};
|
||||||
|
use traits::operations::{Inv, ApproxEq};
|
||||||
|
use traits::geometry::{Rotation, Transform, Transformation, Translation, ToHomogeneous};
|
||||||
|
|
||||||
|
use structs::vec::{Vec1, Vec2, Vec3};
|
||||||
|
use structs::pnt::{Pnt2, Pnt3};
|
||||||
|
use structs::rot::{Rot2, Rot3};
|
||||||
|
use structs::iso::{Iso2, Iso3};
|
||||||
|
|
||||||
|
// FIXME: the name is not explicit at all but coherent with the other tree-letters names…
|
||||||
|
/// A two-dimensional similarity transformation.
|
||||||
|
///
|
||||||
|
/// This is a composition of a uniform scale, followed by a rotation, followed by a translation.
|
||||||
|
/// Vectors `Vec2` are not affected by the translational component of this transformation while
|
||||||
|
/// points `Pnt2` are.
|
||||||
|
/// Similarity transformations conserve angles. Distances are multiplied by some constant (the
|
||||||
|
/// scale factor). The scale factor cannot be zero.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||||
|
pub struct Sim2<N> {
|
||||||
|
/// The uniform scale applicable by this similarity transformation.
|
||||||
|
scale: N,
|
||||||
|
/// The isometry applicable by this similarity transformation.
|
||||||
|
pub isometry: Iso2<N>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A three-dimensional similarity transformation.
|
||||||
|
///
|
||||||
|
/// This is a composition of a scale, followed by a rotation, followed by a translation.
|
||||||
|
/// Vectors `Vec3` are not affected by the translational component of this transformation while
|
||||||
|
/// points `Pnt3` are.
|
||||||
|
/// Similarity transformations conserve angles. Distances are multiplied by some constant (the
|
||||||
|
/// scale factor). The scale factor cannot be zero.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||||
|
pub struct Sim3<N> {
|
||||||
|
/// The uniform scale applicable by this similarity transformation.
|
||||||
|
scale: N,
|
||||||
|
/// The isometry applicable by this similarity transformation.
|
||||||
|
pub isometry: Iso3<N>
|
||||||
|
}
|
||||||
|
|
||||||
|
sim_impl!(Sim2, Iso2, Rot2, Vec2, Vec1);
|
||||||
|
dim_impl!(Sim2, 2);
|
||||||
|
sim_scale_impl!(Sim2);
|
||||||
|
sim_one_impl!(Sim2);
|
||||||
|
sim_mul_sim_impl!(Sim2);
|
||||||
|
sim_mul_pnt_vec_impl!(Sim2, Pnt2);
|
||||||
|
pnt_vec_mul_sim_impl!(Sim2, Pnt2);
|
||||||
|
sim_mul_pnt_vec_impl!(Sim2, Vec2);
|
||||||
|
pnt_vec_mul_sim_impl!(Sim2, Vec2);
|
||||||
|
transformation_impl!(Sim2);
|
||||||
|
sim_transform_impl!(Sim2, Pnt2);
|
||||||
|
sim_inv_impl!(Sim2);
|
||||||
|
sim_to_homogeneous_impl!(Sim2, Mat3);
|
||||||
|
sim_approx_eq_impl!(Sim2);
|
||||||
|
sim_rand_impl!(Sim2);
|
||||||
|
sim_arbitrary_impl!(Sim2);
|
||||||
|
|
||||||
|
sim_impl!(Sim3, Iso3, Rot3, Vec3, Vec3);
|
||||||
|
dim_impl!(Sim3, 3);
|
||||||
|
sim_scale_impl!(Sim3);
|
||||||
|
sim_one_impl!(Sim3);
|
||||||
|
sim_mul_sim_impl!(Sim3);
|
||||||
|
sim_mul_pnt_vec_impl!(Sim3, Pnt3);
|
||||||
|
pnt_vec_mul_sim_impl!(Sim3, Pnt3);
|
||||||
|
sim_mul_pnt_vec_impl!(Sim3, Vec3);
|
||||||
|
pnt_vec_mul_sim_impl!(Sim3, Vec3);
|
||||||
|
transformation_impl!(Sim3);
|
||||||
|
sim_transform_impl!(Sim3, Pnt3);
|
||||||
|
sim_inv_impl!(Sim3);
|
||||||
|
sim_to_homogeneous_impl!(Sim3, Mat4);
|
||||||
|
sim_approx_eq_impl!(Sim3);
|
||||||
|
sim_rand_impl!(Sim3);
|
||||||
|
sim_arbitrary_impl!(Sim3);
|
264
src/structs/sim_macros.rs
Normal file
264
src/structs/sim_macros.rs
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
#![macro_use]
|
||||||
|
|
||||||
|
macro_rules! sim_impl(
|
||||||
|
($t: ident, $iso: ident, $rotmat: ident, $subvec: ident, $subrotvec: ident) => (
|
||||||
|
impl<N: BaseFloat> $t<N> {
|
||||||
|
/// Creates a new similarity transformation from a vector, an axis-angle rotation, and a scale factor.
|
||||||
|
///
|
||||||
|
/// The scale factor may be negative but not zero.
|
||||||
|
#[inline]
|
||||||
|
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>, scale: N) -> $t<N> {
|
||||||
|
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||||
|
|
||||||
|
$t {
|
||||||
|
scale: scale,
|
||||||
|
isometry: $iso::new(translation, rotation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new similarity transformation from a rotation matrix, a vector, and a scale factor.
|
||||||
|
///
|
||||||
|
/// The scale factor may be negative but not zero.
|
||||||
|
#[inline]
|
||||||
|
pub fn new_with_rotmat(translation: $subvec<N>, rotation: $rotmat<N>, scale: N) -> $t<N> {
|
||||||
|
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||||
|
|
||||||
|
$t {
|
||||||
|
scale: scale,
|
||||||
|
isometry: $iso::new_with_rotmat(translation, rotation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new similarity transformation from an isometry and a scale factor.
|
||||||
|
///
|
||||||
|
/// The scale factor may be negative but not zero.
|
||||||
|
#[inline]
|
||||||
|
pub fn new_with_iso(isometry: $iso<N>, scale: N) -> $t<N> {
|
||||||
|
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||||
|
|
||||||
|
$t {
|
||||||
|
scale: scale,
|
||||||
|
isometry: isometry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_scale_impl(
|
||||||
|
($t: ident) => (
|
||||||
|
impl<N: BaseFloat> $t<N> {
|
||||||
|
/// The scale factor of this similarity transformation.
|
||||||
|
#[inline]
|
||||||
|
pub fn scale(&self) -> N {
|
||||||
|
self.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The inverse scale factor of this similarity transformation.
|
||||||
|
#[inline]
|
||||||
|
pub fn inv_scale(&self) -> N {
|
||||||
|
::one::<N>() / self.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Appends in-place a scale to this similarity transformation.
|
||||||
|
#[inline]
|
||||||
|
pub fn append_scale_mut(&mut self, s: &N) {
|
||||||
|
assert!(!s.is_zero(), "Cannot append a zero scale to a similarity transformation.");
|
||||||
|
self.scale = *s * self.scale;
|
||||||
|
self.isometry.translation = self.isometry.translation * *s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Appends a scale to this similarity transformation.
|
||||||
|
#[inline]
|
||||||
|
pub fn append_scale(&self, s: &N) -> $t<N> {
|
||||||
|
assert!(!s.is_zero(), "Cannot append a zero scale to a similarity transformation.");
|
||||||
|
$t::new_with_rotmat(self.isometry.translation * *s, self.isometry.rotation, self.scale * *s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prepends in-place a scale to this similarity transformation.
|
||||||
|
#[inline]
|
||||||
|
pub fn prepend_scale_mut(&mut self, s: &N) {
|
||||||
|
assert!(!s.is_zero(), "Cannot prepend a zero scale to a similarity transformation.");
|
||||||
|
self.scale = self.scale * *s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prepends a scale to this similarity transformation.
|
||||||
|
#[inline]
|
||||||
|
pub fn prepend_scale(&self, s: &N) -> $t<N> {
|
||||||
|
assert!(!s.is_zero(), "A similarity transformation scale must not be zero.");
|
||||||
|
$t::new_with_iso(self.isometry, self.scale * *s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the scale of this similarity transformation.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_scale(&mut self, s: N) {
|
||||||
|
assert!(!s.is_zero(), "A similarity transformation scale must not be zero.");
|
||||||
|
self.scale = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_one_impl(
|
||||||
|
($t: ident) => (
|
||||||
|
impl<N: BaseFloat> One for $t<N> {
|
||||||
|
#[inline]
|
||||||
|
fn one() -> $t<N> {
|
||||||
|
$t::new_with_iso(::one(), ::one())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_mul_sim_impl(
|
||||||
|
($t: ident) => (
|
||||||
|
impl<N: BaseFloat> Mul<$t<N>> for $t<N> {
|
||||||
|
type Output = $t<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, right: $t<N>) -> $t<N> {
|
||||||
|
$t::new_with_rotmat(
|
||||||
|
self.isometry.translation + self.isometry.rotation * (right.isometry.translation * right.scale),
|
||||||
|
self.isometry.rotation * right.isometry.rotation,
|
||||||
|
self.scale * right.scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_mul_pnt_vec_impl(
|
||||||
|
($t: ident, $tv: ident) => (
|
||||||
|
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||||
|
type Output = $tv<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, right: $tv<N>) -> $tv<N> {
|
||||||
|
self.isometry * (right * self.scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! pnt_vec_mul_sim_impl(
|
||||||
|
($t: ident, $tv: ident) => (
|
||||||
|
impl<N: BaseNum> Mul<$t<N>> for $tv<N> {
|
||||||
|
type Output = $tv<N>;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, right: $t<N>) -> $tv<N> {
|
||||||
|
self * right.isometry * right.scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_transform_impl(
|
||||||
|
($t: ident, $tp: ident) => (
|
||||||
|
impl<N: BaseNum> Transform<$tp<N>> for $t<N> {
|
||||||
|
#[inline]
|
||||||
|
fn transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||||
|
self.isometry.transform(p) * self.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inv_transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||||
|
self.isometry.inv_transform(p) / self.scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_inv_impl(
|
||||||
|
($t: ident) => (
|
||||||
|
impl<N: BaseNum + Neg<Output = N>> Inv for $t<N> {
|
||||||
|
#[inline]
|
||||||
|
fn inv_mut(&mut self) -> bool {
|
||||||
|
self.scale = ::one::<N>() / self.scale;
|
||||||
|
self.isometry.inv_mut();
|
||||||
|
// We multiply by self.scale because the scale has been inverted on the previous line.
|
||||||
|
self.isometry.translation = self.isometry.translation * self.scale;
|
||||||
|
|
||||||
|
// always succeed
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inv(&self) -> Option<$t<N>> {
|
||||||
|
let mut res = *self;
|
||||||
|
res.inv_mut();
|
||||||
|
|
||||||
|
// always succeed
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_to_homogeneous_impl(
|
||||||
|
($t: ident, $th: ident) => (
|
||||||
|
impl<N: BaseNum> ToHomogeneous<$th<N>> for $t<N> {
|
||||||
|
fn to_homogeneous(&self) -> $th<N> {
|
||||||
|
let mut res = (*self.isometry.rotation.submat() * self.scale).to_homogeneous();
|
||||||
|
|
||||||
|
// copy the translation
|
||||||
|
let dim = Dim::dim(None::<$th<N>>);
|
||||||
|
|
||||||
|
res.set_col(dim - 1, self.isometry.translation.as_pnt().to_homogeneous().to_vec());
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_approx_eq_impl(
|
||||||
|
($t: ident) => (
|
||||||
|
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||||
|
#[inline]
|
||||||
|
fn approx_epsilon(_: Option<$t<N>>) -> N {
|
||||||
|
ApproxEq::approx_epsilon(None::<N>)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn approx_ulps(_: Option<$t<N>>) -> u32 {
|
||||||
|
ApproxEq::approx_ulps(None::<N>)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
|
||||||
|
ApproxEq::approx_eq_eps(&self.scale, &other.scale, epsilon) &&
|
||||||
|
ApproxEq::approx_eq_eps(&self.isometry, &other.isometry, epsilon)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn approx_eq_ulps(&self, other: &$t<N>, ulps: u32) -> bool {
|
||||||
|
ApproxEq::approx_eq_ulps(&self.scale, &other.scale, ulps) &&
|
||||||
|
ApproxEq::approx_eq_ulps(&self.isometry, &other.isometry, ulps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_rand_impl(
|
||||||
|
($t: ident) => (
|
||||||
|
impl<N: Rand + BaseFloat> Rand for $t<N> {
|
||||||
|
#[inline]
|
||||||
|
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
|
||||||
|
$t::new_with_iso(rng.gen(), rng.gen())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! sim_arbitrary_impl(
|
||||||
|
($t: ident) => (
|
||||||
|
#[cfg(feature="arbitrary")]
|
||||||
|
impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> {
|
||||||
|
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
|
||||||
|
$t::new_with_iso(
|
||||||
|
Arbitrary::arbitrary(g),
|
||||||
|
Arbitrary::arbitrary(g)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
@ -1,4 +1,4 @@
|
|||||||
//! Vectors with dimensions known at compile-time.
|
//! Vectors with dimension known at compile-time.
|
||||||
|
|
||||||
#![allow(missing_docs)] // we allow missing to avoid having to document the dispatch traits.
|
#![allow(missing_docs)] // we allow missing to avoid having to document the dispatch traits.
|
||||||
|
|
||||||
@ -21,6 +21,9 @@ use quickcheck::{Arbitrary, Gen};
|
|||||||
|
|
||||||
|
|
||||||
/// Vector of dimension 0.
|
/// Vector of dimension 0.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
||||||
pub struct Vec0<N>(pub PhantomData<N>);
|
pub struct Vec0<N>(pub PhantomData<N>);
|
||||||
@ -41,6 +44,9 @@ impl<N> Repeat<N> for Vec0<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Vector of dimension 1.
|
/// Vector of dimension 1.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Vec1<N> {
|
pub struct Vec1<N> {
|
||||||
@ -93,6 +99,9 @@ rand_impl!(Vec1, x);
|
|||||||
mean_impl!(Vec1);
|
mean_impl!(Vec1);
|
||||||
|
|
||||||
/// Vector of dimension 2.
|
/// Vector of dimension 2.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Vec2<N> {
|
pub struct Vec2<N> {
|
||||||
@ -147,6 +156,9 @@ rand_impl!(Vec2, x, y);
|
|||||||
mean_impl!(Vec2);
|
mean_impl!(Vec2);
|
||||||
|
|
||||||
/// Vector of dimension 3.
|
/// Vector of dimension 3.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Vec3<N> {
|
pub struct Vec3<N> {
|
||||||
@ -204,6 +216,9 @@ mean_impl!(Vec3);
|
|||||||
|
|
||||||
|
|
||||||
/// Vector of dimension 4.
|
/// Vector of dimension 4.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Vec4<N> {
|
pub struct Vec4<N> {
|
||||||
@ -262,6 +277,9 @@ rand_impl!(Vec4, x, y, z, w);
|
|||||||
mean_impl!(Vec4);
|
mean_impl!(Vec4);
|
||||||
|
|
||||||
/// Vector of dimension 5.
|
/// Vector of dimension 5.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Vec5<N> {
|
pub struct Vec5<N> {
|
||||||
@ -322,6 +340,9 @@ rand_impl!(Vec5, x, y, z, w, a);
|
|||||||
mean_impl!(Vec5);
|
mean_impl!(Vec5);
|
||||||
|
|
||||||
/// Vector of dimension 6.
|
/// Vector of dimension 6.
|
||||||
|
///
|
||||||
|
/// The main differance between a point and a vector is that a vector is not affected by
|
||||||
|
/// translations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Vec6<N> {
|
pub struct Vec6<N> {
|
||||||
|
Loading…
Reference in New Issue
Block a user