1 use alga::general::{
2     AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
3     AbstractSemigroup, Identity, Multiplicative, RealField, TwoSidedInverse,
4 };
5 use alga::linear::Similarity as AlgaSimilarity;
6 use alga::linear::{AffineTransformation, ProjectiveTransformation, Rotation, Transformation};
7 
8 use crate::base::SVector;
9 use crate::geometry::{AbstractRotation, Point, Similarity, Translation};
10 
11 /*
12  *
13  * Algebraic structures.
14  *
15  */
16 impl<T: RealField + simba::scalar::RealField, R, const D: usize> Identity<Multiplicative>
17     for Similarity<T, R, D>
18 where
19     R: Rotation<Point<T, D>> + AbstractRotation<T, D>,
20 {
21     #[inline]
identity() -> Self22     fn identity() -> Self {
23         Self::identity()
24     }
25 }
26 
27 impl<T: RealField + simba::scalar::RealField, R, const D: usize> TwoSidedInverse<Multiplicative>
28     for Similarity<T, R, D>
29 where
30     R: Rotation<Point<T, D>> + AbstractRotation<T, D>,
31 {
32     #[inline]
33     #[must_use = "Did you mean to use two_sided_inverse_mut()?"]
two_sided_inverse(&self) -> Self34     fn two_sided_inverse(&self) -> Self {
35         self.inverse()
36     }
37 
38     #[inline]
two_sided_inverse_mut(&mut self)39     fn two_sided_inverse_mut(&mut self) {
40         self.inverse_mut()
41     }
42 }
43 
44 impl<T: RealField + simba::scalar::RealField, R, const D: usize> AbstractMagma<Multiplicative>
45     for Similarity<T, R, D>
46 where
47     R: Rotation<Point<T, D>> + AbstractRotation<T, D>,
48 {
49     #[inline]
operate(&self, rhs: &Self) -> Self50     fn operate(&self, rhs: &Self) -> Self {
51         self * rhs
52     }
53 }
54 
55 macro_rules! impl_multiplicative_structures(
56     ($($marker: ident<$operator: ident>),* $(,)*) => {$(
57         impl<T: RealField + simba::scalar::RealField, R, const D: usize> $marker<$operator> for Similarity<T, R, D>
58             where R: Rotation<Point<T, D>> + AbstractRotation<T, D>,
59                   { }
60     )*}
61 );
62 
63 impl_multiplicative_structures!(
64     AbstractSemigroup<Multiplicative>,
65     AbstractMonoid<Multiplicative>,
66     AbstractQuasigroup<Multiplicative>,
67     AbstractLoop<Multiplicative>,
68     AbstractGroup<Multiplicative>
69 );
70 
71 /*
72  *
73  * Transformation groups.
74  *
75  */
76 impl<T: RealField + simba::scalar::RealField, R, const D: usize> Transformation<Point<T, D>>
77     for Similarity<T, R, D>
78 where
79     R: Rotation<Point<T, D>> + AbstractRotation<T, D>,
80 {
81     #[inline]
transform_point(&self, pt: &Point<T, D>) -> Point<T, D>82     fn transform_point(&self, pt: &Point<T, D>) -> Point<T, D> {
83         self.transform_point(pt)
84     }
85 
86     #[inline]
transform_vector(&self, v: &SVector<T, D>) -> SVector<T, D>87     fn transform_vector(&self, v: &SVector<T, D>) -> SVector<T, D> {
88         self.transform_vector(v)
89     }
90 }
91 
92 impl<T: RealField + simba::scalar::RealField, R, const D: usize>
93     ProjectiveTransformation<Point<T, D>> for Similarity<T, R, D>
94 where
95     R: Rotation<Point<T, D>> + AbstractRotation<T, D>,
96 {
97     #[inline]
inverse_transform_point(&self, pt: &Point<T, D>) -> Point<T, D>98     fn inverse_transform_point(&self, pt: &Point<T, D>) -> Point<T, D> {
99         self.inverse_transform_point(pt)
100     }
101 
102     #[inline]
inverse_transform_vector(&self, v: &SVector<T, D>) -> SVector<T, D>103     fn inverse_transform_vector(&self, v: &SVector<T, D>) -> SVector<T, D> {
104         self.inverse_transform_vector(v)
105     }
106 }
107 
108 impl<T: RealField + simba::scalar::RealField, R, const D: usize> AffineTransformation<Point<T, D>>
109     for Similarity<T, R, D>
110 where
111     R: Rotation<Point<T, D>> + AbstractRotation<T, D>,
112 {
113     type NonUniformScaling = T;
114     type Rotation = R;
115     type Translation = Translation<T, D>;
116 
117     #[inline]
decompose(&self) -> (Translation<T, D>, R, T, R)118     fn decompose(&self) -> (Translation<T, D>, R, T, R) {
119         (
120             self.isometry.translation,
121             self.isometry.rotation.clone(),
122             self.scaling(),
123             <R as AbstractRotation<T, D>>::identity(),
124         )
125     }
126 
127     #[inline]
append_translation(&self, t: &Self::Translation) -> Self128     fn append_translation(&self, t: &Self::Translation) -> Self {
129         t * self
130     }
131 
132     #[inline]
prepend_translation(&self, t: &Self::Translation) -> Self133     fn prepend_translation(&self, t: &Self::Translation) -> Self {
134         self * t
135     }
136 
137     #[inline]
append_rotation(&self, r: &Self::Rotation) -> Self138     fn append_rotation(&self, r: &Self::Rotation) -> Self {
139         Similarity::from_isometry(self.isometry.append_rotation(r), self.scaling())
140     }
141 
142     #[inline]
prepend_rotation(&self, r: &Self::Rotation) -> Self143     fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
144         Similarity::from_isometry(self.isometry.prepend_rotation(r), self.scaling())
145     }
146 
147     #[inline]
append_scaling(&self, s: &Self::NonUniformScaling) -> Self148     fn append_scaling(&self, s: &Self::NonUniformScaling) -> Self {
149         self.append_scaling(*s)
150     }
151 
152     #[inline]
prepend_scaling(&self, s: &Self::NonUniformScaling) -> Self153     fn prepend_scaling(&self, s: &Self::NonUniformScaling) -> Self {
154         self.prepend_scaling(*s)
155     }
156 
157     #[inline]
append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point<T, D>) -> Option<Self>158     fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point<T, D>) -> Option<Self> {
159         let mut res = self.clone();
160         res.append_rotation_wrt_point_mut(r, p);
161         Some(res)
162     }
163 }
164 
165 impl<T: RealField + simba::scalar::RealField, R, const D: usize> AlgaSimilarity<Point<T, D>>
166     for Similarity<T, R, D>
167 where
168     R: Rotation<Point<T, D>> + AbstractRotation<T, D>,
169 {
170     type Scaling = T;
171 
172     #[inline]
translation(&self) -> Translation<T, D>173     fn translation(&self) -> Translation<T, D> {
174         self.isometry.translation()
175     }
176 
177     #[inline]
rotation(&self) -> R178     fn rotation(&self) -> R {
179         self.isometry.rotation()
180     }
181 
182     #[inline]
scaling(&self) -> T183     fn scaling(&self) -> T {
184         self.scaling()
185     }
186 }
187