1 use num::{One, Zero};
2 
3 use alga::general::{RealField, SubsetOf, SupersetOf};
4 use alga::linear::Rotation;
5 
6 use crate::base::allocator::Allocator;
7 use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
8 use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN};
9 
10 use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation};
11 
12 /*
13  * This file provides the following conversions:
14  * =============================================
15  *
16  * Translation -> Translation
17  * Translation -> Isometry
18  * Translation -> Similarity
19  * Translation -> Transform
20  * Translation -> Matrix (homogeneous)
21  */
22 
23 impl<N1, N2, D: DimName> SubsetOf<Translation<N2, D>> for Translation<N1, D>
24 where
25     N1: Scalar,
26     N2: Scalar + SupersetOf<N1>,
27     DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
28 {
29     #[inline]
to_superset(&self) -> Translation<N2, D>30     fn to_superset(&self) -> Translation<N2, D> {
31         Translation::from(self.vector.to_superset())
32     }
33 
34     #[inline]
is_in_subset(rot: &Translation<N2, D>) -> bool35     fn is_in_subset(rot: &Translation<N2, D>) -> bool {
36         crate::is_convertible::<_, VectorN<N1, D>>(&rot.vector)
37     }
38 
39     #[inline]
from_superset_unchecked(rot: &Translation<N2, D>) -> Self40     unsafe fn from_superset_unchecked(rot: &Translation<N2, D>) -> Self {
41         Translation {
42             vector: rot.vector.to_subset_unchecked(),
43         }
44     }
45 }
46 
47 impl<N1, N2, D: DimName, R> SubsetOf<Isometry<N2, D, R>> for Translation<N1, D>
48 where
49     N1: RealField,
50     N2: RealField + SupersetOf<N1>,
51     R: Rotation<Point<N2, D>>,
52     DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
53 {
54     #[inline]
to_superset(&self) -> Isometry<N2, D, R>55     fn to_superset(&self) -> Isometry<N2, D, R> {
56         Isometry::from_parts(self.to_superset(), R::identity())
57     }
58 
59     #[inline]
is_in_subset(iso: &Isometry<N2, D, R>) -> bool60     fn is_in_subset(iso: &Isometry<N2, D, R>) -> bool {
61         iso.rotation == R::identity()
62     }
63 
64     #[inline]
from_superset_unchecked(iso: &Isometry<N2, D, R>) -> Self65     unsafe fn from_superset_unchecked(iso: &Isometry<N2, D, R>) -> Self {
66         Self::from_superset_unchecked(&iso.translation)
67     }
68 }
69 
70 impl<N1, N2, D: DimName, R> SubsetOf<Similarity<N2, D, R>> for Translation<N1, D>
71 where
72     N1: RealField,
73     N2: RealField + SupersetOf<N1>,
74     R: Rotation<Point<N2, D>>,
75     DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
76 {
77     #[inline]
to_superset(&self) -> Similarity<N2, D, R>78     fn to_superset(&self) -> Similarity<N2, D, R> {
79         Similarity::from_parts(self.to_superset(), R::identity(), N2::one())
80     }
81 
82     #[inline]
is_in_subset(sim: &Similarity<N2, D, R>) -> bool83     fn is_in_subset(sim: &Similarity<N2, D, R>) -> bool {
84         sim.isometry.rotation == R::identity() && sim.scaling() == N2::one()
85     }
86 
87     #[inline]
from_superset_unchecked(sim: &Similarity<N2, D, R>) -> Self88     unsafe fn from_superset_unchecked(sim: &Similarity<N2, D, R>) -> Self {
89         Self::from_superset_unchecked(&sim.isometry.translation)
90     }
91 }
92 
93 impl<N1, N2, D, C> SubsetOf<Transform<N2, D, C>> for Translation<N1, D>
94 where
95     N1: RealField,
96     N2: RealField + SupersetOf<N1>,
97     C: SuperTCategoryOf<TAffine>,
98     D: DimNameAdd<U1>,
99     DefaultAllocator: Allocator<N1, D>
100         + Allocator<N2, D>
101         + Allocator<N1, DimNameSum<D, U1>, DimNameSum<D, U1>>
102         + Allocator<N2, DimNameSum<D, U1>, DimNameSum<D, U1>>,
103 {
104     #[inline]
to_superset(&self) -> Transform<N2, D, C>105     fn to_superset(&self) -> Transform<N2, D, C> {
106         Transform::from_matrix_unchecked(self.to_homogeneous().to_superset())
107     }
108 
109     #[inline]
is_in_subset(t: &Transform<N2, D, C>) -> bool110     fn is_in_subset(t: &Transform<N2, D, C>) -> bool {
111         <Self as SubsetOf<_>>::is_in_subset(t.matrix())
112     }
113 
114     #[inline]
from_superset_unchecked(t: &Transform<N2, D, C>) -> Self115     unsafe fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
116         Self::from_superset_unchecked(t.matrix())
117     }
118 }
119 
120 impl<N1, N2, D> SubsetOf<MatrixN<N2, DimNameSum<D, U1>>> for Translation<N1, D>
121 where
122     N1: RealField,
123     N2: RealField + SupersetOf<N1>,
124     D: DimNameAdd<U1>,
125     DefaultAllocator: Allocator<N1, D>
126         + Allocator<N2, D>
127         + Allocator<N1, DimNameSum<D, U1>, DimNameSum<D, U1>>
128         + Allocator<N2, DimNameSum<D, U1>, DimNameSum<D, U1>>,
129 {
130     #[inline]
to_superset(&self) -> MatrixN<N2, DimNameSum<D, U1>>131     fn to_superset(&self) -> MatrixN<N2, DimNameSum<D, U1>> {
132         self.to_homogeneous().to_superset()
133     }
134 
135     #[inline]
is_in_subset(m: &MatrixN<N2, DimNameSum<D, U1>>) -> bool136     fn is_in_subset(m: &MatrixN<N2, DimNameSum<D, U1>>) -> bool {
137         let id = m.fixed_slice::<DimNameSum<D, U1>, D>(0, 0);
138 
139         // Scalar types agree.
140         m.iter().all(|e| SupersetOf::<N1>::is_in_subset(e)) &&
141         // The block part does nothing.
142         id.is_identity(N2::zero()) &&
143         // The normalization factor is one.
144         m[(D::dim(), D::dim())] == N2::one()
145     }
146 
147     #[inline]
from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self148     unsafe fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
149         let t = m.fixed_slice::<D, U1>(0, D::dim());
150         Self {
151             vector: crate::convert_unchecked(t.into_owned()),
152         }
153     }
154 }
155 
156 impl<N: Scalar + Zero + One, D: DimName> From<Translation<N, D>> for MatrixN<N, DimNameSum<D, U1>>
157 where
158     D: DimNameAdd<U1>,
159     DefaultAllocator: Allocator<N, D> + Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
160 {
161     #[inline]
from(t: Translation<N, D>) -> Self162     fn from(t: Translation<N, D>) -> Self {
163         t.to_homogeneous()
164     }
165 }
166 
167 impl<N: Scalar, D: DimName> From<VectorN<N, D>> for Translation<N, D>
168 where DefaultAllocator: Allocator<N, D>
169 {
170     #[inline]
from(vector: VectorN<N, D>) -> Self171     fn from(vector: VectorN<N, D>) -> Self {
172         Translation { vector }
173     }
174 }
175