use alga::general::{AbstractMagma, AbstractGroup, AbstractLoop, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Real, Inverse, Multiplicative, Identity, Id}; use alga::linear::{Transformation, Similarity, AffineTransformation, Isometry, DirectIsometry, OrthogonalTransformation, ProjectiveTransformation, Rotation}; use core::ColumnVector; use core::dimension::{DimName, U1}; use core::storage::OwnedStorage; use core::allocator::OwnedAllocator; use geometry::{RotationBase, PointBase}; /* * * Algebraic structures. * */ impl Identity for RotationBase where N: Real, S: OwnedStorage, S::Alloc: OwnedAllocator { #[inline] fn identity() -> Self { Self::identity() } } impl Inverse for RotationBase where N: Real, S: OwnedStorage, S::Alloc: OwnedAllocator { #[inline] fn inverse(&self) -> Self { self.transpose() } #[inline] fn inverse_mut(&mut self) { self.transpose_mut() } } impl AbstractMagma for RotationBase where N: Real, S: OwnedStorage, S::Alloc: OwnedAllocator { #[inline] fn operate(&self, rhs: &Self) -> Self { self * rhs } } macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( impl $marker<$operator> for RotationBase where N: Real, S: OwnedStorage, S::Alloc: OwnedAllocator { } )*} ); impl_multiplicative_structures!( AbstractSemigroup, AbstractMonoid, AbstractQuasigroup, AbstractLoop, AbstractGroup ); /* * * Transformation groups. * */ impl Transformation> for RotationBase where N: Real, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { #[inline] fn transform_point(&self, pt: &PointBase) -> PointBase { self * pt } #[inline] fn transform_vector(&self, v: &ColumnVector) -> ColumnVector { self * v } } impl ProjectiveTransformation> for RotationBase where N: Real, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { #[inline] fn inverse_transform_point(&self, pt: &PointBase) -> PointBase { PointBase::from_coordinates(self.inverse_transform_vector(&pt.coords)) } #[inline] fn inverse_transform_vector(&self, v: &ColumnVector) -> ColumnVector { self.matrix().tr_mul(v) } } impl AffineTransformation> for RotationBase where N: Real, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { 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 RotationBase where N: Real, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { 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 RotationBase where N: Real, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { } )*} ); marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation); /// Subgroups of the n-dimensional rotation group `SO(n)`. impl Rotation> for RotationBase where N: Real, SA: OwnedStorage, SB: OwnedStorage, SA::Alloc: OwnedAllocator, SB::Alloc: OwnedAllocator { #[inline] fn powf(&self, _: N) -> Option { // XXX: Add the general case. // XXX: Use specialization for 2D and 3D. unimplemented!() } #[inline] fn rotation_between(_: &ColumnVector, _: &ColumnVector) -> Option { // XXX: Add the general case. // XXX: Use specialization for 2D and 3D. unimplemented!() } #[inline] fn scaled_rotation_between(_: &ColumnVector, _: &ColumnVector, _: N) -> Option { // XXX: Add the general case. // XXX: Use specialization for 2D and 3D. unimplemented!() } } /* impl Matrix for RotationBase { type Field = N; type Row = Matrix; type Column = Matrix; type Transpose = Self; #[inline] fn nrows(&self) -> usize { self.submatrix.nrows() } #[inline] fn ncolumns(&self) -> usize { self.submatrix.ncolumns() } #[inline] fn row(&self, i: usize) -> Self::Row { self.submatrix.row(i) } #[inline] fn column(&self, i: usize) -> Self::Column { self.submatrix.column(i) } #[inline] fn get(&self, i: usize, j: usize) -> Self::Field { self.submatrix[(i, j)] } #[inline] unsafe fn get_unchecked(&self, i: usize, j: usize) -> Self::Field { self.submatrix.at_fast(i, j) } #[inline] fn transpose(&self) -> Self::Transpose { RotationBase::from_matrix_unchecked(self.submatrix.transpose()) } } impl SquareMatrix for RotationBase { type Vector = Matrix; #[inline] fn diagonal(&self) -> Self::Coordinates { self.submatrix.diagonal() } #[inline] fn determinant(&self) -> Self::Field { ::one() } #[inline] fn try_inverse(&self) -> Option { Some(::transpose(self)) } #[inline] fn try_inverse_mut(&mut self) -> bool { self.transpose_mut(); true } #[inline] fn transpose_mut(&mut self) { self.submatrix.transpose_mut() } } impl InversibleSquareMatrix for RotationBase { } */