use num::Zero; use simba::scalar::{RealField, SubsetOf, SupersetOf}; use simba::simd::{PrimitiveSimdValue, SimdValue}; #[cfg(feature = "mint")] use mint; use crate::base::allocator::Allocator; use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN, Scalar}; use crate::geometry::{ AbstractRotation, Isometry, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, UnitComplex, UnitQuaternion, UnitDualQuaternion, }; /* * This file provides the following conversions: * ============================================= * * Rotation -> Rotation * Rotation3 -> UnitQuaternion * Rotation3 -> UnitDualQuaternion * Rotation2 -> UnitComplex * Rotation -> Isometry * Rotation -> Similarity * Rotation -> Transform * Rotation -> Matrix (homogeneous) * mint::EulerAngles -> Rotation */ impl SubsetOf> for Rotation where N1: RealField, N2: RealField + SupersetOf, DefaultAllocator: Allocator + Allocator, { #[inline] fn to_superset(&self) -> Rotation { Rotation::from_matrix_unchecked(self.matrix().to_superset()) } #[inline] fn is_in_subset(rot: &Rotation) -> bool { crate::is_convertible::<_, MatrixN>(rot.matrix()) } #[inline] fn from_superset_unchecked(rot: &Rotation) -> Self { Rotation::from_matrix_unchecked(rot.matrix().to_subset_unchecked()) } } impl SubsetOf> for Rotation3 where N1: RealField, N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitQuaternion { let q = UnitQuaternion::::from_rotation_matrix(self); q.to_superset() } #[inline] fn is_in_subset(q: &UnitQuaternion) -> bool { crate::is_convertible::<_, UnitQuaternion>(q) } #[inline] fn from_superset_unchecked(q: &UnitQuaternion) -> Self { let q: UnitQuaternion = crate::convert_ref_unchecked(q); q.to_rotation_matrix() } } impl SubsetOf> for Rotation3 where N1: RealField, N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitDualQuaternion { let q = UnitQuaternion::::from_rotation_matrix(self); let dq = UnitDualQuaternion::from_rotation(q); dq.to_superset() } #[inline] fn is_in_subset(dq: &UnitDualQuaternion) -> bool { crate::is_convertible::<_, UnitQuaternion>(&dq.rotation()) && dq.translation().vector.is_zero() } #[inline] fn from_superset_unchecked(dq: &UnitDualQuaternion) -> Self { let dq: UnitDualQuaternion = crate::convert_ref_unchecked(dq); dq.rotation().to_rotation_matrix() } } impl SubsetOf> for Rotation2 where N1: RealField, N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitComplex { let q = UnitComplex::::from_rotation_matrix(self); q.to_superset() } #[inline] fn is_in_subset(q: &UnitComplex) -> bool { crate::is_convertible::<_, UnitComplex>(q) } #[inline] fn from_superset_unchecked(q: &UnitComplex) -> Self { let q: UnitComplex = crate::convert_ref_unchecked(q); q.to_rotation_matrix() } } impl SubsetOf> for Rotation where N1: RealField, N2: RealField + SupersetOf, R: AbstractRotation + SupersetOf, DefaultAllocator: Allocator + Allocator, { #[inline] fn to_superset(&self) -> Isometry { Isometry::from_parts(Translation::identity(), crate::convert_ref(self)) } #[inline] fn is_in_subset(iso: &Isometry) -> bool { iso.translation.vector.is_zero() } #[inline] fn from_superset_unchecked(iso: &Isometry) -> Self { crate::convert_ref_unchecked(&iso.rotation) } } impl SubsetOf> for Rotation where N1: RealField, N2: RealField + SupersetOf, R: AbstractRotation + SupersetOf, DefaultAllocator: Allocator + Allocator, { #[inline] fn to_superset(&self) -> Similarity { Similarity::from_parts(Translation::identity(), crate::convert_ref(self), N2::one()) } #[inline] fn is_in_subset(sim: &Similarity) -> bool { sim.isometry.translation.vector.is_zero() && sim.scaling() == N2::one() } #[inline] fn from_superset_unchecked(sim: &Similarity) -> Self { crate::convert_ref_unchecked(&sim.isometry.rotation) } } impl SubsetOf> for Rotation where N1: RealField, N2: RealField + SupersetOf, C: SuperTCategoryOf, D: DimNameAdd + DimMin, // needed by .is_special_orthogonal() DefaultAllocator: Allocator + Allocator + Allocator, DimNameSum> + Allocator, DimNameSum> + Allocator<(usize, usize), D>, { // needed by .is_special_orthogonal() #[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>> for Rotation where N1: RealField, N2: RealField + SupersetOf, D: DimNameAdd + DimMin, // needed by .is_special_orthogonal() DefaultAllocator: Allocator + Allocator + Allocator, DimNameSum> + Allocator, DimNameSum> + Allocator<(usize, usize), D>, { // needed by .is_special_orthogonal() #[inline] fn to_superset(&self) -> MatrixN> { self.to_homogeneous().to_superset() } #[inline] fn is_in_subset(m: &MatrixN>) -> 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() * crate::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] fn from_superset_unchecked(m: &MatrixN>) -> Self { let r = m.fixed_slice::(0, 0); Self::from_matrix_unchecked(crate::convert_unchecked(r.into_owned())) } } #[cfg(feature = "mint")] impl From> for Rotation3 { fn from(euler: mint::EulerAngles) -> Self { Self::from_euler_angles(euler.a, euler.b, euler.c) } } impl From> for Matrix3 { #[inline] fn from(q: Rotation2) -> Self { q.to_homogeneous() } } impl From> for Matrix2 { #[inline] fn from(q: Rotation2) -> Self { q.into_inner() } } impl From> for Matrix4 { #[inline] fn from(q: Rotation3) -> Self { q.to_homogeneous() } } impl From> for Matrix3 { #[inline] fn from(q: Rotation3) -> Self { q.into_inner() } } impl From<[Rotation; 2]> for Rotation where N: From<[::Element; 2]>, N::Element: Scalar + Copy, DefaultAllocator: Allocator + Allocator, { #[inline] fn from(arr: [Rotation; 2]) -> Self { Self::from_matrix_unchecked(MatrixN::from([ arr[0].clone().into_inner(), arr[1].clone().into_inner(), ])) } } impl From<[Rotation; 4]> for Rotation where N: From<[::Element; 4]>, N::Element: Scalar + Copy, DefaultAllocator: Allocator + Allocator, { #[inline] fn from(arr: [Rotation; 4]) -> Self { Self::from_matrix_unchecked(MatrixN::from([ arr[0].clone().into_inner(), arr[1].clone().into_inner(), arr[2].clone().into_inner(), arr[3].clone().into_inner(), ])) } } impl From<[Rotation; 8]> for Rotation where N: From<[::Element; 8]>, N::Element: Scalar + Copy, DefaultAllocator: Allocator + Allocator, { #[inline] fn from(arr: [Rotation; 8]) -> Self { Self::from_matrix_unchecked(MatrixN::from([ arr[0].clone().into_inner(), arr[1].clone().into_inner(), arr[2].clone().into_inner(), arr[3].clone().into_inner(), arr[4].clone().into_inner(), arr[5].clone().into_inner(), arr[6].clone().into_inner(), arr[7].clone().into_inner(), ])) } } impl From<[Rotation; 16]> for Rotation where N: From<[::Element; 16]>, N::Element: Scalar + Copy, DefaultAllocator: Allocator + Allocator, { #[inline] fn from(arr: [Rotation; 16]) -> Self { Self::from_matrix_unchecked(MatrixN::from([ arr[0].clone().into_inner(), arr[1].clone().into_inner(), arr[2].clone().into_inner(), arr[3].clone().into_inner(), arr[4].clone().into_inner(), arr[5].clone().into_inner(), arr[6].clone().into_inner(), arr[7].clone().into_inner(), arr[8].clone().into_inner(), arr[9].clone().into_inner(), arr[10].clone().into_inner(), arr[11].clone().into_inner(), arr[12].clone().into_inner(), arr[13].clone().into_inner(), arr[14].clone().into_inner(), arr[15].clone().into_inner(), ])) } }