use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Id, Identity, Inverse, Multiplicative, Real, }; use alga::linear::{ AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation, ProjectiveTransformation, Rotation, Similarity, Transformation, }; use base::allocator::Allocator; use base::dimension::U2; use base::{DefaultAllocator, Vector2}; use geometry::{Point2, UnitComplex}; /* * * Implementations for UnitComplex. * */ impl Identity for UnitComplex { #[inline] fn identity() -> Self { Self::identity() } } impl AbstractMagma for UnitComplex { #[inline] fn operate(&self, rhs: &Self) -> Self { self * rhs } } impl Inverse for UnitComplex { #[inline] fn inverse(&self) -> Self { self.inverse() } #[inline] fn inverse_mut(&mut self) { self.inverse_mut() } } macro_rules! impl_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( impl $marker<$operator> for UnitComplex { } )*} ); impl_structures!( AbstractSemigroup, AbstractQuasigroup, AbstractMonoid, AbstractLoop, AbstractGroup ); impl Transformation> for UnitComplex where DefaultAllocator: Allocator { #[inline] fn transform_point(&self, pt: &Point2) -> Point2 { self * pt } #[inline] fn transform_vector(&self, v: &Vector2) -> Vector2 { self * v } } impl ProjectiveTransformation> for UnitComplex where DefaultAllocator: Allocator { #[inline] fn inverse_transform_point(&self, pt: &Point2) -> Point2 { // FIXME: would it be useful performancewise not to call inverse explicitly (i-e. implement // the inverse transformation explicitly here) ? self.inverse() * pt } #[inline] fn inverse_transform_vector(&self, v: &Vector2) -> Vector2 { self.inverse() * v } } impl AffineTransformation> for UnitComplex where DefaultAllocator: Allocator { type Rotation = Self; type NonUniformScaling = Id; type Translation = Id; #[inline] fn decompose(&self) -> (Id, Self, Id, Self) { (Id::new(), self.clone(), Id::new(), Self::identity()) } #[inline] fn append_translation(&self, _: &Self::Translation) -> Self { self.clone() } #[inline] fn prepend_translation(&self, _: &Self::Translation) -> Self { self.clone() } #[inline] fn append_rotation(&self, r: &Self::Rotation) -> Self { r * self } #[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() } } impl Similarity> for UnitComplex where DefaultAllocator: Allocator { type Scaling = Id; #[inline] fn translation(&self) -> Id { Id::new() } #[inline] fn rotation(&self) -> Self { self.clone() } #[inline] fn scaling(&self) -> Id { Id::new() } } macro_rules! marker_impl( ($($Trait: ident),*) => {$( impl $Trait> for UnitComplex where DefaultAllocator: Allocator { } )*} ); marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation); impl Rotation> for UnitComplex where DefaultAllocator: Allocator { #[inline] fn powf(&self, n: N) -> Option { Some(self.powf(n)) } #[inline] fn rotation_between(a: &Vector2, b: &Vector2) -> Option { Some(Self::rotation_between(a, b)) } #[inline] fn scaled_rotation_between(a: &Vector2, b: &Vector2, s: N) -> Option { Some(Self::scaled_rotation_between(a, b, s)) } }