From 0c8b8bfcdb4f9be383f0cc6304f697ecbad6b4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Thu, 24 Mar 2016 19:03:40 +0100 Subject: [PATCH] Add similarity transformations Sim2 and Sim3 (uniform scale followed by a rotation followed by a translation). --- README.md | 12 +- src/lib.rs | 13 +- src/structs/iso.rs | 18 ++- src/structs/iso_macros.rs | 27 +++- src/structs/mod.rs | 3 + src/structs/pnt.rs | 23 +++- src/structs/sim.rs | 80 ++++++++++++ src/structs/sim_macros.rs | 264 ++++++++++++++++++++++++++++++++++++++ src/structs/vec.rs | 23 +++- 9 files changed, 444 insertions(+), 19 deletions(-) create mode 100644 src/structs/sim.rs create mode 100644 src/structs/sim_macros.rs diff --git a/README.md b/README.md index 6a3150d3..68dc1126 100644 --- a/README.md +++ b/README.md @@ -44,15 +44,17 @@ fn main() { **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: -* 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`. * Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `. * Rotation matrices: `Rot2`, `Rot3`, `Rot4`. * 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`. -* Dynamically sized vector: `DVec`. -* Dynamically sized (square or rectangular) matrix: `DMat`. +* Dynamically sized heap-allocated vector: `DVec`. +* 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`. * Almost one trait per functionality: useful for generic programming. -* Operator overloading using multidispatch. diff --git a/src/lib.rs b/src/lib.rs index 9f6b175e..f5953f7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,18 +41,20 @@ fn main() { **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: -* 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`. * Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `. * Rotation matrices: `Rot2`, `Rot3`, `Rot4`. * 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`. -* Dynamically sized vector: `DVec`. -* Dynamically sized (square or rectangular) matrix: `DMat`. +* Dynamically sized heap-allocated vector: `DVec`. +* 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`. * Almost one trait per functionality: useful for generic programming. -* Operator overloading using multidispatch. ## **nalgebra** in use @@ -139,6 +141,7 @@ pub use structs::{ DMat, DMat1, DMat2, DMat3, DMat4, DMat5, DMat6, DVec, DVec1, DVec2, DVec3, DVec4, DVec5, DVec6, Iso2, Iso3, Iso4, + Sim2, Sim3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot2, Rot3, Rot4, diff --git a/src/structs/iso.rs b/src/structs/iso.rs index f42d48d5..7c022ed5 100644 --- a/src/structs/iso.rs +++ b/src/structs/iso.rs @@ -1,7 +1,3 @@ -//! Isometric transformations. - -#![allow(missing_docs)] - use std::ops::{Add, Sub, Mul, Neg}; use rand::{Rand, Rng}; @@ -22,7 +18,8 @@ use quickcheck::{Arbitrary, Gen}; /// 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. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)] @@ -35,7 +32,8 @@ pub struct Iso2 { /// 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. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)] @@ -48,6 +46,8 @@ pub struct Iso3 { /// 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. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)] @@ -117,6 +117,8 @@ translate_impl!(Iso2, Pnt2); iso_mul_iso_impl!(Iso2); iso_mul_pnt_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); iso_impl!(Iso3, Rot3, Vec3, Vec3); @@ -137,6 +139,8 @@ translate_impl!(Iso3, Pnt3); iso_mul_iso_impl!(Iso3); iso_mul_pnt_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); // iso_impl!(Iso4, Rot4, Vec4, Vec4); @@ -157,5 +161,7 @@ translate_impl!(Iso4, Pnt4); iso_mul_iso_impl!(Iso4); iso_mul_pnt_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: Arbitrary // arbitrary_iso_impl!(Iso4); diff --git a/src/structs/iso_macros.rs b/src/structs/iso_macros.rs index 7cdd3136..79484bf7 100644 --- a/src/structs/iso_macros.rs +++ b/src/structs/iso_macros.rs @@ -3,7 +3,7 @@ macro_rules! iso_impl( ($t: ident, $submat: ident, $subvec: ident, $subrotvec: ident) => ( impl $t { - /// Creates a new isometry from a rotation matrix and a vector. + /// Creates a new isometry from an axis-angle rotation, and a vector. #[inline] pub fn new(translation: $subvec, rotation: $subrotvec) -> $t { $t { @@ -89,6 +89,19 @@ macro_rules! iso_mul_pnt_impl( ) ); +macro_rules! iso_mul_vec_impl( + ($t: ident, $tv: ident) => ( + impl Mul<$tv> for $t { + type Output = $tv; + + #[inline] + fn mul(self, right: $tv) -> $tv { + self.rotation * right + } + } + ) +); + macro_rules! pnt_mul_iso_impl( ($t: ident, $tv: ident) => ( impl Mul<$t> for $tv { @@ -101,6 +114,18 @@ macro_rules! pnt_mul_iso_impl( ) ); +macro_rules! vec_mul_iso_impl( + ($t: ident, $tv: ident) => ( + impl Mul<$t> for $tv { + type Output = $tv; + #[inline] + fn mul(self, right: $t) -> $tv { + self * right.rotation + } + } + ) +); + macro_rules! translation_impl( ($t: ident, $tv: ident) => ( impl Translation<$tv> for $t { diff --git a/src/structs/mod.rs b/src/structs/mod.rs index d5ab760e..c2888f56 100644 --- a/src/structs/mod.rs +++ b/src/structs/mod.rs @@ -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::rot::{Rot2, Rot3, Rot4}; pub use self::iso::{Iso2, Iso3, Iso4}; +pub use self::sim::{Sim2, Sim3}; pub use self::persp::{Persp3, PerspMat3}; pub use self::ortho::{Ortho3, OrthoMat3}; pub use self::quat::{Quat, UnitQuat}; @@ -29,6 +30,8 @@ mod rot_macros; mod rot; mod iso_macros; mod iso; +mod sim_macros; +mod sim; mod persp; mod ortho; diff --git a/src/structs/pnt.rs b/src/structs/pnt.rs index a937c73a..f2d6fca0 100644 --- a/src/structs/pnt.rs +++ b/src/structs/pnt.rs @@ -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. @@ -19,6 +19,9 @@ use quickcheck::{Arbitrary, Gen}; /// Point of dimension 0. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, Clone, Debug, Copy)] pub struct Pnt0(pub PhantomData); @@ -39,6 +42,9 @@ impl Repeat for Pnt0 { } /// Point of dimension 1. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Pnt1 { @@ -79,6 +85,9 @@ arbitrary_pnt_impl!(Pnt1, x); rand_impl!(Pnt1, x); /// Point of dimension 2. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Pnt2 { @@ -121,6 +130,9 @@ arbitrary_pnt_impl!(Pnt2, x, y); rand_impl!(Pnt2, x, y); /// Point of dimension 3. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Pnt3 { @@ -165,6 +177,9 @@ arbitrary_pnt_impl!(Pnt3, x, y, z); rand_impl!(Pnt3, x, y, z); /// Point of dimension 4. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Pnt4 { @@ -211,6 +226,9 @@ arbitrary_pnt_impl!(Pnt4, x, y, z, w); rand_impl!(Pnt4, x, y, z, w); /// Point of dimension 5. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Pnt5 { @@ -259,6 +277,9 @@ arbitrary_pnt_impl!(Pnt5, x, y, z, w, a); rand_impl!(Pnt5, x, y, z, w, a); /// Point of dimension 6. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Pnt6 { diff --git a/src/structs/sim.rs b/src/structs/sim.rs new file mode 100644 index 00000000..299c385e --- /dev/null +++ b/src/structs/sim.rs @@ -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 { + /// The uniform scale applicable by this similarity transformation. + scale: N, + /// The isometry applicable by this similarity transformation. + pub isometry: Iso2 +} + +/// 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 { + /// The uniform scale applicable by this similarity transformation. + scale: N, + /// The isometry applicable by this similarity transformation. + pub isometry: Iso3 +} + +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); diff --git a/src/structs/sim_macros.rs b/src/structs/sim_macros.rs new file mode 100644 index 00000000..75d6cde9 --- /dev/null +++ b/src/structs/sim_macros.rs @@ -0,0 +1,264 @@ +#![macro_use] + +macro_rules! sim_impl( + ($t: ident, $iso: ident, $rotmat: ident, $subvec: ident, $subrotvec: ident) => ( + impl $t { + /// 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, rotation: $subrotvec, scale: N) -> $t { + 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, rotation: $rotmat, scale: N) -> $t { + 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, scale: N) -> $t { + 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 $t { + /// 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::() / 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 { + 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 { + 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 One for $t { + #[inline] + fn one() -> $t { + $t::new_with_iso(::one(), ::one()) + } + } + ) +); + +macro_rules! sim_mul_sim_impl( + ($t: ident) => ( + impl Mul<$t> for $t { + type Output = $t; + + #[inline] + fn mul(self, right: $t) -> $t { + $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 Mul<$tv> for $t { + type Output = $tv; + + #[inline] + fn mul(self, right: $tv) -> $tv { + self.isometry * (right * self.scale) + } + } + ) +); + +macro_rules! pnt_vec_mul_sim_impl( + ($t: ident, $tv: ident) => ( + impl Mul<$t> for $tv { + type Output = $tv; + #[inline] + fn mul(self, right: $t) -> $tv { + self * right.isometry * right.scale + } + } + ) +); + +macro_rules! sim_transform_impl( + ($t: ident, $tp: ident) => ( + impl Transform<$tp> for $t { + #[inline] + fn transform(&self, p: &$tp) -> $tp { + self.isometry.transform(p) * self.scale + } + + #[inline] + fn inv_transform(&self, p: &$tp) -> $tp { + self.isometry.inv_transform(p) / self.scale + } + } + ) +); + +macro_rules! sim_inv_impl( + ($t: ident) => ( + impl> Inv for $t { + #[inline] + fn inv_mut(&mut self) -> bool { + self.scale = ::one::() / 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> { + let mut res = *self; + res.inv_mut(); + + // always succeed + Some(res) + } + } + ) +); + +macro_rules! sim_to_homogeneous_impl( + ($t: ident, $th: ident) => ( + impl ToHomogeneous<$th> for $t { + fn to_homogeneous(&self) -> $th { + let mut res = (*self.isometry.rotation.submat() * self.scale).to_homogeneous(); + + // copy the translation + let dim = Dim::dim(None::<$th>); + + res.set_col(dim - 1, self.isometry.translation.as_pnt().to_homogeneous().to_vec()); + + res + } + } + ) +); + +macro_rules! sim_approx_eq_impl( + ($t: ident) => ( + impl> ApproxEq for $t { + #[inline] + fn approx_epsilon(_: Option<$t>) -> N { + ApproxEq::approx_epsilon(None::) + } + + #[inline] + fn approx_ulps(_: Option<$t>) -> u32 { + ApproxEq::approx_ulps(None::) + } + + #[inline] + fn approx_eq_eps(&self, other: &$t, 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, 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 Rand for $t { + #[inline] + fn rand(rng: &mut R) -> $t { + $t::new_with_iso(rng.gen(), rng.gen()) + } + } + ) +); + +macro_rules! sim_arbitrary_impl( + ($t: ident) => ( + #[cfg(feature="arbitrary")] + impl Arbitrary for $t { + fn arbitrary(g: &mut G) -> $t { + $t::new_with_iso( + Arbitrary::arbitrary(g), + Arbitrary::arbitrary(g) + ) + } + } + ) +); diff --git a/src/structs/vec.rs b/src/structs/vec.rs index 32517fff..3b2339f4 100644 --- a/src/structs/vec.rs +++ b/src/structs/vec.rs @@ -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. @@ -21,6 +21,9 @@ use quickcheck::{Arbitrary, Gen}; /// Vector of dimension 0. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, Clone, Debug, Copy)] pub struct Vec0(pub PhantomData); @@ -41,6 +44,9 @@ impl Repeat for Vec0 { } /// Vector of dimension 1. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Vec1 { @@ -93,6 +99,9 @@ rand_impl!(Vec1, x); mean_impl!(Vec1); /// Vector of dimension 2. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Vec2 { @@ -147,6 +156,9 @@ rand_impl!(Vec2, x, y); mean_impl!(Vec2); /// Vector of dimension 3. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Vec3 { @@ -204,6 +216,9 @@ mean_impl!(Vec3); /// Vector of dimension 4. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Vec4 { @@ -262,6 +277,9 @@ rand_impl!(Vec4, x, y, z, w); mean_impl!(Vec4); /// Vector of dimension 5. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Vec5 { @@ -322,6 +340,9 @@ rand_impl!(Vec5, x, y, z, w, a); mean_impl!(Vec5); /// Vector of dimension 6. +/// +/// The main differance between a point and a vector is that a vector is not affected by +/// translations. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] pub struct Vec6 {