use num::Zero; use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation as AlgaRotation; use core::{Matrix, SquareMatrix}; use core::dimension::{DimName, DimNameSum, DimNameAdd, U1, U3, U4}; use core::storage::OwnedStorage; use core::allocator::{OwnedAllocator, Allocator}; use geometry::{PointBase, TranslationBase, RotationBase, UnitQuaternionBase, OwnedUnitQuaternionBase, IsometryBase, SimilarityBase, TransformBase, SuperTCategoryOf, TAffine}; /* * This file provides the following conversions: * ============================================= * * RotationBase -> RotationBase * Rotation3 -> UnitQuaternion * RotationBase -> IsometryBase * RotationBase -> SimilarityBase * RotationBase -> TransformBase * RotationBase -> Matrix (homogeneous) */ impl SubsetOf> for RotationBase where N1: Real, N2: Real + SupersetOf, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { #[inline] fn to_superset(&self) -> RotationBase { RotationBase::from_matrix_unchecked(self.matrix().to_superset()) } #[inline] fn is_in_subset(rot: &RotationBase) -> bool { ::is_convertible::<_, Matrix>(rot.matrix()) } #[inline] unsafe fn from_superset_unchecked(rot: &RotationBase) -> Self { RotationBase::from_matrix_unchecked(rot.matrix().to_subset_unchecked()) } } impl SubsetOf> for RotationBase where N1: Real, N2: Real + SupersetOf, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator + Allocator + Allocator, SB::Alloc: OwnedAllocator + Allocator { #[inline] fn to_superset(&self) -> UnitQuaternionBase { let q = OwnedUnitQuaternionBase::::from_rotation_matrix(self); q.to_superset() } #[inline] fn is_in_subset(q: &UnitQuaternionBase) -> bool { ::is_convertible::<_, OwnedUnitQuaternionBase>(q) } #[inline] unsafe fn from_superset_unchecked(q: &UnitQuaternionBase) -> Self { let q: OwnedUnitQuaternionBase = ::convert_ref_unchecked(q); q.to_rotation_matrix() } } impl SubsetOf> for RotationBase where N1: Real, N2: Real + SupersetOf, SA: OwnedStorage, SB: OwnedStorage, R: AlgaRotation> + SupersetOf>, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { #[inline] fn to_superset(&self) -> IsometryBase { IsometryBase::from_parts(TranslationBase::identity(), ::convert_ref(self)) } #[inline] fn is_in_subset(iso: &IsometryBase) -> bool { iso.translation.vector.is_zero() } #[inline] unsafe fn from_superset_unchecked(iso: &IsometryBase) -> Self { ::convert_ref_unchecked(&iso.rotation) } } impl SubsetOf> for RotationBase where N1: Real, N2: Real + SupersetOf, SA: OwnedStorage, SB: OwnedStorage, R: AlgaRotation> + SupersetOf>, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { #[inline] fn to_superset(&self) -> SimilarityBase { SimilarityBase::from_parts(TranslationBase::identity(), ::convert_ref(self), N2::one()) } #[inline] fn is_in_subset(sim: &SimilarityBase) -> bool { sim.isometry.translation.vector.is_zero() && sim.scaling() == N2::one() } #[inline] unsafe fn from_superset_unchecked(sim: &SimilarityBase) -> Self { ::convert_ref_unchecked(&sim.isometry.rotation) } } impl SubsetOf> for RotationBase where N1: Real, N2: Real + SupersetOf, SA: OwnedStorage, SB: OwnedStorage, DimNameSum>, C: SuperTCategoryOf, D: DimNameAdd, SA::Alloc: OwnedAllocator + Allocator, DimNameSum>, SB::Alloc: OwnedAllocator, DimNameSum, SB> + Allocator + Allocator { #[inline] fn to_superset(&self) -> TransformBase { TransformBase::from_matrix_unchecked(self.to_homogeneous().to_superset()) } #[inline] fn is_in_subset(t: &TransformBase) -> bool { >::is_in_subset(t.matrix()) } #[inline] unsafe fn from_superset_unchecked(t: &TransformBase) -> Self { Self::from_superset_unchecked(t.matrix()) } } impl SubsetOf, SB>> for RotationBase where N1: Real, N2: Real + SupersetOf, SA: OwnedStorage, SB: OwnedStorage, DimNameSum>, D: DimNameAdd, SA::Alloc: OwnedAllocator + Allocator, DimNameSum>, SB::Alloc: OwnedAllocator, DimNameSum, SB> + Allocator + Allocator { #[inline] fn to_superset(&self) -> SquareMatrix, SB> { self.to_homogeneous().to_superset() } #[inline] fn is_in_subset(m: &SquareMatrix, SB>) -> bool { let rot = m.fixed_slice::(0, 0); let bottom = m.fixed_slice::(D::dim(), 0); // Scalar types agree. m.iter().all(|e| SupersetOf::::is_in_subset(e)) && // The block part is a rotation. rot.is_special_orthogonal(N2::default_epsilon() * ::convert(100.0)) && // The bottom row is (0, 0, ..., 1) bottom.iter().all(|e| e.is_zero()) && m[(D::dim(), D::dim())] == N2::one() } #[inline] unsafe fn from_superset_unchecked(m: &SquareMatrix, SB>) -> Self { let r = m.fixed_slice::(0, 0); Self::from_matrix_unchecked(::convert_unchecked(r.into_owned())) } }