use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Identity, Multiplicative, RealField, TwoSidedInverse, }; use alga::linear::{ProjectiveTransformation, Transformation}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, VectorN}; use crate::geometry::{Point, SubTCategoryOf, TCategory, TProjective, Transform}; /* * * Algebraic structures. * */ impl, C> Identity for Transform where C: TCategory, DefaultAllocator: Allocator, DimNameSum>, { #[inline] fn identity() -> Self { Self::identity() } } impl, C> TwoSidedInverse for Transform where C: SubTCategoryOf, DefaultAllocator: Allocator, DimNameSum>, { #[inline] #[must_use = "Did you mean to use two_sided_inverse_mut()?"] fn two_sided_inverse(&self) -> Self { self.clone().inverse() } #[inline] fn two_sided_inverse_mut(&mut self) { self.inverse_mut() } } impl, C> AbstractMagma for Transform where C: TCategory, DefaultAllocator: Allocator, DimNameSum>, { #[inline] fn operate(&self, rhs: &Self) -> Self { self * rhs } } macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( impl, C> $marker<$operator> for Transform where C: TCategory, DefaultAllocator: Allocator, DimNameSum> { } )*} ); macro_rules! impl_inversible_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( impl, C> $marker<$operator> for Transform where C: SubTCategoryOf, DefaultAllocator: Allocator, DimNameSum> { } )*} ); impl_multiplicative_structures!( AbstractSemigroup, AbstractMonoid, ); impl_inversible_multiplicative_structures!( AbstractQuasigroup, AbstractLoop, AbstractGroup ); /* * * Transformation groups. * */ impl, C> Transformation> for Transform where N: RealField + simba::scalar::RealField, C: TCategory, DefaultAllocator: Allocator, DimNameSum> + Allocator> + Allocator + Allocator, { #[inline] fn transform_point(&self, pt: &Point) -> Point { self.transform_point(pt) } #[inline] fn transform_vector(&self, v: &VectorN) -> VectorN { self.transform_vector(v) } } impl, C> ProjectiveTransformation> for Transform where N: RealField + simba::scalar::RealField, C: SubTCategoryOf, DefaultAllocator: Allocator, DimNameSum> + Allocator> + Allocator + Allocator, { #[inline] fn inverse_transform_point(&self, pt: &Point) -> Point { self.inverse_transform_point(pt) } #[inline] fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { self.inverse_transform_vector(v) } } // FIXME: we need to implement an SVD for this. // // impl, C> AffineTransformation> for Transform // where N: RealField, // C: SubTCategoryOf, // DefaultAllocator: Allocator, DimNameSum> + // Allocator + // Allocator { // type PreRotation = Rotation; // type NonUniformScaling = VectorN; // type PostRotation = Rotation; // type Translation = Translation; // // #[inline] // fn decompose(&self) -> (Self::Translation, Self::PostRotation, Self::NonUniformScaling, Self::PreRotation) { // unimplemented!() // } // }