1 use alga::general::{ 2 AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, 3 AbstractSemigroup, Id, Identity, Multiplicative, RealField, TwoSidedInverse, 4 }; 5 use alga::linear::Isometry as AlgaIsometry; 6 use alga::linear::{ 7 AffineTransformation, DirectIsometry, ProjectiveTransformation, Rotation, Similarity, 8 Transformation, 9 }; 10 11 use crate::base::SVector; 12 13 use crate::geometry::{AbstractRotation, Isometry, Point, Translation}; 14 15 /* 16 * 17 * Algebraic structures. 18 * 19 */ 20 impl<T: RealField + simba::scalar::RealField, R, const D: usize> Identity<Multiplicative> 21 for Isometry<T, R, D> 22 where 23 R: Rotation<Point<T, D>> + AbstractRotation<T, D>, 24 { 25 #[inline] identity() -> Self26 fn identity() -> Self { 27 Self::identity() 28 } 29 } 30 31 impl<T: RealField + simba::scalar::RealField, R, const D: usize> TwoSidedInverse<Multiplicative> 32 for Isometry<T, R, D> 33 where 34 R: Rotation<Point<T, D>> + AbstractRotation<T, D>, 35 { 36 #[inline] 37 #[must_use = "Did you mean to use two_sided_inverse_mut()?"] two_sided_inverse(&self) -> Self38 fn two_sided_inverse(&self) -> Self { 39 self.inverse() 40 } 41 42 #[inline] two_sided_inverse_mut(&mut self)43 fn two_sided_inverse_mut(&mut self) { 44 self.inverse_mut() 45 } 46 } 47 48 impl<T: RealField + simba::scalar::RealField, R, const D: usize> AbstractMagma<Multiplicative> 49 for Isometry<T, R, D> 50 where 51 R: Rotation<Point<T, D>> + AbstractRotation<T, D>, 52 { 53 #[inline] operate(&self, rhs: &Self) -> Self54 fn operate(&self, rhs: &Self) -> Self { 55 self * rhs 56 } 57 } 58 59 macro_rules! impl_multiplicative_structures( 60 ($($marker: ident<$operator: ident>),* $(,)*) => {$( 61 impl<T: RealField + simba::scalar::RealField, R, const D: usize> $marker<$operator> for Isometry<T, R, D> 62 where R: Rotation<Point<T, D>> + AbstractRotation<T, D> { } 63 )*} 64 ); 65 66 impl_multiplicative_structures!( 67 AbstractSemigroup<Multiplicative>, 68 AbstractMonoid<Multiplicative>, 69 AbstractQuasigroup<Multiplicative>, 70 AbstractLoop<Multiplicative>, 71 AbstractGroup<Multiplicative> 72 ); 73 74 /* 75 * 76 * Transformation groups. 77 * 78 */ 79 impl<T: RealField + simba::scalar::RealField, R, const D: usize> Transformation<Point<T, D>> 80 for Isometry<T, R, D> 81 where 82 R: Rotation<Point<T, D>> + AbstractRotation<T, D>, 83 { 84 #[inline] transform_point(&self, pt: &Point<T, D>) -> Point<T, D>85 fn transform_point(&self, pt: &Point<T, D>) -> Point<T, D> { 86 self.transform_point(pt) 87 } 88 89 #[inline] transform_vector(&self, v: &SVector<T, D>) -> SVector<T, D>90 fn transform_vector(&self, v: &SVector<T, D>) -> SVector<T, D> { 91 self.transform_vector(v) 92 } 93 } 94 95 impl<T: RealField + simba::scalar::RealField, R, const D: usize> 96 ProjectiveTransformation<Point<T, D>> for Isometry<T, R, D> 97 where 98 R: Rotation<Point<T, D>> + AbstractRotation<T, D>, 99 { 100 #[inline] inverse_transform_point(&self, pt: &Point<T, D>) -> Point<T, D>101 fn inverse_transform_point(&self, pt: &Point<T, D>) -> Point<T, D> { 102 self.inverse_transform_point(pt) 103 } 104 105 #[inline] inverse_transform_vector(&self, v: &SVector<T, D>) -> SVector<T, D>106 fn inverse_transform_vector(&self, v: &SVector<T, D>) -> SVector<T, D> { 107 self.inverse_transform_vector(v) 108 } 109 } 110 111 impl<T: RealField + simba::scalar::RealField, R, const D: usize> AffineTransformation<Point<T, D>> 112 for Isometry<T, R, D> 113 where 114 R: Rotation<Point<T, D>> + AbstractRotation<T, D>, 115 { 116 type Rotation = R; 117 type NonUniformScaling = Id; 118 type Translation = Translation<T, D>; 119 120 #[inline] decompose(&self) -> (Self::Translation, R, Id, R)121 fn decompose(&self) -> (Self::Translation, R, Id, R) { 122 ( 123 self.translation, 124 self.rotation.clone(), 125 Id::new(), 126 <R as AbstractRotation<T, D>>::identity(), 127 ) 128 } 129 130 #[inline] append_translation(&self, t: &Self::Translation) -> Self131 fn append_translation(&self, t: &Self::Translation) -> Self { 132 t * self 133 } 134 135 #[inline] prepend_translation(&self, t: &Self::Translation) -> Self136 fn prepend_translation(&self, t: &Self::Translation) -> Self { 137 self * t 138 } 139 140 #[inline] append_rotation(&self, r: &Self::Rotation) -> Self141 fn append_rotation(&self, r: &Self::Rotation) -> Self { 142 let shift = Transformation::transform_vector(r, &self.translation.vector); 143 Isometry::from_parts(Translation::from(shift), r.clone() * self.rotation.clone()) 144 } 145 146 #[inline] prepend_rotation(&self, r: &Self::Rotation) -> Self147 fn prepend_rotation(&self, r: &Self::Rotation) -> Self { 148 Isometry::from_parts(self.translation, self.rotation.prepend_rotation(r)) 149 } 150 151 #[inline] append_scaling(&self, _: &Self::NonUniformScaling) -> Self152 fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { 153 self.clone() 154 } 155 156 #[inline] prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self157 fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { 158 self.clone() 159 } 160 161 #[inline] append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point<T, D>) -> Option<Self>162 fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point<T, D>) -> Option<Self> { 163 let mut res = self.clone(); 164 res.append_rotation_wrt_point_mut(r, p); 165 Some(res) 166 } 167 } 168 169 impl<T: RealField + simba::scalar::RealField, R, const D: usize> Similarity<Point<T, D>> 170 for Isometry<T, R, D> 171 where 172 R: Rotation<Point<T, D>> + AbstractRotation<T, D>, 173 { 174 type Scaling = Id; 175 176 #[inline] translation(&self) -> Translation<T, D>177 fn translation(&self) -> Translation<T, D> { 178 self.translation 179 } 180 181 #[inline] rotation(&self) -> R182 fn rotation(&self) -> R { 183 self.rotation.clone() 184 } 185 186 #[inline] scaling(&self) -> Id187 fn scaling(&self) -> Id { 188 Id::new() 189 } 190 } 191 192 macro_rules! marker_impl( 193 ($($Trait: ident),*) => {$( 194 impl<T: RealField + simba::scalar::RealField, R, const D: usize> $Trait<Point<T, D>> for Isometry<T, R, D> 195 where R: Rotation<Point<T, D>> + AbstractRotation<T, D> { } 196 )*} 197 ); 198 199 marker_impl!(AlgaIsometry, DirectIsometry); 200