1use simba::scalar::{RealField, SubsetOf, SupersetOf};
2use simba::simd::{PrimitiveSimdValue, SimdRealField, SimdValue};
3
4use crate::base::allocator::Allocator;
5use crate::base::dimension::{DimMin, DimNameAdd, DimNameSum, U1};
6use crate::base::{Const, DefaultAllocator, OMatrix, Scalar};
7
8use crate::geometry::{
9 AbstractRotation, Isometry, Isometry3, Similarity, SuperTCategoryOf, TAffine, Transform,
10 Translation, UnitDualQuaternion, UnitQuaternion,
11};
12use crate::{ArrayStorage, Point, SVector};
13
14impl<T1, T2, R1, R2, const D: usize> SubsetOf<Isometry<T2, R2, D>> for Isometry<T1, R1, D>
26where
27 T1: RealField,
28 T2: RealField + SupersetOf<T1>,
29 R1: AbstractRotation<T1, D> + SubsetOf<R2>,
30 R2: AbstractRotation<T2, D>,
31{
32 #[inline]
33 fn to_superset(&self) -> Isometry<T2, R2, D> {
34 Isometry::from_parts(self.translation.to_superset(), self.rotation.to_superset())
35 }
36
37 #[inline]
38 fn is_in_subset(iso: &Isometry<T2, R2, D>) -> bool {
39 crate::is_convertible::<_, Translation<T1, D>>(&iso.translation)
40 && crate::is_convertible::<_, R1>(&iso.rotation)
41 }
42
43 #[inline]
44 fn from_superset_unchecked(iso: &Isometry<T2, R2, D>) -> Self {
45 Isometry::from_parts(
46 iso.translation.to_subset_unchecked(),
47 iso.rotation.to_subset_unchecked(),
48 )
49 }
50}
51
52impl<T1, T2> SubsetOf<UnitDualQuaternion<T2>> for Isometry3<T1>
53where
54 T1: RealField,
55 T2: RealField + SupersetOf<T1>,
56{
57 #[inline]
58 fn to_superset(&self) -> UnitDualQuaternion<T2> {
59 let dq = UnitDualQuaternion::<T1>::from_isometry(self);
60 dq.to_superset()
61 }
62
63 #[inline]
64 fn is_in_subset(dq: &UnitDualQuaternion<T2>) -> bool {
65 crate::is_convertible::<_, UnitQuaternion<T1>>(&dq.rotation())
66 && crate::is_convertible::<_, Translation<T1, 3>>(&dq.translation())
67 }
68
69 #[inline]
70 fn from_superset_unchecked(dq: &UnitDualQuaternion<T2>) -> Self {
71 let dq: UnitDualQuaternion<T1> = crate::convert_ref_unchecked(dq);
72 dq.to_isometry()
73 }
74}
75
76impl<T1, T2, R1, R2, const D: usize> SubsetOf<Similarity<T2, R2, D>> for Isometry<T1, R1, D>
77where
78 T1: RealField,
79 T2: RealField + SupersetOf<T1>,
80 R1: AbstractRotation<T1, D> + SubsetOf<R2>,
81 R2: AbstractRotation<T2, D>,
82{
83 #[inline]
84 fn to_superset(&self) -> Similarity<T2, R2, D> {
85 Similarity::from_isometry(self.to_superset(), T2::one())
86 }
87
88 #[inline]
89 fn is_in_subset(sim: &Similarity<T2, R2, D>) -> bool {
90 crate::is_convertible::<_, Isometry<T1, R1, D>>(&sim.isometry) && sim.scaling() == T2::one()
91 }
92
93 #[inline]
94 fn from_superset_unchecked(sim: &Similarity<T2, R2, D>) -> Self {
95 crate::convert_ref_unchecked(&sim.isometry)
96 }
97}
98
99impl<T1, T2, R, C, const D: usize> SubsetOf<Transform<T2, C, D>> for Isometry<T1, R, D>
100where
101 T1: RealField,
102 T2: RealField + SupersetOf<T1>,
103 C: SuperTCategoryOf<TAffine>,
104 R: AbstractRotation<T1, D>
105 + SubsetOf<OMatrix<T1, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>>
106 + SubsetOf<OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>>,
107 Const<D>: DimNameAdd<U1> + DimMin<Const<D>, Output = Const<D>>, DefaultAllocator: Allocator<DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
109 {
114 #[inline]
115 fn to_superset(&self) -> Transform<T2, C, D> {
116 Transform::from_matrix_unchecked(self.to_homogeneous().to_superset())
117 }
118
119 #[inline]
120 fn is_in_subset(t: &Transform<T2, C, D>) -> bool {
121 <Self as SubsetOf<_>>::is_in_subset(t.matrix())
122 }
123
124 #[inline]
125 fn from_superset_unchecked(t: &Transform<T2, C, D>) -> Self {
126 Self::from_superset_unchecked(t.matrix())
127 }
128}
129
130impl<T1, T2, R, const D: usize>
131 SubsetOf<OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>> for Isometry<T1, R, D>
132where
133 T1: RealField,
134 T2: RealField + SupersetOf<T1>,
135 R: AbstractRotation<T1, D>
136 + SubsetOf<OMatrix<T1, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>>
137 + SubsetOf<OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>>,
138 Const<D>: DimNameAdd<U1> + DimMin<Const<D>, Output = Const<D>>, DefaultAllocator: Allocator<Const<D>, Const<1>, Buffer<T1> = ArrayStorage<T1, D, 1>>
140 + Allocator<DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
141{
142 #[inline]
143 fn to_superset(&self) -> OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>> {
144 self.to_homogeneous().to_superset()
145 }
146
147 #[inline]
148 fn is_in_subset(m: &OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>) -> bool {
149 let rot = m.fixed_view::<D, D>(0, 0);
150 let bottom = m.fixed_view::<1, D>(D, 0);
151
152 m.iter().all(|e| SupersetOf::<T1>::is_in_subset(e)) &&
154 rot.is_special_orthogonal(T2::default_epsilon() * crate::convert(100.0)) &&
156 bottom.iter().all(|e| e.is_zero()) && m[(D, D)] == T2::one()
158 }
159
160 #[inline]
161 fn from_superset_unchecked(
162 m: &OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
163 ) -> Self {
164 let t = m.fixed_view::<D, 1>(0, D).into_owned();
165 let t = Translation {
166 vector: crate::convert_unchecked(t),
167 };
168
169 Self::from_parts(t, crate::convert_unchecked(m.clone_owned()))
170 }
171}
172
173impl<T: SimdRealField, R: AbstractRotation<T, D>, const D: usize> From<Translation<T, D>>
174 for Isometry<T, R, D>
175{
176 #[inline]
177 fn from(tra: Translation<T, D>) -> Self {
178 Self::from_parts(tra, R::identity())
179 }
180}
181
182impl<T: SimdRealField, R, const D: usize> From<Isometry<T, R, D>>
183 for OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
184where
185 Const<D>: DimNameAdd<U1>,
186 R: SubsetOf<OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>>,
187 DefaultAllocator: Allocator<DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, {
189 #[inline]
190 fn from(iso: Isometry<T, R, D>) -> Self {
191 iso.to_homogeneous()
192 }
193}
194
195impl<T: SimdRealField, R, const D: usize> From<[T; D]> for Isometry<T, R, D>
196where
197 R: AbstractRotation<T, D>,
198{
199 #[inline]
200 fn from(coords: [T; D]) -> Self {
201 Self::from_parts(coords.into(), R::identity())
202 }
203}
204
205impl<T: SimdRealField, R, const D: usize> From<SVector<T, D>> for Isometry<T, R, D>
206where
207 R: AbstractRotation<T, D>,
208{
209 #[inline]
210 fn from(coords: SVector<T, D>) -> Self {
211 Self::from_parts(coords.into(), R::identity())
212 }
213}
214impl<T: SimdRealField, R, const D: usize> From<Point<T, D>> for Isometry<T, R, D>
215where
216 R: AbstractRotation<T, D>,
217{
218 #[inline]
219 fn from(coords: Point<T, D>) -> Self {
220 Self::from_parts(coords.into(), R::identity())
221 }
222}
223
224impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
225 From<[Isometry<T::Element, R::Element, D>; 2]> for Isometry<T, R, D>
226where
227 T: From<[<T as SimdValue>::Element; 2]>,
228 R: SimdValue + AbstractRotation<T, D> + From<[<R as SimdValue>::Element; 2]>,
229 R::Element: AbstractRotation<T::Element, D>,
230 T::Element: Scalar + Copy,
231 R::Element: Scalar + Copy,
232{
233 #[inline]
234 fn from(arr: [Isometry<T::Element, R::Element, D>; 2]) -> Self {
235 let tra = Translation::from([arr[0].translation, arr[1].translation]);
236 let rot = R::from([arr[0].rotation, arr[0].rotation]);
237
238 Self::from_parts(tra, rot)
239 }
240}
241
242impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
243 From<[Isometry<T::Element, R::Element, D>; 4]> for Isometry<T, R, D>
244where
245 T: From<[<T as SimdValue>::Element; 4]>,
246 R: SimdValue + AbstractRotation<T, D> + From<[<R as SimdValue>::Element; 4]>,
247 R::Element: AbstractRotation<T::Element, D>,
248 T::Element: Scalar + Copy,
249 R::Element: Scalar + Copy,
250{
251 #[inline]
252 fn from(arr: [Isometry<T::Element, R::Element, D>; 4]) -> Self {
253 let tra = Translation::from([
254 arr[0].translation,
255 arr[1].translation,
256 arr[2].translation,
257 arr[3].translation,
258 ]);
259 let rot = R::from([
260 arr[0].rotation,
261 arr[1].rotation,
262 arr[2].rotation,
263 arr[3].rotation,
264 ]);
265
266 Self::from_parts(tra, rot)
267 }
268}
269
270impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
271 From<[Isometry<T::Element, R::Element, D>; 8]> for Isometry<T, R, D>
272where
273 T: From<[<T as SimdValue>::Element; 8]>,
274 R: SimdValue + AbstractRotation<T, D> + From<[<R as SimdValue>::Element; 8]>,
275 R::Element: AbstractRotation<T::Element, D>,
276 T::Element: Scalar + Copy,
277 R::Element: Scalar + Copy,
278{
279 #[inline]
280 fn from(arr: [Isometry<T::Element, R::Element, D>; 8]) -> Self {
281 let tra = Translation::from([
282 arr[0].translation,
283 arr[1].translation,
284 arr[2].translation,
285 arr[3].translation,
286 arr[4].translation,
287 arr[5].translation,
288 arr[6].translation,
289 arr[7].translation,
290 ]);
291 let rot = R::from([
292 arr[0].rotation,
293 arr[1].rotation,
294 arr[2].rotation,
295 arr[3].rotation,
296 arr[4].rotation,
297 arr[5].rotation,
298 arr[6].rotation,
299 arr[7].rotation,
300 ]);
301
302 Self::from_parts(tra, rot)
303 }
304}
305
306impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
307 From<[Isometry<T::Element, R::Element, D>; 16]> for Isometry<T, R, D>
308where
309 T: From<[<T as SimdValue>::Element; 16]>,
310 R: SimdValue + AbstractRotation<T, D> + From<[<R as SimdValue>::Element; 16]>,
311 R::Element: AbstractRotation<T::Element, D>,
312 T::Element: Scalar + Copy,
313 R::Element: Scalar + Copy,
314{
315 #[inline]
316 fn from(arr: [Isometry<T::Element, R::Element, D>; 16]) -> Self {
317 let tra = Translation::from([
318 arr[0].translation,
319 arr[1].translation,
320 arr[2].translation,
321 arr[3].translation,
322 arr[4].translation,
323 arr[5].translation,
324 arr[6].translation,
325 arr[7].translation,
326 arr[8].translation,
327 arr[9].translation,
328 arr[10].translation,
329 arr[11].translation,
330 arr[12].translation,
331 arr[13].translation,
332 arr[14].translation,
333 arr[15].translation,
334 ]);
335 let rot = R::from([
336 arr[0].rotation,
337 arr[1].rotation,
338 arr[2].rotation,
339 arr[3].rotation,
340 arr[4].rotation,
341 arr[5].rotation,
342 arr[6].rotation,
343 arr[7].rotation,
344 arr[8].rotation,
345 arr[9].rotation,
346 arr[10].rotation,
347 arr[11].rotation,
348 arr[12].rotation,
349 arr[13].rotation,
350 arr[14].rotation,
351 arr[15].rotation,
352 ]);
353
354 Self::from_parts(tra, rot)
355 }
356}