diff --git a/src/adaptors/rotmat.rs b/src/adaptors/rotmat.rs index 8e253eb6..4a00766a 100644 --- a/src/adaptors/rotmat.rs +++ b/src/adaptors/rotmat.rs @@ -5,15 +5,18 @@ use traits::rlmul::{RMul, LMul}; use traits::cross::Cross; use traits::dim::Dim; use traits::inv::Inv; +use traits::row::Row; +use traits::col::Col; use traits::transpose::Transpose; -use traits::rotation::{Rotation, Rotate}; +use traits::absolute::Absolute; +use traits::rotation::{Rotation, Rotate, RotationMatrix}; use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable use traits::homogeneous::ToHomogeneous; use traits::indexable::Indexable; use traits::norm::Norm; -use vec::Vec1; +use traits::comp::absolute_rotate::AbsoluteRotate; +use vec::{Vec1, Vec2, Vec3}; use mat::{Mat2, Mat3}; -use vec::Vec3; /// Matrix wrapper representing rotation matrix. It is built uppon another matrix and ensures (at /// the type-level) that it will always represent a rotation. Rotation matrices have some @@ -120,6 +123,14 @@ impl Rotmat> { } } +impl +RotationMatrix, Vec1, Rotmat>> for Rotmat> { + #[inline] + fn to_rot_mat(&self) -> Rotmat> { + self.clone() + } +} + impl Rotation> for Rotmat> { #[inline] @@ -148,6 +159,14 @@ Rotation> for Rotmat> { } } +impl +RotationMatrix, Vec3, Rotmat>> for Rotmat> { + #[inline] + fn to_rot_mat(&self) -> Rotmat> { + self.clone() + } +} + impl Rotation> for Rotmat> { #[inline] @@ -304,8 +323,42 @@ Transpose for Rotmat { } } +impl, R> Row for Rotmat { + #[inline] + fn num_rows(&self) -> uint { + self.submat.num_rows() + } + #[inline] + fn row(&self, i: uint) -> R { + self.submat.row(i) + } + + #[inline] + fn set_row(&mut self, i: uint, row: R) { + self.submat.set_row(i, row); + } +} + +impl, C> Col for Rotmat { + #[inline] + fn num_cols(&self) -> uint { + self.submat.num_cols() + } + + #[inline] + fn col(&self, i: uint) -> C { + self.submat.col(i) + } + + #[inline] + fn set_col(&mut self, i: uint, col: C) { + self.submat.set_col(i, col); + } +} + // we loose the info that we are a rotation matrix impl, M2> ToHomogeneous for Rotmat { + #[inline] fn to_homogeneous(&self) -> M2 { self.submat.to_homogeneous() } @@ -328,3 +381,33 @@ impl, M: ApproxEq> ApproxEq for Rotmat { self.submat.approx_eq_eps(&other.submat, epsilon) } } + +impl, M2> Absolute for Rotmat { + #[inline] + fn absolute(&self) -> M2 { + self.submat.absolute() + } +} + +impl AbsoluteRotate> for Rotmat> { + #[inline] + fn absolute_rotate(&self, v: &Vec3) -> Vec3 { + Vec3::new( + self.submat.m11.abs() * v.x + self.submat.m12.abs() * v.y + self.submat.m13.abs() * v.z, + self.submat.m21.abs() * v.x + self.submat.m22.abs() * v.y + self.submat.m23.abs() * v.z, + self.submat.m31.abs() * v.x + self.submat.m32.abs() * v.y + self.submat.m33.abs() * v.z) + } +} + +impl AbsoluteRotate> for Rotmat> { + #[inline] + fn absolute_rotate(&self, v: &Vec2) -> Vec2 { + // the matrix is skew-symetric, so we dont need to compute the absolute value of every + // component. + let m11 = self.submat.m11.abs(); + let m12 = self.submat.m12.abs(); + let m22 = self.submat.m22.abs(); + + Vec2::new(m11 * v.x + m12 * v.y, m12 * v.x + m22 * v.y) + } +} diff --git a/src/adaptors/transform.rs b/src/adaptors/transform.rs index 04e22161..ec31f7ef 100644 --- a/src/adaptors/transform.rs +++ b/src/adaptors/transform.rs @@ -2,14 +2,17 @@ use std::num::{One, Zero}; use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; use traits::dim::Dim; +use traits::absolute::Absolute; +use traits::mat::Mat; use traits::inv::Inv; -use traits::rotation::{Rotation, Rotate}; +use traits::rotation::{Rotation, Rotate, RotationMatrix}; use traits::translation::{Translation, Translate}; use Ts = traits::transformation::Transform; use traits::transformation::{Transformation}; use traits::rlmul::{RMul, LMul}; use traits::homogeneous::{ToHomogeneous, FromHomogeneous}; use traits::column::Column; +use traits::comp::absolute_rotate::AbsoluteRotate; use adaptors::rotmat::Rotmat; use vec::Vec3; use mat::Mat3; @@ -53,6 +56,14 @@ impl Transform { } } +impl + RotationMatrix, M2: Mat + Rotation> +RotationMatrix for Transform { + #[inline] + fn to_rot_mat(&self) -> M2 { + self.submat.to_rot_mat() + } +} + impl Transform, Rotmat>> { /// 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 @@ -342,3 +353,18 @@ impl Rand for Transform { Transform::new(rng.gen(), rng.gen()) } } + +impl, M: Absolute, V2, M2> +Absolute> for Transform { + #[inline] + fn absolute(&self) -> Transform { + Transform::new(self.subtrans.absolute(), self.submat.absolute()) + } +} + +impl> AbsoluteRotate for Transform { + #[inline] + fn absolute_rotate(&self, v: &V) -> V { + self.submat.absolute_rotate(v) + } +} diff --git a/src/lib.rs b/src/lib.rs index 00cb94ec..970dec47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,16 +29,14 @@ mod vec0_spec; mod identity_spec; /// Wrappers around raw matrices to restrict their behaviour. -pub mod adaptors -{ +pub mod adaptors { pub mod rotmat; pub mod transform; } pub mod types; -pub mod traits -{ +pub mod traits { pub mod vector; pub mod sample; pub mod indexable; @@ -61,11 +59,21 @@ pub mod traits pub mod mat_cast; pub mod norm; pub mod dot; + pub mod mat; + pub mod absolute; + pub mod col; + + /// Unusual traits which are composition of other primitive traits. + /// Those are mainly shortcuts to make some operation easier to use or faster. + /// Mathematics purists should really not go in there! + pub mod comp { + pub mod rotation_with_translation; + pub mod absolute_rotate; + } } #[cfg(test)] -pub mod tests -{ +pub mod tests { pub mod mat; pub mod vec; } diff --git a/src/mat.rs b/src/mat.rs index ed116313..fd1f233e 100644 --- a/src/mat.rs +++ b/src/mat.rs @@ -7,6 +7,8 @@ use std::vec::{VecIterator, VecMutIterator}; use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Outer}; // traits +pub use traits::mat::Mat; +pub use traits::absolute::Absolute; pub use traits::dim::Dim; pub use traits::indexable::Indexable; pub use traits::iterable::{Iterable, IterableMut}; @@ -15,12 +17,15 @@ pub use traits::mat_cast::MatCast; pub use traits::column::Column; pub use traits::inv::Inv; pub use traits::rlmul::{RMul, LMul}; -pub use traits::rotation::{Rotation, Rotate, RotationWithTranslation}; +pub use traits::rotation::{Rotation, RotationMatrix, Rotate}; pub use traits::transformation::{Transformation, Transform}; pub use traits::translation::{Translation, Translate}; pub use traits::transpose::{Transpose}; pub use traits::homogeneous::{ToHomogeneous, FromHomogeneous}; pub use traits::row::Row; +pub use traits::col::Col; +pub use traits::comp::rotation_with_translation::RotationWithTranslation; +pub use traits::comp::absolute_rotate::AbsoluteRotate; // structs pub use dmat::DMat; @@ -57,6 +62,7 @@ scalar_mul_impl!(Mat1, m11) scalar_div_impl!(Mat1, m11) scalar_add_impl!(Mat1, m11) scalar_sub_impl!(Mat1, m11) +absolute_impl!(Mat1, m11) one_impl!(Mat1, One::one) iterable_impl!(Mat1, 1) iterable_mut_impl!(Mat1, 1) @@ -71,6 +77,7 @@ transpose_impl!(Mat1, 1) approx_eq_impl!(Mat1) column_impl!(Mat1, Vec1, 1) row_impl!(Mat1, Vec1, 1) +col_impl!(Mat1, Vec1, 1) to_homogeneous_impl!(Mat1, Mat2, 1, 2) from_homogeneous_impl!(Mat1, Mat2, 1, 2) outer_impl!(Vec1, Mat1) @@ -98,6 +105,8 @@ scalar_add_impl!(Mat2, m11, m12, m21, m22) scalar_sub_impl!(Mat2, m11, m12, m21, m22) +absolute_impl!(Mat2, m11, m12, + m21, m22) one_impl!(Mat2, One::one, Zero::zero, Zero::zero, One::one) iterable_impl!(Mat2, 2) @@ -113,6 +122,7 @@ transpose_impl!(Mat2, 2) approx_eq_impl!(Mat2) column_impl!(Mat2, Vec2, 2) row_impl!(Mat2, Vec2, 2) +col_impl!(Mat2, Vec2, 2) to_homogeneous_impl!(Mat2, Mat3, 2, 3) from_homogeneous_impl!(Mat2, Mat3, 2, 3) outer_impl!(Vec2, Mat2) @@ -149,6 +159,9 @@ scalar_add_impl!(Mat3, m11, m12, m13, scalar_sub_impl!(Mat3, m11, m12, m13, m21, m22, m23, m31, m32, m33) +absolute_impl!(Mat3, m11, m12, m13, + m21, m22, m23, + m31, m32, m33) one_impl!(Mat3, One::one , Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, One::one) @@ -165,6 +178,7 @@ transpose_impl!(Mat3, 3) approx_eq_impl!(Mat3) column_impl!(Mat3, Vec3, 3) // (specialized) row_impl!(Mat3, Vec3, 3) +// (specialized) col_impl!(Mat3, Vec3, 3) to_homogeneous_impl!(Mat3, Mat4, 3, 4) from_homogeneous_impl!(Mat3, Mat4, 3, 4) outer_impl!(Vec3, Mat3) @@ -226,6 +240,12 @@ scalar_sub_impl!(Mat4, m31, m32, m33, m34, m41, m42, m43, m44 ) +absolute_impl!(Mat4, + m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44 +) one_impl!(Mat4, One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, @@ -243,6 +263,7 @@ transpose_impl!(Mat4, 4) approx_eq_impl!(Mat4) column_impl!(Mat4, Vec4, 4) row_impl!(Mat4, Vec4, 4) +col_impl!(Mat4, Vec4, 4) to_homogeneous_impl!(Mat4, Mat5, 4, 5) from_homogeneous_impl!(Mat4, Mat5, 4, 5) outer_impl!(Vec4, Mat4) @@ -271,6 +292,13 @@ mat_cast_impl!(Mat5, m41, m42, m43, m44, m45, m51, m52, m53, m54, m55 ) +absolute_impl!(Mat5, + m11, m12, m13, m14, m15, + m21, m22, m23, m24, m25, + m31, m32, m33, m34, m35, + m41, m42, m43, m44, m45, + m51, m52, m53, m54, m55 +) one_impl!(Mat5, One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, @@ -333,6 +361,7 @@ transpose_impl!(Mat5, 5) approx_eq_impl!(Mat5) column_impl!(Mat5, Vec5, 5) row_impl!(Mat5, Vec5, 5) +col_impl!(Mat5, Vec5, 5) to_homogeneous_impl!(Mat5, Mat6, 5, 6) from_homogeneous_impl!(Mat5, Mat6, 5, 6) outer_impl!(Vec5, Mat5) @@ -412,6 +441,14 @@ scalar_sub_impl!(Mat6, m51, m52, m53, m54, m55, m56, m61, m62, m63, m64, m65, m66 ) +absolute_impl!(Mat6, + m11, m12, m13, m14, m15, m16, + m21, m22, m23, m24, m25, m26, + m31, m32, m33, m34, m35, m36, + m41, m42, m43, m44, m45, m46, + m51, m52, m53, m54, m55, m56, + m61, m62, m63, m64, m65, m66 +) one_impl!(Mat6, One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, @@ -433,4 +470,5 @@ transpose_impl!(Mat6, 6) approx_eq_impl!(Mat6) column_impl!(Mat6, Vec6, 6) row_impl!(Mat6, Vec6, 6) +col_impl!(Mat6, Vec6, 6) outer_impl!(Vec6, Mat6) diff --git a/src/mat_macros.rs b/src/mat_macros.rs index 60753a00..aaa22fb4 100644 --- a/src/mat_macros.rs +++ b/src/mat_macros.rs @@ -105,6 +105,17 @@ macro_rules! scalar_sub_impl( ) ) +macro_rules! absolute_impl( + ($t: ident, $comp0: ident $(,$compN: ident)*) => ( + impl Absolute<$t> for $t { + #[inline] + fn absolute(&self) -> $t { + $t::new(self.$comp0.abs() $(, self.$compN.abs() )*) + } + } + ) +) + macro_rules! iterable_impl( ($t: ident, $dim: expr) => ( impl Iterable for $t { @@ -208,6 +219,11 @@ macro_rules! column_impl( macro_rules! row_impl( ($t: ident, $tv: ident, $dim: expr) => ( impl Row<$tv> for $t { + #[inline] + fn num_rows(&self) -> uint { + Dim::dim(None::<$t>) + } + #[inline] fn set_row(&mut self, row: uint, v: $tv) { for (i, e) in v.iter().enumerate() { @@ -229,6 +245,35 @@ macro_rules! row_impl( ) ) +macro_rules! col_impl( + ($t: ident, $tv: ident, $dim: expr) => ( + impl Col<$tv> for $t { + #[inline] + fn num_cols(&self) -> uint { + Dim::dim(None::<$t>) + } + + #[inline] + fn set_col(&mut self, col: uint, v: $tv) { + for (i, e) in v.iter().enumerate() { + self.set((col, i), e.clone()); + } + } + + #[inline] + fn col(&self, col: uint) -> $tv { + let mut res: $tv = Zero::zero(); + + for (i, e) in res.mut_iter().enumerate() { + *e = self.at((i, col)); + } + + res + } + } + ) +) + macro_rules! mul_impl( ($t: ident, $dim: expr) => ( impl Mul<$t, $t> for $t { diff --git a/src/mat_spec.rs b/src/mat_spec.rs index 75d6e57a..4de3f8cb 100644 --- a/src/mat_spec.rs +++ b/src/mat_spec.rs @@ -1,6 +1,6 @@ use std::num::{Zero, One}; use vec::Vec3; -use mat::{Mat1, Mat2, Mat3, Inv, Row}; +use mat::{Mat1, Mat2, Mat3, Inv, Row, Col}; use mat; // some specializations: @@ -110,6 +110,11 @@ Inv for Mat3 { } impl Row> for Mat3 { + #[inline] + fn num_rows(&self) -> uint { + 3 + } + #[inline] fn row(&self, i: uint) -> Vec3 { match i { @@ -144,6 +149,46 @@ impl Row> for Mat3 { } } +impl Col> for Mat3 { + #[inline] + fn num_cols(&self) -> uint { + 3 + } + + #[inline] + fn col(&self, i: uint) -> Vec3 { + match i { + 0 => Vec3::new(self.m11.clone(), self.m21.clone(), self.m31.clone()), + 1 => Vec3::new(self.m12.clone(), self.m22.clone(), self.m32.clone()), + 2 => Vec3::new(self.m13.clone(), self.m23.clone(), self.m33.clone()), + _ => fail!("Index out of range: 3d matrices do not have " + i.to_str() + " cols.") + } + } + + #[inline] + fn set_col(&mut self, i: uint, r: Vec3) { + match i { + 0 => { + self.m11 = r.x.clone(); + self.m21 = r.y.clone(); + self.m31 = r.z; + }, + 1 => { + self.m12 = r.x.clone(); + self.m22 = r.y.clone(); + self.m32 = r.z; + }, + 2 => { + self.m13 = r.x.clone(); + self.m23 = r.y.clone(); + self.m33 = r.z; + }, + _ => fail!("Index out of range: 3d matrices do not have " + i.to_str() + " cols.") + + } + } +} + // FIXME: move this to another file? impl mat::Mat4 { /// Computes a projection matrix given the frustrum near plane width, height, the field of diff --git a/src/traits/absolute.rs b/src/traits/absolute.rs new file mode 100644 index 00000000..8d57c11e --- /dev/null +++ b/src/traits/absolute.rs @@ -0,0 +1,7 @@ +/// Trait of objects having an absolute value. +/// This is useful of the object and the absolute value do not have the same type. +pub trait Absolute { + /// Compute some absolute representation of this object. + /// Typically, this will make all component of a matrix or vector positive. + fn absolute(&self) -> A; +} diff --git a/src/traits/col.rs b/src/traits/col.rs new file mode 100644 index 00000000..b604fde7 --- /dev/null +++ b/src/traits/col.rs @@ -0,0 +1,9 @@ +/// Traits to access columns of a matrix or vector. +pub trait Col { + /// The number of columun of this matrix or vector. + fn num_cols(&self) -> uint; + /// Reads the `i`-th column of `self`. + fn col(&self, i: uint) -> C; + /// Writes the `i`-th column of `self`. + fn set_col(&mut self, i: uint, C); +} diff --git a/src/traits/comp/absolute_rotate.rs b/src/traits/comp/absolute_rotate.rs new file mode 100644 index 00000000..f0532dc3 --- /dev/null +++ b/src/traits/comp/absolute_rotate.rs @@ -0,0 +1,16 @@ +/// Trait of matrices having the following operation: +/// +/// self.absolute_rotate(v) = self.rotation_matrix().absolute().rmul(v) +/// +/// The operation is accessible using the `RotationMatrix`, `Absolute`, and `RMul` traits, but +/// doing so is not easy in generic code as it can be a cause of type over-parametrization. +/// +/// # Known use case: +/// * to compute efficiently the AABB of a rotated AABB. +pub trait AbsoluteRotate { + + /// This is the same as: + /// + /// self.absolute_rotate(v) = self.rotation_matrix().absolute().rmul(v) + fn absolute_rotate(&self, &V) -> V; +} diff --git a/src/traits/comp/rotation_with_translation.rs b/src/traits/comp/rotation_with_translation.rs new file mode 100644 index 00000000..b196177b --- /dev/null +++ b/src/traits/comp/rotation_with_translation.rs @@ -0,0 +1,70 @@ +use traits::rotation::Rotation; +use traits::translation::Translation; + +// NOTE: we cannot call this an Isometry since an isometry really does not need to have a rotation +// nor a translation (this can be a reflexion). +/// Utilities to make rotations with regard to a point different than the origin. +/// All those operations are the composition of rotations and translations. +/// This could be implemented in term of the `Rotation` and `Translation` traits, but having those +/// here make it easier to use. +/// +/// # Known use case: +/// * to change the center of a rotation. +pub trait RotationWithTranslation, AV>: Rotation + Translation { + /** + * Applies a rotation centered on a specific point. + * + * - `m`: the object to be rotated. + * - `ammount`: the rotation to apply. + * - `point`: the center of rotation. + */ + #[inline] + fn rotated_wrt_point(&self, ammount: &AV, center: &LV) -> Self { + let mut res = self.translated(&-center); + + res.rotate_by(ammount); + res.translate_by(center); + + res + } + + /// Rotates an object using a specific center of rotation. + /// + /// # Arguments + /// * `m` - the object to be rotated + /// * `ammount` - the rotation to be applied + /// * `center` - the new center of rotation + #[inline] + fn rotate_wrt_point(&mut self, ammount: &AV, center: &LV) { + self.translate_by(&-center); + self.rotate_by(ammount); + self.translate_by(center); + } + + /** + * Applies a rotation centered on the input translation. + * + * # Arguments + * * `m` - the object to be rotated. + * * `ammount` - the rotation to apply. + */ + #[inline] + fn rotated_wrt_center(&self, ammount: &AV) -> Self { + self.rotated_wrt_point(ammount, &self.translation()) + } + + /** + * Applies a rotation centered on the input translation. + * + * # Arguments + * * `m` - the object to be rotated. + * * `ammount` - the rotation to apply. + */ + #[inline] + fn rotate_wrt_center(&mut self, ammount: &AV) { + let center = self.translation(); + self.rotate_wrt_point(ammount, ¢er) + } +} + +impl, AV, M: Rotation + Translation> RotationWithTranslation for M; diff --git a/src/traits/mat.rs b/src/traits/mat.rs new file mode 100644 index 00000000..9e7585b6 --- /dev/null +++ b/src/traits/mat.rs @@ -0,0 +1,8 @@ +use traits::row::Row; +use traits::col::Col; +use traits::rlmul::{RMul, LMul}; + +/// Trait of matrix. A matrix must have lines and columns. +pub trait Mat : Row + Col + RMul + LMul { } + +impl + Col + RMul + LMul, R, C> Mat for M; diff --git a/src/traits/rotation.rs b/src/traits/rotation.rs index 0f6b2bd6..aeba53e0 100644 --- a/src/traits/rotation.rs +++ b/src/traits/rotation.rs @@ -1,4 +1,4 @@ -use traits::translation::Translation; +use traits::mat::Mat; /// Trait of object which represent a rotation, and to wich new rotations can /// be appended. A rotation is assumed to be an isomitry without translation @@ -29,64 +29,9 @@ pub trait Rotate { fn inv_rotate(&self, &V) -> V; } -/// Utilities to make rotations with regard to a point different than the origin. -// NOTE: we cannot call this an Isometry since an isometry really does not need to have a rotation -// nor a translation (this can be a reflexion). -pub trait RotationWithTranslation, AV>: Rotation + Translation { - /** - * Applies a rotation centered on a specific point. - * - * - `m`: the object to be rotated. - * - `ammount`: the rotation to apply. - * - `point`: the center of rotation. - */ - #[inline] - fn rotated_wrt_point(&self, ammount: &AV, center: &LV) -> Self { - let mut res = self.translated(&-center); - - res.rotate_by(ammount); - res.translate_by(center); - - res - } - - /// Rotates an object using a specific center of rotation. - /// - /// # Arguments - /// * `m` - the object to be rotated - /// * `ammount` - the rotation to be applied - /// * `center` - the new center of rotation - #[inline] - fn rotate_wrt_point(&mut self, ammount: &AV, center: &LV) { - self.translate_by(&-center); - self.rotate_by(ammount); - self.translate_by(center); - } - - /** - * Applies a rotation centered on the input translation. - * - * # Arguments - * * `m` - the object to be rotated. - * * `ammount` - the rotation to apply. - */ - #[inline] - fn rotated_wrt_center(&self, ammount: &AV) -> Self { - self.rotated_wrt_point(ammount, &self.translation()) - } - - /** - * Applies a rotation centered on the input translation. - * - * # Arguments - * * `m` - the object to be rotated. - * * `ammount` - the rotation to apply. - */ - #[inline] - fn rotate_wrt_center(&mut self, ammount: &AV) { - let center = self.translation(); - self.rotate_wrt_point(ammount, ¢er) - } +/// Trait of transformation having a rotation extractable as a rotation matrix. This can typically +/// be implemented by quaternions to convert them +pub trait RotationMatrix + Rotation> : Rotation { + /// Gets the rotation matrix from this object. + fn to_rot_mat(&self) -> R; } - -impl, AV, M: Rotation + Translation> RotationWithTranslation for M; diff --git a/src/traits/row.rs b/src/traits/row.rs index 8e84250e..248d6f28 100644 --- a/src/traits/row.rs +++ b/src/traits/row.rs @@ -1,5 +1,7 @@ /// Traits to access rows of a matrix or vector. pub trait Row { + /// The number of columun of this matrix or vector. + fn num_rows(&self) -> uint; /// Reads the `i`-th row of `self`. fn row(&self, i: uint) -> R; /// Writes the `i`-th row of `self`. diff --git a/src/vec_spec.rs b/src/vec_spec.rs index 0b4ecf68..660b0631 100644 --- a/src/vec_spec.rs +++ b/src/vec_spec.rs @@ -41,6 +41,11 @@ impl + Zero + Clone> CrossMatrix> for Vec3 { // FIXME: iplement this for all other vectors impl Row> for Vec2 { + #[inline] + fn num_rows(&self) -> uint { + 2 + } + #[inline] fn row(&self, i: uint) -> Vec1 { match i {