use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, }; use alga::linear::Isometry as AlgaIsometry; use alga::linear::{ AffineTransformation, DirectIsometry, ProjectiveTransformation, Rotation, Similarity, Transformation, }; use crate::base::allocator::Allocator; use crate::base::dimension::DimName; use crate::base::{DefaultAllocator, VectorN}; use crate::geometry::{Isometry, Point, Translation}; /* * * Algebraic structures. * */ impl Identity for Isometry where R: Rotation>, DefaultAllocator: Allocator, { #[inline] fn identity() -> Self { Self::identity() } } impl TwoSidedInverse for Isometry where R: Rotation>, DefaultAllocator: Allocator, { #[inline] fn two_sided_inverse(&self) -> Self { self.inverse() } #[inline] fn two_sided_inverse_mut(&mut self) { self.inverse_mut() } } impl AbstractMagma for Isometry where R: Rotation>, DefaultAllocator: Allocator, { #[inline] fn operate(&self, rhs: &Self) -> Self { self * rhs } } macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( impl $marker<$operator> for Isometry where R: Rotation>, DefaultAllocator: Allocator { } )*} ); impl_multiplicative_structures!( AbstractSemigroup, AbstractMonoid, AbstractQuasigroup, AbstractLoop, AbstractGroup ); /* * * Transformation groups. * */ impl Transformation> for Isometry where R: Rotation>, DefaultAllocator: Allocator, { #[inline] fn transform_point(&self, pt: &Point) -> Point { self * pt } #[inline] fn transform_vector(&self, v: &VectorN) -> VectorN { self * v } } impl ProjectiveTransformation> for Isometry where R: Rotation>, DefaultAllocator: Allocator, { #[inline] fn inverse_transform_point(&self, pt: &Point) -> Point { self.rotation .inverse_transform_point(&(pt - &self.translation.vector)) } #[inline] fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { self.rotation.inverse_transform_vector(v) } } impl AffineTransformation> for Isometry where R: Rotation>, DefaultAllocator: Allocator, { type Rotation = R; type NonUniformScaling = Id; type Translation = Translation; #[inline] fn decompose(&self) -> (Self::Translation, R, Id, R) { ( self.translation.clone(), self.rotation.clone(), Id::new(), R::identity(), ) } #[inline] fn append_translation(&self, t: &Self::Translation) -> Self { t * self } #[inline] fn prepend_translation(&self, t: &Self::Translation) -> Self { self * t } #[inline] fn append_rotation(&self, r: &Self::Rotation) -> Self { let shift = r.transform_vector(&self.translation.vector); Isometry::from_parts(Translation::from(shift), r.clone() * self.rotation.clone()) } #[inline] fn prepend_rotation(&self, r: &Self::Rotation) -> Self { self * r } #[inline] fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { self.clone() } #[inline] fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { self.clone() } #[inline] fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point) -> Option { let mut res = self.clone(); res.append_rotation_wrt_point_mut(r, p); Some(res) } } impl Similarity> for Isometry where R: Rotation>, DefaultAllocator: Allocator, { type Scaling = Id; #[inline] fn translation(&self) -> Translation { self.translation.clone() } #[inline] fn rotation(&self) -> R { self.rotation.clone() } #[inline] fn scaling(&self) -> Id { Id::new() } } macro_rules! marker_impl( ($($Trait: ident),*) => {$( impl $Trait> for Isometry where R: Rotation>, DefaultAllocator: Allocator { } )*} ); marker_impl!(AlgaIsometry, DirectIsometry);