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::{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<T1, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
109 + Allocator<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
110 + Allocator<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
111 {
116 #[inline]
117 fn to_superset(&self) -> Transform<T2, C, D> {
118 Transform::from_matrix_unchecked(self.to_homogeneous().to_superset())
119 }
120
121 #[inline]
122 fn is_in_subset(t: &Transform<T2, C, D>) -> bool {
123 <Self as SubsetOf<_>>::is_in_subset(t.matrix())
124 }
125
126 #[inline]
127 fn from_superset_unchecked(t: &Transform<T2, C, D>) -> Self {
128 Self::from_superset_unchecked(t.matrix())
129 }
130}
131
132impl<T1, T2, R, const D: usize>
133 SubsetOf<OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>> for Isometry<T1, R, D>
134where
135 T1: RealField,
136 T2: RealField + SupersetOf<T1>,
137 R: AbstractRotation<T1, D>
138 + SubsetOf<OMatrix<T1, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>>
139 + SubsetOf<OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>>,
140 Const<D>: DimNameAdd<U1> + DimMin<Const<D>, Output = Const<D>>, DefaultAllocator: Allocator<T1, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
142 + Allocator<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
143 + Allocator<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, {
149 #[inline]
150 fn to_superset(&self) -> OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>> {
151 self.to_homogeneous().to_superset()
152 }
153
154 #[inline]
155 fn is_in_subset(m: &OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>) -> bool {
156 let rot = m.fixed_slice::<D, D>(0, 0);
157 let bottom = m.fixed_slice::<1, D>(D, 0);
158
159 m.iter().all(|e| SupersetOf::<T1>::is_in_subset(e)) &&
161 rot.is_special_orthogonal(T2::default_epsilon() * crate::convert(100.0)) &&
163 bottom.iter().all(|e| e.is_zero()) && m[(D, D)] == T2::one()
165 }
166
167 #[inline]
168 fn from_superset_unchecked(
169 m: &OMatrix<T2, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
170 ) -> Self {
171 let t = m.fixed_slice::<D, 1>(0, D).into_owned();
172 let t = Translation {
173 vector: crate::convert_unchecked(t),
174 };
175
176 Self::from_parts(t, crate::convert_unchecked(m.clone_owned()))
177 }
178}
179
180impl<T: SimdRealField, R: AbstractRotation<T, D>, const D: usize> From<Translation<T, D>>
181 for Isometry<T, R, D>
182{
183 #[inline]
184 fn from(tra: Translation<T, D>) -> Self {
185 Self::from_parts(tra, R::identity())
186 }
187}
188
189impl<T: SimdRealField, R, const D: usize> From<Isometry<T, R, D>>
190 for OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
191where
192 Const<D>: DimNameAdd<U1>,
193 R: SubsetOf<OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>>,
194 DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, {
196 #[inline]
197 fn from(iso: Isometry<T, R, D>) -> Self {
198 iso.to_homogeneous()
199 }
200}
201
202impl<T: SimdRealField, R, const D: usize> From<[T; D]> for Isometry<T, R, D>
203where
204 R: AbstractRotation<T, D>,
205{
206 #[inline]
207 fn from(coords: [T; D]) -> Self {
208 Self::from_parts(coords.into(), R::identity())
209 }
210}
211
212impl<T: SimdRealField, R, const D: usize> From<SVector<T, D>> for Isometry<T, R, D>
213where
214 R: AbstractRotation<T, D>,
215{
216 #[inline]
217 fn from(coords: SVector<T, D>) -> Self {
218 Self::from_parts(coords.into(), R::identity())
219 }
220}
221impl<T: SimdRealField, R, const D: usize> From<Point<T, D>> for Isometry<T, R, D>
222where
223 R: AbstractRotation<T, D>,
224{
225 #[inline]
226 fn from(coords: Point<T, D>) -> Self {
227 Self::from_parts(coords.into(), R::identity())
228 }
229}
230
231impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
232 From<[Isometry<T::Element, R::Element, D>; 2]> for Isometry<T, R, D>
233where
234 T: From<[<T as SimdValue>::Element; 2]>,
235 R: SimdValue + AbstractRotation<T, D> + From<[<R as SimdValue>::Element; 2]>,
236 R::Element: AbstractRotation<T::Element, D>,
237 T::Element: Scalar + Copy,
238 R::Element: Scalar + Copy,
239{
240 #[inline]
241 fn from(arr: [Isometry<T::Element, R::Element, D>; 2]) -> Self {
242 let tra = Translation::from([arr[0].translation, arr[1].translation]);
243 let rot = R::from([arr[0].rotation, arr[0].rotation]);
244
245 Self::from_parts(tra, rot)
246 }
247}
248
249impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
250 From<[Isometry<T::Element, R::Element, D>; 4]> for Isometry<T, R, D>
251where
252 T: From<[<T as SimdValue>::Element; 4]>,
253 R: SimdValue + AbstractRotation<T, D> + From<[<R as SimdValue>::Element; 4]>,
254 R::Element: AbstractRotation<T::Element, D>,
255 T::Element: Scalar + Copy,
256 R::Element: Scalar + Copy,
257{
258 #[inline]
259 fn from(arr: [Isometry<T::Element, R::Element, D>; 4]) -> Self {
260 let tra = Translation::from([
261 arr[0].translation,
262 arr[1].translation,
263 arr[2].translation,
264 arr[3].translation,
265 ]);
266 let rot = R::from([
267 arr[0].rotation,
268 arr[1].rotation,
269 arr[2].rotation,
270 arr[3].rotation,
271 ]);
272
273 Self::from_parts(tra, rot)
274 }
275}
276
277impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
278 From<[Isometry<T::Element, R::Element, D>; 8]> for Isometry<T, R, D>
279where
280 T: From<[<T as SimdValue>::Element; 8]>,
281 R: SimdValue + AbstractRotation<T, D> + From<[<R as SimdValue>::Element; 8]>,
282 R::Element: AbstractRotation<T::Element, D>,
283 T::Element: Scalar + Copy,
284 R::Element: Scalar + Copy,
285{
286 #[inline]
287 fn from(arr: [Isometry<T::Element, R::Element, D>; 8]) -> Self {
288 let tra = Translation::from([
289 arr[0].translation,
290 arr[1].translation,
291 arr[2].translation,
292 arr[3].translation,
293 arr[4].translation,
294 arr[5].translation,
295 arr[6].translation,
296 arr[7].translation,
297 ]);
298 let rot = R::from([
299 arr[0].rotation,
300 arr[1].rotation,
301 arr[2].rotation,
302 arr[3].rotation,
303 arr[4].rotation,
304 arr[5].rotation,
305 arr[6].rotation,
306 arr[7].rotation,
307 ]);
308
309 Self::from_parts(tra, rot)
310 }
311}
312
313impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
314 From<[Isometry<T::Element, R::Element, D>; 16]> for Isometry<T, R, D>
315where
316 T: From<[<T as SimdValue>::Element; 16]>,
317 R: SimdValue + AbstractRotation<T, D> + From<[<R as SimdValue>::Element; 16]>,
318 R::Element: AbstractRotation<T::Element, D>,
319 T::Element: Scalar + Copy,
320 R::Element: Scalar + Copy,
321{
322 #[inline]
323 fn from(arr: [Isometry<T::Element, R::Element, D>; 16]) -> Self {
324 let tra = Translation::from([
325 arr[0].translation,
326 arr[1].translation,
327 arr[2].translation,
328 arr[3].translation,
329 arr[4].translation,
330 arr[5].translation,
331 arr[6].translation,
332 arr[7].translation,
333 arr[8].translation,
334 arr[9].translation,
335 arr[10].translation,
336 arr[11].translation,
337 arr[12].translation,
338 arr[13].translation,
339 arr[14].translation,
340 arr[15].translation,
341 ]);
342 let rot = R::from([
343 arr[0].rotation,
344 arr[1].rotation,
345 arr[2].rotation,
346 arr[3].rotation,
347 arr[4].rotation,
348 arr[5].rotation,
349 arr[6].rotation,
350 arr[7].rotation,
351 arr[8].rotation,
352 arr[9].rotation,
353 arr[10].rotation,
354 arr[11].rotation,
355 arr[12].rotation,
356 arr[13].rotation,
357 arr[14].rotation,
358 arr[15].rotation,
359 ]);
360
361 Self::from_parts(tra, rot)
362 }
363}