use simba::scalar::{RealField, SubsetOf, SupersetOf}; use simba::simd::{PrimitiveSimdValue, SimdRealField, SimdValue}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimMin, DimNameAdd, DimNameSum, U1}; use crate::base::{Const, DefaultAllocator, OMatrix, Scalar}; use crate::geometry::{ AbstractRotation, Isometry, Isometry3, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, UnitDualQuaternion, UnitQuaternion, }; use crate::{Point, SVector}; /* * This file provides the following conversions: * ============================================= * * Isometry -> Isometry * Isometry3 -> UnitDualQuaternion * Isometry -> Similarity * Isometry -> Transform * Isometry -> Matrix (homogeneous) */ impl SubsetOf> for Isometry where T1: RealField, T2: RealField + SupersetOf, R1: AbstractRotation + SubsetOf, R2: AbstractRotation, { #[inline] fn to_superset(&self) -> Isometry { Isometry::from_parts(self.translation.to_superset(), self.rotation.to_superset()) } #[inline] fn is_in_subset(iso: &Isometry) -> bool { crate::is_convertible::<_, Translation>(&iso.translation) && crate::is_convertible::<_, R1>(&iso.rotation) } #[inline] fn from_superset_unchecked(iso: &Isometry) -> Self { Isometry::from_parts( iso.translation.to_subset_unchecked(), iso.rotation.to_subset_unchecked(), ) } } impl SubsetOf> for Isometry3 where T1: RealField, T2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitDualQuaternion { let dq = UnitDualQuaternion::::from_isometry(self); dq.to_superset() } #[inline] fn is_in_subset(dq: &UnitDualQuaternion) -> bool { crate::is_convertible::<_, UnitQuaternion>(&dq.rotation()) && crate::is_convertible::<_, Translation>(&dq.translation()) } #[inline] fn from_superset_unchecked(dq: &UnitDualQuaternion) -> Self { let dq: UnitDualQuaternion = crate::convert_ref_unchecked(dq); dq.to_isometry() } } impl SubsetOf> for Isometry where T1: RealField, T2: RealField + SupersetOf, R1: AbstractRotation + SubsetOf, R2: AbstractRotation, { #[inline] fn to_superset(&self) -> Similarity { Similarity::from_isometry(self.to_superset(), T2::one()) } #[inline] fn is_in_subset(sim: &Similarity) -> bool { crate::is_convertible::<_, Isometry>(&sim.isometry) && sim.scaling() == T2::one() } #[inline] fn from_superset_unchecked(sim: &Similarity) -> Self { crate::convert_ref_unchecked(&sim.isometry) } } impl SubsetOf> for Isometry where T1: RealField, T2: RealField + SupersetOf, C: SuperTCategoryOf, R: AbstractRotation + SubsetOf, U1>, DimNameSum, U1>>> + SubsetOf, U1>, DimNameSum, U1>>>, Const: DimNameAdd + DimMin, Output = Const>, // needed by .is_special_orthogonal() DefaultAllocator: Allocator, U1>, DimNameSum, U1>> + Allocator, U1>, DimNameSum, U1>> + Allocator, U1>, DimNameSum, U1>>, // + Allocator // + Allocator<(usize, usize), D> // + Allocator // + Allocator { #[inline] fn to_superset(&self) -> Transform { Transform::from_matrix_unchecked(self.to_homogeneous().to_superset()) } #[inline] fn is_in_subset(t: &Transform) -> bool { >::is_in_subset(t.matrix()) } #[inline] fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } impl SubsetOf, U1>, DimNameSum, U1>>> for Isometry where T1: RealField, T2: RealField + SupersetOf, R: AbstractRotation + SubsetOf, U1>, DimNameSum, U1>>> + SubsetOf, U1>, DimNameSum, U1>>>, Const: DimNameAdd + DimMin, Output = Const>, // needed by .is_special_orthogonal() DefaultAllocator: Allocator, U1>, DimNameSum, U1>> + Allocator, U1>, DimNameSum, U1>> + Allocator, U1>, DimNameSum, U1>>, // + Allocator<(usize, usize), D> // + Allocator // + Allocator // + Allocator // + Allocator { #[inline] fn to_superset(&self) -> OMatrix, U1>, DimNameSum, U1>> { self.to_homogeneous().to_superset() } #[inline] fn is_in_subset(m: &OMatrix, U1>, DimNameSum, U1>>) -> bool { let rot = m.fixed_slice::(0, 0); let bottom = m.fixed_slice::<1, D>(D, 0); // Scalar types agree. m.iter().all(|e| SupersetOf::::is_in_subset(e)) && // The block part is a rotation. rot.is_special_orthogonal(T2::default_epsilon() * crate::convert(100.0)) && // The bottom row is (0, 0, ..., 1) bottom.iter().all(|e| e.is_zero()) && m[(D, D)] == T2::one() } #[inline] fn from_superset_unchecked( m: &OMatrix, U1>, DimNameSum, U1>>, ) -> Self { let t = m.fixed_slice::(0, D).into_owned(); let t = Translation { vector: crate::convert_unchecked(t), }; Self::from_parts(t, crate::convert_unchecked(m.clone_owned())) } } impl, const D: usize> From> for Isometry { #[inline] fn from(tra: Translation) -> Self { Self::from_parts(tra, R::identity()) } } impl From> for OMatrix, U1>, DimNameSum, U1>> where Const: DimNameAdd, R: SubsetOf, U1>, DimNameSum, U1>>>, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, // + Allocator, { #[inline] fn from(iso: Isometry) -> Self { iso.to_homogeneous() } } impl From<[T; D]> for Isometry where R: AbstractRotation, { #[inline] fn from(coords: [T; D]) -> Self { Self::from_parts(coords.into(), R::identity()) } } impl From> for Isometry where R: AbstractRotation, { #[inline] fn from(coords: SVector) -> Self { Self::from_parts(coords.into(), R::identity()) } } impl From> for Isometry where R: AbstractRotation, { #[inline] fn from(coords: Point) -> Self { Self::from_parts(coords.into(), R::identity()) } } impl From<[Isometry; 2]> for Isometry where T: From<[::Element; 2]>, R: SimdValue + AbstractRotation + From<[::Element; 2]>, R::Element: AbstractRotation, T::Element: Scalar + Copy, R::Element: Scalar + Copy, { #[inline] fn from(arr: [Isometry; 2]) -> Self { let tra = Translation::from([arr[0].translation, arr[1].translation]); let rot = R::from([arr[0].rotation, arr[0].rotation]); Self::from_parts(tra, rot) } } impl From<[Isometry; 4]> for Isometry where T: From<[::Element; 4]>, R: SimdValue + AbstractRotation + From<[::Element; 4]>, R::Element: AbstractRotation, T::Element: Scalar + Copy, R::Element: Scalar + Copy, { #[inline] fn from(arr: [Isometry; 4]) -> Self { let tra = Translation::from([ arr[0].translation, arr[1].translation, arr[2].translation, arr[3].translation, ]); let rot = R::from([ arr[0].rotation, arr[1].rotation, arr[2].rotation, arr[3].rotation, ]); Self::from_parts(tra, rot) } } impl From<[Isometry; 8]> for Isometry where T: From<[::Element; 8]>, R: SimdValue + AbstractRotation + From<[::Element; 8]>, R::Element: AbstractRotation, T::Element: Scalar + Copy, R::Element: Scalar + Copy, { #[inline] fn from(arr: [Isometry; 8]) -> Self { let tra = Translation::from([ arr[0].translation, arr[1].translation, arr[2].translation, arr[3].translation, arr[4].translation, arr[5].translation, arr[6].translation, arr[7].translation, ]); let rot = R::from([ arr[0].rotation, arr[1].rotation, arr[2].rotation, arr[3].rotation, arr[4].rotation, arr[5].rotation, arr[6].rotation, arr[7].rotation, ]); Self::from_parts(tra, rot) } } impl From<[Isometry; 16]> for Isometry where T: From<[::Element; 16]>, R: SimdValue + AbstractRotation + From<[::Element; 16]>, R::Element: AbstractRotation, T::Element: Scalar + Copy, R::Element: Scalar + Copy, { #[inline] fn from(arr: [Isometry; 16]) -> Self { let tra = Translation::from([ arr[0].translation, arr[1].translation, arr[2].translation, arr[3].translation, arr[4].translation, arr[5].translation, arr[6].translation, arr[7].translation, arr[8].translation, arr[9].translation, arr[10].translation, arr[11].translation, arr[12].translation, arr[13].translation, arr[14].translation, arr[15].translation, ]); let rot = R::from([ arr[0].rotation, arr[1].rotation, arr[2].rotation, arr[3].rotation, arr[4].rotation, arr[5].rotation, arr[6].rotation, arr[7].rotation, arr[8].rotation, arr[9].rotation, arr[10].rotation, arr[11].rotation, arr[12].rotation, arr[13].rotation, arr[14].rotation, arr[15].rotation, ]); Self::from_parts(tra, rot) } }