From 18e9b8998df8ff18f84f5a099b79062de49f5900 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 13 Oct 2018 10:25:34 +0200 Subject: [PATCH] Add impls of From/Into to convert any transformation types to a matrix. --- CHANGELOG.md | 2 ++ src/base/conversion.rs | 12 ++++---- src/geometry/isometry_conversion.rs | 16 +++++++++-- src/geometry/orthographic.rs | 13 +++++++-- src/geometry/perspective.rs | 11 ++++++-- src/geometry/point_conversion.rs | 29 +++++++++++++------- src/geometry/quaternion_conversion.rs | 22 +++++++++++++-- src/geometry/rotation_conversion.rs | 38 +++++++++++++++++++++++--- src/geometry/similarity_conversion.rs | 25 +++++++++++++---- src/geometry/transform_conversion.rs | 16 +++++++++-- src/geometry/translation_conversion.rs | 17 ++++++++++-- src/geometry/unit_complex.rs | 14 ++++++++++ tests/core/matrix.rs | 14 ++++------ 13 files changed, 181 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33bdbf8f..399deea5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). * Add `.slerp` and `.try_slerp` to unit vectors. * Add `.to_projective` and `.as_projective` to `Perspective3` and `Orthographic3` in order to use them as `Projective3` structures. + * Add impl for `From/Into` to allow the conversion of any transformation type to a matrix. + ## [0.16.0] All dependencies have been updated to their latest versions. diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 23654c4f..930fc24d 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -5,18 +5,20 @@ use std::convert::{AsMut, AsRef, From, Into}; use std::mem; use std::ptr; +use generic_array::ArrayLength; use std::ops::Mul; use typenum::Prod; -use generic_array::ArrayLength; use base::allocator::{Allocator, SameShapeAllocator}; use base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use base::dimension::{Dim, DimName, Dynamic, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9}; +use base::dimension::{ + Dim, DimName, Dynamic, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9, +}; use base::iter::{MatrixIter, MatrixIterMut}; use base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixArray, MatrixSlice, MatrixSliceMut, Scalar}; #[cfg(any(feature = "std", feature = "alloc"))] use base::MatrixVec; +use base::{DefaultAllocator, Matrix, MatrixArray, MatrixMN, MatrixSlice, MatrixSliceMut, Scalar}; // FIXME: too bad this won't work allo slice conversions. impl SubsetOf> for MatrixMN @@ -333,7 +335,6 @@ impl_from_into_mint_2D!( (U4, U4) => ColumnMatrix4{x, y, z, w}[4]; ); - impl<'a, N, R, C, RStride, CStride> From> for Matrix> where @@ -403,8 +404,7 @@ where RStride: Dim, CStride: Dim, { - fn from(matrix_slice: MatrixSliceMut<'a, N, Dynamic, C, RStride, CStride>) -> Self - { + fn from(matrix_slice: MatrixSliceMut<'a, N, Dynamic, C, RStride, CStride>) -> Self { matrix_slice.into_owned() } } diff --git a/src/geometry/isometry_conversion.rs b/src/geometry/isometry_conversion.rs index 3a19de5c..a896caf6 100644 --- a/src/geometry/isometry_conversion.rs +++ b/src/geometry/isometry_conversion.rs @@ -1,9 +1,9 @@ use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation; -use base::{DefaultAllocator, MatrixN}; -use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; use base::allocator::Allocator; +use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; +use base::{DefaultAllocator, MatrixN}; use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; @@ -146,3 +146,15 @@ where Self::from_parts(t, ::convert_unchecked(m.clone_owned())) } } + +impl From> for MatrixN> +where + D: DimNameAdd, + R: SubsetOf>>, + DefaultAllocator: Allocator, DimNameSum> + Allocator, +{ + #[inline] + fn from(iso: Isometry) -> Self { + iso.to_homogeneous() + } +} diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 253b1110..d76e8c5a 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -3,7 +3,7 @@ use quickcheck::{Arbitrary, Gen}; use rand::distributions::{Distribution, Standard}; use rand::Rng; #[cfg(feature = "serde-serialize")] -use serde::{Serialize, Deserialize, Serializer, Deserializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; use std::mem; @@ -14,7 +14,7 @@ use base::helper; use base::storage::Storage; use base::{Matrix4, Vector, Vector3}; -use geometry::{Projective3, Point3}; +use geometry::{Point3, Projective3}; /// A 3D orthographic projection stored as an homogeneous 4x4 matrix. pub struct Orthographic3 { @@ -150,7 +150,7 @@ impl Orthographic3 { /// Computes the corresponding homogeneous matrix. #[inline] pub fn to_homogeneous(&self) -> Matrix4 { - self.matrix.clone_owned() + self.matrix } /// A reference to the underlying homogeneous transformation matrix. @@ -356,3 +356,10 @@ where Self::new(left, right, bottom, top, znear, zfar) } } + +impl From> for Matrix4 { + #[inline] + fn from(orth: Orthographic3) -> Self { + orth.unwrap() + } +} diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index 4b4dfeae..1537b327 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -4,7 +4,7 @@ use rand::distributions::{Distribution, Standard}; use rand::Rng; #[cfg(feature = "serde-serialize")] -use serde::{Serialize, Deserialize, Serializer, Deserializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; use std::mem; @@ -15,7 +15,7 @@ use base::helper; use base::storage::Storage; use base::{Matrix4, Scalar, Vector, Vector3}; -use geometry::{Projective3, Point3}; +use geometry::{Point3, Projective3}; /// A 3D perspective projection stored as an homogeneous 4x4 matrix. pub struct Perspective3 { @@ -282,3 +282,10 @@ impl Arbitrary for Perspective3 { Self::new(aspect, Arbitrary::arbitrary(g), znear, zfar) } } + +impl From> for Matrix4 { + #[inline] + fn from(orth: Perspective3) -> Self { + orth.unwrap() + } +} diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index 8284e275..1b1cbaf7 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -1,26 +1,26 @@ -use num::{One, Zero}; use alga::general::{ClosedDiv, SubsetOf, SupersetOf}; +use num::{One, Zero}; -use base::{DefaultAllocator, Matrix, Scalar, VectorN}; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use base::allocator::Allocator; +use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use base::{DefaultAllocator, Matrix, Scalar, VectorN}; +#[cfg(feature = "mint")] +use base::dimension::{U2, U3}; +#[cfg(feature = "mint")] +use base::storage::{Storage, StorageMut}; use geometry::Point; #[cfg(feature = "mint")] use mint; #[cfg(feature = "mint")] -use base::dimension::{U2, U3}; -#[cfg(feature = "mint")] use std::convert::{AsMut, AsRef, From, Into}; -#[cfg(feature = "mint")] -use base::storage::{Storage, StorageMut}; /* * This file provides the following conversions: * ============================================= * * Point -> Point * Point -> Vector (homogeneous) - * + * * mint::Point <-> Point */ @@ -77,8 +77,6 @@ where } } - - #[cfg(feature = "mint")] macro_rules! impl_from_into_mint_1D( ($($NRows: ident => $PT:ident, $VT:ident [$SZ: expr]);* $(;)*) => {$( @@ -129,3 +127,14 @@ impl_from_into_mint_1D!( U2 => Point2, Vector2[2]; U3 => Point3, Vector3[3]; ); + +impl From> for VectorN> +where + D: DimNameAdd, + DefaultAllocator: Allocator + Allocator>, +{ + #[inline] + fn from(t: Point) -> Self { + t.to_homogeneous() + } +} diff --git a/src/geometry/quaternion_conversion.rs b/src/geometry/quaternion_conversion.rs index 15c6fc63..451bc9c0 100644 --- a/src/geometry/quaternion_conversion.rs +++ b/src/geometry/quaternion_conversion.rs @@ -6,10 +6,12 @@ use alga::linear::Rotation as AlgaRotation; #[cfg(feature = "mint")] use mint; -use base::{Matrix4, Vector4}; use base::dimension::U3; -use geometry::{Isometry, Point3, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf, - TAffine, Transform, Translation, UnitQuaternion}; +use base::{Matrix3, Matrix4, Vector4}; +use geometry::{ + Isometry, Point3, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf, TAffine, + Transform, Translation, UnitQuaternion, +}; /* * This file provides the following conversions: @@ -213,3 +215,17 @@ impl Into> for UnitQuaternion { } } } + +impl From> for Matrix4 { + #[inline] + fn from(q: UnitQuaternion) -> Matrix4 { + q.to_homogeneous() + } +} + +impl From> for Matrix3 { + #[inline] + fn from(q: UnitQuaternion) -> Matrix3 { + q.to_rotation_matrix().unwrap() + } +} diff --git a/src/geometry/rotation_conversion.rs b/src/geometry/rotation_conversion.rs index 5e98fbb8..ecabb71f 100644 --- a/src/geometry/rotation_conversion.rs +++ b/src/geometry/rotation_conversion.rs @@ -6,12 +6,14 @@ use alga::linear::Rotation as AlgaRotation; #[cfg(feature = "mint")] use mint; -use base::{DefaultAllocator, MatrixN}; -use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; use base::allocator::Allocator; +use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; +use base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN}; -use geometry::{Isometry, Point, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, - TAffine, Transform, Translation, UnitComplex, UnitQuaternion}; +use geometry::{ + Isometry, Point, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, TAffine, + Transform, Translation, UnitComplex, UnitQuaternion, +}; /* * This file provides the following conversions: @@ -214,3 +216,31 @@ impl From> for Rotation3 { Self::from_euler_angles(euler.a, euler.b, euler.c) } } + +impl From> for Matrix3 { + #[inline] + fn from(q: Rotation2) -> Matrix3 { + q.to_homogeneous() + } +} + +impl From> for Matrix2 { + #[inline] + fn from(q: Rotation2) -> Matrix2 { + q.unwrap() + } +} + +impl From> for Matrix4 { + #[inline] + fn from(q: Rotation3) -> Matrix4 { + q.to_homogeneous() + } +} + +impl From> for Matrix3 { + #[inline] + fn from(q: Rotation3) -> Matrix3 { + q.unwrap() + } +} diff --git a/src/geometry/similarity_conversion.rs b/src/geometry/similarity_conversion.rs index 2c7a1eac..8da75f38 100644 --- a/src/geometry/similarity_conversion.rs +++ b/src/geometry/similarity_conversion.rs @@ -1,9 +1,9 @@ use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation; -use base::{DefaultAllocator, MatrixN}; -use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; use base::allocator::Allocator; +use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; +use base::{DefaultAllocator, MatrixN}; use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; @@ -103,13 +103,16 @@ where #[inline] fn is_in_subset(m: &MatrixN>) -> bool { let mut rot = m.fixed_slice::(0, 0).clone_owned(); - if rot.fixed_columns_mut::(0) + if rot + .fixed_columns_mut::(0) .try_normalize_mut(N2::zero()) .is_some() - && rot.fixed_columns_mut::(1) + && rot + .fixed_columns_mut::(1) .try_normalize_mut(N2::zero()) .is_some() - && rot.fixed_columns_mut::(2) + && rot + .fixed_columns_mut::(2) .try_normalize_mut(N2::zero()) .is_some() { @@ -157,3 +160,15 @@ where Self::from_parts(t, ::convert_unchecked(mm), ::convert_unchecked(scale)) } } + +impl From> for MatrixN> +where + D: DimNameAdd, + R: SubsetOf>>, + DefaultAllocator: Allocator + Allocator, DimNameSum>, +{ + #[inline] + fn from(sim: Similarity) -> Self { + sim.to_homogeneous() + } +} diff --git a/src/geometry/transform_conversion.rs b/src/geometry/transform_conversion.rs index 1dd02681..0ab96221 100644 --- a/src/geometry/transform_conversion.rs +++ b/src/geometry/transform_conversion.rs @@ -1,8 +1,8 @@ use alga::general::{Real, SubsetOf}; -use base::{DefaultAllocator, MatrixN}; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use base::allocator::Allocator; +use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use base::{DefaultAllocator, MatrixN}; use geometry::{SuperTCategoryOf, TCategory, Transform}; @@ -60,3 +60,15 @@ where Transform::from_matrix_unchecked(::convert_ref_unchecked(m)) } } + +impl From> for MatrixN> +where + D: DimNameAdd, + C: TCategory, + DefaultAllocator: Allocator, DimNameSum>, +{ + #[inline] + fn from(t: Transform) -> Self { + t.to_homogeneous() + } +} diff --git a/src/geometry/translation_conversion.rs b/src/geometry/translation_conversion.rs index c75a401a..0d0b20ea 100644 --- a/src/geometry/translation_conversion.rs +++ b/src/geometry/translation_conversion.rs @@ -1,9 +1,11 @@ +use num::{One, Zero}; + use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation; -use base::{DefaultAllocator, MatrixN, Scalar, VectorN}; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use base::allocator::Allocator; +use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use base::{DefaultAllocator, MatrixN, Scalar, VectorN}; use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; @@ -146,3 +148,14 @@ where Self::from_vector(::convert_unchecked(t.into_owned())) } } + +impl From> for MatrixN> +where + D: DimNameAdd, + DefaultAllocator: Allocator + Allocator, DimNameSum>, +{ + #[inline] + fn from(t: Translation) -> Self { + t.to_homogeneous() + } +} diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index d58e7b82..9e91b1f1 100644 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -173,3 +173,17 @@ impl UlpsEq for UnitComplex { && self.im.ulps_eq(&other.im, epsilon, max_ulps) } } + +impl From> for Matrix3 { + #[inline] + fn from(q: UnitComplex) -> Matrix3 { + q.to_homogeneous() + } +} + +impl From> for Matrix2 { + #[inline] + fn from(q: UnitComplex) -> Matrix2 { + q.to_rotation_matrix().unwrap() + } +} diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 50a2f860..05e98384 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -242,12 +242,8 @@ fn from_rows_with_different_dimensions() { #[test] fn copy_from_slice() { let mut a = Matrix3::zeros(); - let data = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 ]; - let expected_a = Matrix3::new( - 1.0, 4.0, 7.0, - 2.0, 5.0, 8.0, - 3.0, 6.0, 9.0 - ); + let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]; + let expected_a = Matrix3::new(1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0); a.copy_from_slice(&data); @@ -258,7 +254,7 @@ fn copy_from_slice() { #[test] fn copy_from_slice_too_small() { let mut a = Matrix3::zeros(); - let data = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ]; + let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; a.copy_from_slice(&data); } @@ -266,7 +262,7 @@ fn copy_from_slice_too_small() { #[test] fn copy_from_slice_too_large() { let mut a = Matrix3::zeros(); - let data = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 ]; + let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]; a.copy_from_slice(&data); } @@ -727,6 +723,7 @@ fn partial_clamp() { assert_eq!(*inter.unwrap(), n); } +#[test] fn swizzle() { let a = Vector2::new(1.0f32, 2.0); let b = Vector3::new(1.0f32, 2.0, 3.0); @@ -761,7 +758,6 @@ fn swizzle() { assert_eq!(b.zxz(), Vector3::new(3.0, 1.0, 3.0)); assert_eq!(b.zyz(), Vector3::new(3.0, 2.0, 3.0)); - assert_eq!(c.xy(), Vector2::new(1.0, 2.0)); assert_eq!(c.yx(), Vector2::new(2.0, 1.0)); assert_eq!(c.xx(), Vector2::new(1.0, 1.0));