use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation; use core::{SquareMatrix, OwnedSquareMatrix}; use core::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use core::storage::OwnedStorage; use core::allocator::{Allocator, OwnedAllocator}; use geometry::{PointBase, TranslationBase, IsometryBase, SimilarityBase, TransformBase, SuperTCategoryOf, TAffine}; /* * This file provides the following conversions: * ============================================= * * SimilarityBase -> SimilarityBase * SimilarityBase -> TransformBase * SimilarityBase -> Matrix (homogeneous) */ impl SubsetOf> for SimilarityBase where N1: Real + SubsetOf, N2: Real + SupersetOf, R1: Rotation> + SubsetOf, R2: Rotation>, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { #[inline] fn to_superset(&self) -> SimilarityBase { SimilarityBase::from_isometry( self.isometry.to_superset(), self.scaling().to_superset() ) } #[inline] fn is_in_subset(sim: &SimilarityBase) -> bool { ::is_convertible::<_, IsometryBase>(&sim.isometry) && ::is_convertible::<_, N1>(&sim.scaling()) } #[inline] unsafe fn from_superset_unchecked(sim: &SimilarityBase) -> Self { SimilarityBase::from_isometry( sim.isometry.to_subset_unchecked(), sim.scaling().to_subset_unchecked() ) } } impl SubsetOf> for SimilarityBase where N1: Real, N2: Real + SupersetOf, SA: OwnedStorage, SB: OwnedStorage, DimNameSum>, C: SuperTCategoryOf, R: Rotation> + SubsetOf, SA::Alloc>> + // needed by: .to_homogeneous() SubsetOf, SB>>, // needed by: ::convert_unchecked(mm) D: DimNameAdd, SA::Alloc: OwnedAllocator + Allocator + // needed by R Allocator, DimNameSum> + // needed by: .to_homogeneous() Allocator, DimNameSum>, // needed by R SB::Alloc: OwnedAllocator, DimNameSum, SB> + Allocator + // needed by: mm.fixed_slice_mut Allocator + // needed by: m.fixed_slice Allocator { // needed by: m.fixed_slice #[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 SimilarityBase where N1: Real, N2: Real + SupersetOf, SA: OwnedStorage, SB: OwnedStorage, DimNameSum>, R: Rotation> + SubsetOf, SA::Alloc>> + // needed by: .to_homogeneous() SubsetOf, SB>>, // needed by: ::convert_unchecked(mm) D: DimNameAdd, SA::Alloc: OwnedAllocator + Allocator + // needed by R Allocator, DimNameSum> + // needed by: .to_homogeneous() Allocator, DimNameSum>, // needed by R SB::Alloc: OwnedAllocator, DimNameSum, SB> + Allocator + // needed by: mm.fixed_slice_mut Allocator + // needed by: m.fixed_slice Allocator { // needed by: m.fixed_slice #[inline] fn to_superset(&self) -> SquareMatrix, SB> { self.to_homogeneous().to_superset() } #[inline] fn is_in_subset(m: &SquareMatrix, SB>) -> bool { let mut rot = m.fixed_slice::(0, 0).clone_owned(); if rot.fixed_columns_mut::(0).try_normalize_mut(N2::zero()).is_some() && rot.fixed_columns_mut::(1).try_normalize_mut(N2::zero()).is_some() && rot.fixed_columns_mut::(2).try_normalize_mut(N2::zero()).is_some() { // FIXME: could we avoid explicit the computation of the determinant? // (its sign is needed to see if the scaling factor is negative). if rot.determinant() < N2::zero() { rot.fixed_columns_mut::(0).neg_mut(); rot.fixed_columns_mut::(1).neg_mut(); rot.fixed_columns_mut::(2).neg_mut(); } let bottom = m.fixed_slice::(D::dim(), 0); // Scalar types agree. m.iter().all(|e| SupersetOf::::is_in_subset(e)) && // The normalized block part is a rotation. // rot.is_special_orthogonal(N2::default_epsilon().sqrt()) && // The bottom row is (0, 0, ..., 1) bottom.iter().all(|e| e.is_zero()) && m[(D::dim(), D::dim())] == N2::one() } else { false } } #[inline] unsafe fn from_superset_unchecked(m: &SquareMatrix, SB>) -> Self { let mut mm = m.clone_owned(); let na = mm.fixed_slice_mut::(0, 0).normalize_mut(); let nb = mm.fixed_slice_mut::(0, 1).normalize_mut(); let nc = mm.fixed_slice_mut::(0, 2).normalize_mut(); let mut scale = (na + nb + nc) / ::convert(3.0); // We take the mean, for robustness. // FIXME: could we avoid the explicit computation of the determinant? // (its sign is needed to see if the scaling factor is negative). if mm.fixed_slice::(0, 0).determinant() < N2::zero() { mm.fixed_slice_mut::(0, 0).neg_mut(); mm.fixed_slice_mut::(0, 1).neg_mut(); mm.fixed_slice_mut::(0, 2).neg_mut(); scale = -scale; } let t = m.fixed_slice::(0, D::dim()).into_owned(); let t = TranslationBase::from_vector(::convert_unchecked(t)); Self::from_parts(t, ::convert_unchecked(mm), ::convert_unchecked(scale)) } }