use approx::ApproxEq; use alga::general::{AbstractMagma, AbstractGroup, AbstractLoop, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Field, Real, Inverse, Multiplicative, Identity}; use alga::linear::{Transformation, ProjectiveTransformation}; use core::{Scalar, ColumnVector}; use core::dimension::{DimNameSum, DimNameAdd, U1}; use core::storage::OwnedStorage; use core::allocator::{Allocator, OwnedAllocator}; use geometry::{PointBase, TransformBase, TCategory, SubTCategoryOf, TProjective}; /* * * Algebraic structures. * */ impl, S, C> Identity for TransformBase where N: Scalar + Field, S: OwnedStorage, DimNameSum>, C: TCategory, S::Alloc: OwnedAllocator, DimNameSum, S> { #[inline] fn identity() -> Self { Self::identity() } } impl, S, C> Inverse for TransformBase where N: Scalar + Field + ApproxEq, S: OwnedStorage, DimNameSum>, C: SubTCategoryOf, S::Alloc: OwnedAllocator, DimNameSum, S> { #[inline] fn inverse(&self) -> Self { self.clone().inverse() } #[inline] fn inverse_mut(&mut self) { self.inverse_mut() } } impl, S, C> AbstractMagma for TransformBase where N: Scalar + Field, S: OwnedStorage, DimNameSum>, C: TCategory, S::Alloc: OwnedAllocator, DimNameSum, S> { #[inline] fn operate(&self, rhs: &Self) -> Self { self * rhs } } macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( impl, S, C> $marker<$operator> for TransformBase where N: Scalar + Field, S: OwnedStorage, DimNameSum>, C: TCategory, S::Alloc: OwnedAllocator, DimNameSum, S> { } )*} ); macro_rules! impl_inversible_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( impl, S, C> $marker<$operator> for TransformBase where N: Scalar + Field + ApproxEq, S: OwnedStorage, DimNameSum>, C: SubTCategoryOf, S::Alloc: OwnedAllocator, DimNameSum, S> { } )*} ); impl_multiplicative_structures!( AbstractSemigroup, AbstractMonoid, ); impl_inversible_multiplicative_structures!( AbstractQuasigroup, AbstractLoop, AbstractGroup ); /* * * Transformation groups. * */ impl, SA, SB, C> Transformation> for TransformBase where N: Real, SA: OwnedStorage, DimNameSum>, SB: OwnedStorage, C: TCategory, SA::Alloc: OwnedAllocator, DimNameSum, SA> + Allocator + Allocator + Allocator, SB::Alloc: OwnedAllocator { #[inline] fn transform_point(&self, pt: &PointBase) -> PointBase { self * pt } #[inline] fn transform_vector(&self, v: &ColumnVector) -> ColumnVector { self * v } } impl, SA, SB, C> ProjectiveTransformation> for TransformBase where N: Real, SA: OwnedStorage, DimNameSum>, SB: OwnedStorage, C: SubTCategoryOf, SA::Alloc: OwnedAllocator, DimNameSum, SA> + Allocator + Allocator + Allocator, SB::Alloc: OwnedAllocator { #[inline] fn inverse_transform_point(&self, pt: &PointBase) -> PointBase { self.inverse() * pt } #[inline] fn inverse_transform_vector(&self, v: &ColumnVector) -> ColumnVector { self.inverse() * v } } // FIXME: we need to implement an SVD for this. // // impl, SA, SB, C> AffineTransformation> for TransformBase // where N: Real, // SA: OwnedStorage, DimNameSum>, // SB: OwnedStorage, // C: SubTCategoryOf, // SA::Alloc: OwnedAllocator, DimNameSum, SA> + // Allocator + // Allocator + // Allocator, // SB::Alloc: OwnedAllocator { // type PreRotation = OwnedRotation; // type NonUniformScaling = OwnedColumnVector; // type PostRotation = OwnedRotation; // type Translation = OwnedTranslation; // // #[inline] // fn decompose(&self) -> (Self::Translation, Self::PostRotation, Self::NonUniformScaling, Self::PreRotation) { // unimplemented!() // } // }