use num::{One, Zero}; use std::ops::{Div, DivAssign, Index, IndexMut, Mul, MulAssign}; use alga::general::{ClosedAdd, ClosedMul, Real, SubsetOf}; use base::allocator::Allocator; use base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U3, U4}; use base::{DefaultAllocator, MatrixN, Scalar, VectorN}; use geometry::{ Isometry, Point, Rotation, Similarity, SubTCategoryOf, SuperTCategoryOf, TAffine, TCategory, TCategoryMul, TGeneral, TProjective, Transform, Translation, UnitQuaternion, }; /* * * In the following, we provide: * ========================= * * Index<(usize, usize)> * IndexMut<(usize, usize)> (where TCategory == TGeneral) * * (Operators) * * Transform × Isometry * Transform × Rotation * Transform × Similarity * Transform × Transform * Transform × UnitQuaternion * FIXME: Transform × UnitComplex * Transform × Translation * Transform × Vector * Transform × Point * * Isometry × Transform * Rotation × Transform * Similarity × Transform * Translation × Transform * UnitQuaternion × Transform * FIXME: UnitComplex × Transform * * FIXME: Transform ÷ Isometry * Transform ÷ Rotation * FIXME: Transform ÷ Similarity * Transform ÷ Transform * Transform ÷ UnitQuaternion * Transform ÷ Translation * * FIXME: Isometry ÷ Transform * Rotation ÷ Transform * FIXME: Similarity ÷ Transform * Translation ÷ Transform * UnitQuaternion ÷ Transform * FIXME: UnitComplex ÷ Transform * * * (Assignment Operators) * * * Transform ×= Transform * Transform ×= Similarity * Transform ×= Isometry * Transform ×= Rotation * Transform ×= UnitQuaternion * FIXME: Transform ×= UnitComplex * Transform ×= Translation * * Transform ÷= Transform * FIXME: Transform ÷= Similarity * FIXME: Transform ÷= Isometry * Transform ÷= Rotation * Transform ÷= UnitQuaternion * FIXME: Transform ÷= UnitComplex * */ /* * * Indexing. * */ impl Index<(usize, usize)> for Transform where D: DimName + DimNameAdd, DefaultAllocator: Allocator, DimNameSum>, { type Output = N; #[inline] fn index(&self, ij: (usize, usize)) -> &N { self.matrix().index(ij) } } // Only general transformations are mutably indexable. impl IndexMut<(usize, usize)> for Transform where D: DimName + DimNameAdd, DefaultAllocator: Allocator, DimNameSum>, { #[inline] fn index_mut(&mut self, ij: (usize, usize)) -> &mut N { self.matrix_mut().index_mut(ij) } } // Transform × Vector md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory; self: Transform, rhs: VectorN, Output = VectorN; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => { let transform = self.matrix().fixed_slice::(0, 0); if C::has_normalizer() { let normalizer = self.matrix().fixed_slice::(D::dim(), 0); let n = normalizer.tr_dot(&rhs); if !n.is_zero() { return transform * (rhs / n); } } transform * rhs }; ); // Transform × Point md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory where DefaultAllocator: Allocator; self: Transform, rhs: Point, Output = Point; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => { let transform = self.matrix().fixed_slice::(0, 0); let translation = self.matrix().fixed_slice::(0, D::dim()); if C::has_normalizer() { let normalizer = self.matrix().fixed_slice::(D::dim(), 0); let n = normalizer.tr_dot(&rhs.coords) + unsafe { *self.matrix().get_unchecked(D::dim(), D::dim()) }; if !n.is_zero() { return (transform * rhs + translation) / n; } } transform * rhs + translation }; ); // Transform × Transform md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategoryMul, CB: TCategory; self: Transform, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.matrix()); ); // Transform × Rotation md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategoryMul; self: Transform, rhs: Rotation, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // Rotation × Transform md_impl_all!( Mul, mul where N: Real; (D, D), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul; self: Rotation, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // Transform × UnitQuaternion md_impl_all!( Mul, mul where N: Real; (U4, U4), (U4, U1) for C: TCategoryMul; self: Transform, rhs: UnitQuaternion, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // UnitQuaternion × Transform md_impl_all!( Mul, mul where N: Real; (U4, U1), (U4, U4) for C: TCategoryMul; self: UnitQuaternion, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // Transform × Isometry md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> >; self: Transform, rhs: Isometry, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // Isometry × Transform md_impl_all!( Mul, mul where N: Real; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> >; self: Isometry, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // Transform × Similarity md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> >; self: Transform, rhs: Similarity, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // Similarity × Transform md_impl_all!( Mul, mul where N: Real; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> >; self: Similarity, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); /* * * FIXME: don't explicitly build the homogeneous translation matrix. * Directly apply the translation, just as in `Matrix::{append,prepend}_translation`. This has not * been done yet because of the `DimNameDiff` requirement (which is not automatically deduced from * `DimNameAdd` requirement). * */ // Transform × Translation md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul; self: Transform, rhs: Translation, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // Translation × Transform md_impl_all!( Mul, mul where N: Real; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul; self: Translation, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // Transform ÷ Transform md_impl_all!( Div, div where N: Real; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategoryMul, CB: SubTCategoryOf; self: Transform, rhs: Transform, Output = Transform; [val val] => self * rhs.inverse(); [ref val] => self * rhs.inverse(); [val ref] => self * rhs.clone().inverse(); [ref ref] => self * rhs.clone().inverse(); ); // Transform ÷ Rotation md_impl_all!( Div, div where N: Real; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategoryMul; self: Transform, rhs: Rotation, Output = Transform; [val val] => self * rhs.inverse(); [ref val] => self * rhs.inverse(); [val ref] => self * rhs.inverse(); [ref ref] => self * rhs.inverse(); ); // Rotation ÷ Transform md_impl_all!( Div, div where N: Real; (D, D), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul; self: Rotation, rhs: Transform, Output = Transform; [val val] => self.inverse() * rhs; [ref val] => self.inverse() * rhs; [val ref] => self.inverse() * rhs; [ref ref] => self.inverse() * rhs; ); // Transform ÷ UnitQuaternion md_impl_all!( Div, div where N: Real; (U4, U4), (U4, U1) for C: TCategoryMul; self: Transform, rhs: UnitQuaternion, Output = Transform; [val val] => self * rhs.inverse(); [ref val] => self * rhs.inverse(); [val ref] => self * rhs.inverse(); [ref ref] => self * rhs.inverse(); ); // UnitQuaternion ÷ Transform md_impl_all!( Div, div where N: Real; (U4, U1), (U4, U4) for C: TCategoryMul; self: UnitQuaternion, rhs: Transform, Output = Transform; [val val] => self.inverse() * rhs; [ref val] => self.inverse() * rhs; [val ref] => self.inverse() * rhs; [ref ref] => self.inverse() * rhs; ); // // Transform ÷ Isometry // md_impl_all!( // Div, div where N: Real; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> > // where SB::Alloc: Allocator, DimNameSum >; // self: Transform, rhs: Isometry, Output = Transform; // [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.inverse().to_homogeneous()); // [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.inverse().to_homogeneous()); // [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.inverse().to_homogeneous()); // [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.inverse().to_homogeneous()); // ); // // Isometry ÷ Transform // md_impl_all!( // Div, div where N: Real; // (D, U1), (DimNameSum, DimNameSum) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> > // where SA::Alloc: Allocator, DimNameSum >; // self: Isometry, rhs: Transform, Output = Transform; // [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); // [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); // [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // ); // // Transform ÷ Similarity // md_impl_all!( // Div, div where N: Real; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> > // where SB::Alloc: Allocator // where SB::Alloc: Allocator, DimNameSum >; // self: Transform, rhs: Similarity, Output = Transform; // [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); // [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); // [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); // [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); // ); // // Similarity ÷ Transform // md_impl_all!( // Div, div where N: Real; // (D, U1), (DimNameSum, DimNameSum) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> > // where SA::Alloc: Allocator // where SA::Alloc: Allocator, DimNameSum >; // self: Similarity, rhs: Transform, Output = Transform; // [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); // [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); // [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // ); // Transform ÷ Translation md_impl_all!( Div, div where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul; self: Transform, rhs: Translation, Output = Transform; [val val] => self * rhs.inverse(); [ref val] => self * rhs.inverse(); [val ref] => self * rhs.inverse(); [ref ref] => self * rhs.inverse(); ); // Translation ÷ Transform md_impl_all!( Div, div where N: Real; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul; self: Translation, rhs: Transform, Output = Transform; [val val] => self.inverse() * rhs; [ref val] => self.inverse() * rhs; [val ref] => self.inverse() * rhs; [ref ref] => self.inverse() * rhs; ); // Transform ×= Transform md_assign_impl_all!( MulAssign, mul_assign where N: Real; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategory, CB: SubTCategoryOf; self: Transform, rhs: Transform; [val] => *self.matrix_mut_unchecked() *= rhs.into_inner(); [ref] => *self.matrix_mut_unchecked() *= rhs.matrix(); ); // Transform ×= Similarity md_assign_impl_all!( MulAssign, mul_assign where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory, R: SubsetOf> >; self: Transform, rhs: Similarity; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // Transform ×= Isometry md_assign_impl_all!( MulAssign, mul_assign where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory, R: SubsetOf> >; self: Transform, rhs: Isometry; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); /* * * FIXME: don't explicitly build the homogeneous translation matrix. * Directly apply the translation, just as in `Matrix::{append,prepend}_translation`. This has not * been done yet because of the `DimNameDiff` requirement (which is not automatically deduced from * `DimNameAdd` requirement). * */ // Transform ×= Translation md_assign_impl_all!( MulAssign, mul_assign where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory; self: Transform, rhs: Translation; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // Transform ×= Rotation md_assign_impl_all!( MulAssign, mul_assign where N: Real; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategory; self: Transform, rhs: Rotation; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // Transform ×= UnitQuaternion md_assign_impl_all!( MulAssign, mul_assign where N: Real; (U4, U4), (U4, U1) for C: TCategory; self: Transform, rhs: UnitQuaternion; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // Transform ÷= Transform md_assign_impl_all!( DivAssign, div_assign where N: Real; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: SuperTCategoryOf, CB: SubTCategoryOf; self: Transform, rhs: Transform; [val] => *self *= rhs.inverse(); [ref] => *self *= rhs.clone().inverse(); ); // // Transform ÷= Similarity // md_assign_impl_all!( // DivAssign, div_assign; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategory, R: SubsetOf> >; // self: Transform, rhs: Similarity; // [val] => *self *= rhs.inverse(); // [ref] => *self *= rhs.inverse(); // ); // // // // Transform ÷= Isometry // md_assign_impl_all!( // DivAssign, div_assign; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategory, R: SubsetOf> >; // self: Transform, rhs: Isometry; // [val] => *self *= rhs.inverse(); // [ref] => *self *= rhs.inverse(); // ); // Transform ÷= Translation md_assign_impl_all!( DivAssign, div_assign where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory; self: Transform, rhs: Translation; [val] => *self *= rhs.inverse(); [ref] => *self *= rhs.inverse(); ); // Transform ÷= Rotation md_assign_impl_all!( DivAssign, div_assign where N: Real; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategory; self: Transform, rhs: Rotation; [val] => *self *= rhs.inverse(); [ref] => *self *= rhs.inverse(); ); // Transform ÷= UnitQuaternion md_assign_impl_all!( DivAssign, div_assign where N: Real; (U4, U4), (U4, U1) for C: TCategory; self: Transform, rhs: UnitQuaternion; [val] => *self *= rhs.inverse(); [ref] => *self *= rhs.inverse(); );