nalgebra/geometry/
dual_quaternion_conversion.rs

1use simba::scalar::{RealField, SubsetOf, SupersetOf};
2use simba::simd::SimdRealField;
3
4use crate::base::{Matrix4, Vector4};
5use crate::geometry::{
6    DualQuaternion, Isometry3, Similarity3, SuperTCategoryOf, TAffine, Transform, Translation3,
7    UnitDualQuaternion, UnitQuaternion,
8};
9
10/*
11 * This file provides the following conversions:
12 * =============================================
13 *
14 * DualQuaternion     -> DualQuaternion
15 * UnitDualQuaternion -> UnitDualQuaternion
16 * UnitDualQuaternion -> Isometry<3>
17 * UnitDualQuaternion -> Similarity<3>
18 * UnitDualQuaternion -> Transform<3>
19 * UnitDualQuaternion -> Matrix<U4> (homogeneous)
20 *
21 * NOTE:
22 * UnitDualQuaternion -> DualQuaternion is already provided by: Unit<T> -> T
23 */
24
25impl<T1, T2> SubsetOf<DualQuaternion<T2>> for DualQuaternion<T1>
26where
27    T1: SimdRealField,
28    T2: SimdRealField + SupersetOf<T1>,
29{
30    #[inline]
31    fn to_superset(&self) -> DualQuaternion<T2> {
32        DualQuaternion::from_real_and_dual(self.real.to_superset(), self.dual.to_superset())
33    }
34
35    #[inline]
36    fn is_in_subset(dq: &DualQuaternion<T2>) -> bool {
37        crate::is_convertible::<_, Vector4<T1>>(&dq.real.coords)
38            && crate::is_convertible::<_, Vector4<T1>>(&dq.dual.coords)
39    }
40
41    #[inline]
42    fn from_superset_unchecked(dq: &DualQuaternion<T2>) -> Self {
43        DualQuaternion::from_real_and_dual(
44            dq.real.to_subset_unchecked(),
45            dq.dual.to_subset_unchecked(),
46        )
47    }
48}
49
50impl<T1, T2> SubsetOf<UnitDualQuaternion<T2>> for UnitDualQuaternion<T1>
51where
52    T1: SimdRealField,
53    T2: SimdRealField + SupersetOf<T1>,
54{
55    #[inline]
56    fn to_superset(&self) -> UnitDualQuaternion<T2> {
57        UnitDualQuaternion::new_unchecked(self.as_ref().to_superset())
58    }
59
60    #[inline]
61    fn is_in_subset(dq: &UnitDualQuaternion<T2>) -> bool {
62        crate::is_convertible::<_, DualQuaternion<T1>>(dq.as_ref())
63    }
64
65    #[inline]
66    fn from_superset_unchecked(dq: &UnitDualQuaternion<T2>) -> Self {
67        Self::new_unchecked(crate::convert_ref_unchecked(dq.as_ref()))
68    }
69}
70
71impl<T1, T2> SubsetOf<Isometry3<T2>> for UnitDualQuaternion<T1>
72where
73    T1: RealField,
74    T2: RealField + SupersetOf<T1>,
75{
76    #[inline]
77    fn to_superset(&self) -> Isometry3<T2> {
78        let dq: UnitDualQuaternion<T2> = self.to_superset();
79        let iso = dq.to_isometry();
80        crate::convert_unchecked(iso)
81    }
82
83    #[inline]
84    fn is_in_subset(iso: &Isometry3<T2>) -> bool {
85        crate::is_convertible::<_, UnitQuaternion<T1>>(&iso.rotation)
86            && crate::is_convertible::<_, Translation3<T1>>(&iso.translation)
87    }
88
89    #[inline]
90    fn from_superset_unchecked(iso: &Isometry3<T2>) -> Self {
91        let dq = UnitDualQuaternion::<T2>::from_isometry(iso);
92        crate::convert_unchecked(dq)
93    }
94}
95
96impl<T1, T2> SubsetOf<Similarity3<T2>> for UnitDualQuaternion<T1>
97where
98    T1: RealField,
99    T2: RealField + SupersetOf<T1>,
100{
101    #[inline]
102    fn to_superset(&self) -> Similarity3<T2> {
103        Similarity3::from_isometry(crate::convert_ref(self), T2::one())
104    }
105
106    #[inline]
107    fn is_in_subset(sim: &Similarity3<T2>) -> bool {
108        sim.scaling() == T2::one()
109    }
110
111    #[inline]
112    fn from_superset_unchecked(sim: &Similarity3<T2>) -> Self {
113        crate::convert_ref_unchecked(&sim.isometry)
114    }
115}
116
117impl<T1, T2, C> SubsetOf<Transform<T2, C, 3>> for UnitDualQuaternion<T1>
118where
119    T1: RealField,
120    T2: RealField + SupersetOf<T1>,
121    C: SuperTCategoryOf<TAffine>,
122{
123    #[inline]
124    fn to_superset(&self) -> Transform<T2, C, 3> {
125        Transform::from_matrix_unchecked(self.clone().to_homogeneous().to_superset())
126    }
127
128    #[inline]
129    fn is_in_subset(t: &Transform<T2, C, 3>) -> bool {
130        <Self as SubsetOf<_>>::is_in_subset(t.matrix())
131    }
132
133    #[inline]
134    fn from_superset_unchecked(t: &Transform<T2, C, 3>) -> Self {
135        Self::from_superset_unchecked(t.matrix())
136    }
137}
138
139impl<T1: RealField, T2: RealField + SupersetOf<T1>> SubsetOf<Matrix4<T2>>
140    for UnitDualQuaternion<T1>
141{
142    #[inline]
143    fn to_superset(&self) -> Matrix4<T2> {
144        self.clone().to_homogeneous().to_superset()
145    }
146
147    #[inline]
148    fn is_in_subset(m: &Matrix4<T2>) -> bool {
149        crate::is_convertible::<_, Isometry3<T1>>(m)
150    }
151
152    #[inline]
153    fn from_superset_unchecked(m: &Matrix4<T2>) -> Self {
154        let iso: Isometry3<T1> = crate::convert_ref_unchecked(m);
155        Self::from_isometry(&iso)
156    }
157}
158
159impl<T: SimdRealField + RealField> From<UnitDualQuaternion<T>> for Matrix4<T>
160where
161    T::Element: SimdRealField,
162{
163    #[inline]
164    fn from(dq: UnitDualQuaternion<T>) -> Self {
165        dq.to_homogeneous()
166    }
167}
168
169impl<T: SimdRealField> From<UnitDualQuaternion<T>> for Isometry3<T>
170where
171    T::Element: SimdRealField,
172{
173    #[inline]
174    fn from(dq: UnitDualQuaternion<T>) -> Self {
175        dq.to_isometry()
176    }
177}
178
179impl<T: SimdRealField> From<Isometry3<T>> for UnitDualQuaternion<T>
180where
181    T::Element: SimdRealField,
182{
183    #[inline]
184    fn from(iso: Isometry3<T>) -> Self {
185        Self::from_isometry(&iso)
186    }
187}