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