Medial Code Documentation
Loading...
Searching...
No Matches
Transform.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
7//
8// This Source Code Form is subject to the terms of the Mozilla
9// Public License v. 2.0. If a copy of the MPL was not distributed
10// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11
12#ifndef EIGEN_TRANSFORM_H
13#define EIGEN_TRANSFORM_H
14
15namespace Eigen {
16
17namespace internal {
18
19template<typename Transform>
21{
22 enum
23 {
24 Dim = Transform::Dim,
25 HDim = Transform::HDim,
26 Mode = Transform::Mode,
27 IsProjective = (int(Mode)==int(Projective))
28 };
29};
30
31template< typename TransformType,
32 typename MatrixType,
34 : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1
35 : 2>
37
38template< typename Other,
39 int Mode,
40 int Options,
41 int Dim,
42 int HDim,
43 int OtherRows=Other::RowsAtCompileTime,
44 int OtherCols=Other::ColsAtCompileTime>
46
47template< typename Lhs,
48 typename Rhs,
49 bool AnyProjective =
53
54template< typename Other,
55 int Mode,
56 int Options,
57 int Dim,
58 int HDim,
59 int OtherRows=Other::RowsAtCompileTime,
60 int OtherCols=Other::ColsAtCompileTime>
62
63template<typename TransformType> struct transform_take_affine_part;
64
65template<typename _Scalar, int _Dim, int _Mode, int _Options>
66struct traits<Transform<_Scalar,_Dim,_Mode,_Options> >
67{
68 typedef _Scalar Scalar;
69 typedef Eigen::Index StorageIndex;
70 typedef Dense StorageKind;
71 enum {
72 Dim1 = _Dim==Dynamic ? _Dim : _Dim + 1,
73 RowsAtCompileTime = _Mode==Projective ? Dim1 : _Dim,
74 ColsAtCompileTime = Dim1,
75 MaxRowsAtCompileTime = RowsAtCompileTime,
76 MaxColsAtCompileTime = ColsAtCompileTime,
77 Flags = 0
78 };
79};
80
81template<int Mode> struct transform_make_affine;
82
83} // end namespace internal
84
199template<typename _Scalar, int _Dim, int _Mode, int _Options>
201{
202public:
204 enum {
205 Mode = _Mode,
206 Options = _Options,
207 Dim = _Dim,
208 HDim = _Dim+1,
209 Rows = int(Mode)==(AffineCompact) ? Dim : HDim
210 };
212 typedef _Scalar Scalar;
213 typedef Eigen::Index StorageIndex;
214 typedef Eigen::Index Index;
222 typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> LinearPart;
224 typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> ConstLinearPart;
226 typedef typename internal::conditional<int(Mode)==int(AffineCompact),
227 MatrixType&,
230 typedef typename internal::conditional<int(Mode)==int(AffineCompact),
231 const MatrixType&,
241
242 // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0
243 enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) };
246
247protected:
248
249 MatrixType m_matrix;
250
251public:
252
255 inline Transform()
256 {
257 check_template_params();
258 internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix);
259 }
260
261 inline Transform(const Transform& other)
262 {
263 check_template_params();
264 m_matrix = other.m_matrix;
265 }
266
267 inline explicit Transform(const TranslationType& t)
268 {
269 check_template_params();
270 *this = t;
271 }
272 inline explicit Transform(const UniformScaling<Scalar>& s)
273 {
274 check_template_params();
275 *this = s;
276 }
277 template<typename Derived>
278 inline explicit Transform(const RotationBase<Derived, Dim>& r)
279 {
280 check_template_params();
281 *this = r;
282 }
283
284 inline Transform& operator=(const Transform& other)
285 { m_matrix = other.m_matrix; return *this; }
286
287 typedef internal::transform_take_affine_part<Transform> take_affine_part;
288
290 template<typename OtherDerived>
291 inline explicit Transform(const EigenBase<OtherDerived>& other)
292 {
294 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
295
296 check_template_params();
298 }
299
301 template<typename OtherDerived>
303 {
305 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
306
308 return *this;
309 }
310
311 template<int OtherOptions>
313 {
314 check_template_params();
315 // only the options change, we can directly copy the matrices
316 m_matrix = other.matrix();
317 }
318
319 template<int OtherMode,int OtherOptions>
320 inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other)
321 {
322 check_template_params();
323 // prevent conversions as:
324 // Affine | AffineCompact | Isometry = Projective
325 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)),
326 YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
327
328 // prevent conversions as:
329 // Isometry = Affine | AffineCompact
330 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)),
331 YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
332
333 enum { ModeIsAffineCompact = Mode == int(AffineCompact),
334 OtherModeIsAffineCompact = OtherMode == int(AffineCompact)
335 };
336
337 if(ModeIsAffineCompact == OtherModeIsAffineCompact)
338 {
339 // We need the block expression because the code is compiled for all
340 // combinations of transformations and will trigger a compile time error
341 // if one tries to assign the matrices directly
342 m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0);
343 makeAffine();
344 }
345 else if(OtherModeIsAffineCompact)
346 {
347 typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType;
348 internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix());
349 }
350 else
351 {
352 // here we know that Mode == AffineCompact and OtherMode != AffineCompact.
353 // if OtherMode were Projective, the static assert above would already have caught it.
354 // So the only possibility is that OtherMode == Affine
355 linear() = other.linear();
356 translation() = other.translation();
357 }
358 }
359
360 template<typename OtherDerived>
361 Transform(const ReturnByValue<OtherDerived>& other)
362 {
363 check_template_params();
364 other.evalTo(*this);
365 }
366
367 template<typename OtherDerived>
368 Transform& operator=(const ReturnByValue<OtherDerived>& other)
369 {
370 other.evalTo(*this);
371 return *this;
372 }
373
374 #ifdef EIGEN_QT_SUPPORT
375 inline Transform(const QMatrix& other);
376 inline Transform& operator=(const QMatrix& other);
377 inline QMatrix toQMatrix(void) const;
378 inline Transform(const QTransform& other);
379 inline Transform& operator=(const QTransform& other);
380 inline QTransform toQTransform(void) const;
381 #endif
382
383 Index rows() const { return int(Mode)==int(Projective) ? m_matrix.cols() : (m_matrix.cols()-1); }
384 Index cols() const { return m_matrix.cols(); }
385
388 inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
391 inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
392
394 inline const MatrixType& matrix() const { return m_matrix; }
396 inline MatrixType& matrix() { return m_matrix; }
397
399 inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); }
401 inline LinearPart linear() { return LinearPart(m_matrix,0,0); }
402
404 inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
406 inline AffinePart affine() { return take_affine_part::run(m_matrix); }
407
409 inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); }
411 inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
412
437 // note: this function is defined here because some compilers cannot find the respective declaration
438 template<typename OtherDerived>
439 EIGEN_STRONG_INLINE const typename OtherDerived::PlainObject
442
450 template<typename OtherDerived> friend
454
461 template<typename DiagonalDerived>
464 {
466 res.linear() *= b;
467 return res;
468 }
469
476 template<typename DiagonalDerived>
479 {
481 res.linear().noalias() = a*b.linear();
482 res.translation().noalias() = a*b.translation();
483 if (Mode!=int(AffineCompact))
484 res.matrix().row(Dim) = b.matrix().row(Dim);
485 return res;
486 }
487
488 template<typename OtherDerived>
489 inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
490
492 inline const Transform operator * (const Transform& other) const
493 {
495 }
496
497 #if EIGEN_COMP_ICC
498private:
499 // this intermediate structure permits to workaround a bug in ICC 11:
500 // error: template instantiation resulted in unexpected function type of "Eigen::Transform<double, 3, 32, 0>
501 // (const Eigen::Transform<double, 3, 2, 0> &) const"
502 // (the meaning of a name may have changed since the template declaration -- the type of the template is:
503 // "Eigen::internal::transform_transform_product_impl<Eigen::Transform<double, 3, 32, 0>,
504 // Eigen::Transform<double, 3, Mode, Options>, <expression>>::ResultType (const Eigen::Transform<double, 3, Mode, Options> &) const")
505 //
506 template<int OtherMode,int OtherOptions> struct icc_11_workaround
507 {
509 typedef typename ProductType::ResultType ResultType;
510 };
511
512public:
514 template<int OtherMode,int OtherOptions>
515 inline typename icc_11_workaround<OtherMode,OtherOptions>::ResultType
516 operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
517 {
518 typedef typename icc_11_workaround<OtherMode,OtherOptions>::ProductType ProductType;
519 return ProductType::run(*this,other);
520 }
521 #else
523 template<int OtherMode,int OtherOptions>
524 inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
529 #endif
530
532 void setIdentity() { m_matrix.setIdentity(); }
533
538 static const Transform Identity()
539 {
540 return Transform(MatrixType::Identity());
541 }
542
543 template<typename OtherDerived>
544 inline Transform& scale(const MatrixBase<OtherDerived> &other);
545
546 template<typename OtherDerived>
547 inline Transform& prescale(const MatrixBase<OtherDerived> &other);
548
549 inline Transform& scale(const Scalar& s);
550 inline Transform& prescale(const Scalar& s);
551
552 template<typename OtherDerived>
553 inline Transform& translate(const MatrixBase<OtherDerived> &other);
554
555 template<typename OtherDerived>
556 inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
557
558 template<typename RotationType>
559 inline Transform& rotate(const RotationType& rotation);
560
561 template<typename RotationType>
562 inline Transform& prerotate(const RotationType& rotation);
563
564 Transform& shear(const Scalar& sx, const Scalar& sy);
565 Transform& preshear(const Scalar& sx, const Scalar& sy);
566
567 inline Transform& operator=(const TranslationType& t);
568 inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
569 inline Transform operator*(const TranslationType& t) const;
570
571 inline Transform& operator=(const UniformScaling<Scalar>& t);
572 inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
573 inline TransformTimeDiagonalReturnType operator*(const UniformScaling<Scalar>& s) const
574 {
576 res.scale(s.factor());
577 return res;
578 }
579
580 inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
581
582 template<typename Derived>
583 inline Transform& operator=(const RotationBase<Derived,Dim>& r);
584 template<typename Derived>
585 inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
586 template<typename Derived>
587 inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
588
589 const LinearMatrixType rotation() const;
590 template<typename RotationMatrixType, typename ScalingMatrixType>
591 void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
592 template<typename ScalingMatrixType, typename RotationMatrixType>
593 void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
594
595 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
596 Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
597 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
598
599 inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
600
602 const Scalar* data() const { return m_matrix.data(); }
604 Scalar* data() { return m_matrix.data(); }
605
611 template<typename NewScalarType>
614
616 template<typename OtherScalarType>
618 {
619 check_template_params();
620 m_matrix = other.matrix().template cast<Scalar>();
621 }
622
627 bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
628 { return m_matrix.isApprox(other.m_matrix, prec); }
629
633 {
634 internal::transform_make_affine<int(Mode)>::run(m_matrix);
635 }
636
641 inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
642 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
647 inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
648 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
649
654 inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
655 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
660 inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
661 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
662
663
664 #ifdef EIGEN_TRANSFORM_PLUGIN
665 #include EIGEN_TRANSFORM_PLUGIN
666 #endif
667
668protected:
669 #ifndef EIGEN_PARSED_BY_DOXYGEN
670 static EIGEN_STRONG_INLINE void check_template_params()
671 {
672 EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
673 }
674 #endif
675
676};
677
679typedef Transform<float,2,Isometry> Isometry2f;
681typedef Transform<float,3,Isometry> Isometry3f;
683typedef Transform<double,2,Isometry> Isometry2d;
685typedef Transform<double,3,Isometry> Isometry3d;
686
688typedef Transform<float,2,Affine> Affine2f;
690typedef Transform<float,3,Affine> Affine3f;
692typedef Transform<double,2,Affine> Affine2d;
694typedef Transform<double,3,Affine> Affine3d;
695
697typedef Transform<float,2,AffineCompact> AffineCompact2f;
699typedef Transform<float,3,AffineCompact> AffineCompact3f;
701typedef Transform<double,2,AffineCompact> AffineCompact2d;
703typedef Transform<double,3,AffineCompact> AffineCompact3d;
704
706typedef Transform<float,2,Projective> Projective2f;
708typedef Transform<float,3,Projective> Projective3f;
710typedef Transform<double,2,Projective> Projective2d;
712typedef Transform<double,3,Projective> Projective3d;
713
714/**************************
715*** Optional QT support ***
716**************************/
717
718#ifdef EIGEN_QT_SUPPORT
723template<typename Scalar, int Dim, int Mode,int Options>
724Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other)
725{
726 check_template_params();
727 *this = other;
728}
729
734template<typename Scalar, int Dim, int Mode,int Options>
735Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
736{
737 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
738 if (Mode == int(AffineCompact))
739 m_matrix << other.m11(), other.m21(), other.dx(),
740 other.m12(), other.m22(), other.dy();
741 else
742 m_matrix << other.m11(), other.m21(), other.dx(),
743 other.m12(), other.m22(), other.dy(),
744 0, 0, 1;
745 return *this;
746}
747
754template<typename Scalar, int Dim, int Mode, int Options>
755QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix(void) const
756{
757 check_template_params();
758 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
759 return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
760 m_matrix.coeff(0,1), m_matrix.coeff(1,1),
761 m_matrix.coeff(0,2), m_matrix.coeff(1,2));
762}
763
768template<typename Scalar, int Dim, int Mode,int Options>
769Transform<Scalar,Dim,Mode,Options>::Transform(const QTransform& other)
770{
771 check_template_params();
772 *this = other;
773}
774
779template<typename Scalar, int Dim, int Mode, int Options>
780Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QTransform& other)
781{
782 check_template_params();
783 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
784 if (Mode == int(AffineCompact))
785 m_matrix << other.m11(), other.m21(), other.dx(),
786 other.m12(), other.m22(), other.dy();
787 else
788 m_matrix << other.m11(), other.m21(), other.dx(),
789 other.m12(), other.m22(), other.dy(),
790 other.m13(), other.m23(), other.m33();
791 return *this;
792}
793
798template<typename Scalar, int Dim, int Mode, int Options>
799QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
800{
801 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
802 if (Mode == int(AffineCompact))
803 return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
804 m_matrix.coeff(0,1), m_matrix.coeff(1,1),
805 m_matrix.coeff(0,2), m_matrix.coeff(1,2));
806 else
807 return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
808 m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
809 m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
810}
811#endif
812
813/*********************
814*** Procedural API ***
815*********************/
816
821template<typename Scalar, int Dim, int Mode, int Options>
822template<typename OtherDerived>
823Transform<Scalar,Dim,Mode,Options>&
825{
826 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
827 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
828 linearExt().noalias() = (linearExt() * other.asDiagonal());
829 return *this;
830}
831
836template<typename Scalar, int Dim, int Mode, int Options>
838{
839 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
840 linearExt() *= s;
841 return *this;
842}
843
848template<typename Scalar, int Dim, int Mode, int Options>
849template<typename OtherDerived>
852{
853 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
854 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
855 m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
856 return *this;
857}
858
863template<typename Scalar, int Dim, int Mode, int Options>
865{
866 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
867 m_matrix.template topRows<Dim>() *= s;
868 return *this;
869}
870
875template<typename Scalar, int Dim, int Mode, int Options>
876template<typename OtherDerived>
879{
880 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
881 translationExt() += linearExt() * other;
882 return *this;
883}
884
889template<typename Scalar, int Dim, int Mode, int Options>
890template<typename OtherDerived>
893{
894 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
895 if(int(Mode)==int(Projective))
896 affine() += other * m_matrix.row(Dim);
897 else
898 translation() += other;
899 return *this;
900}
901
919template<typename Scalar, int Dim, int Mode, int Options>
920template<typename RotationType>
923{
924 linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
925 return *this;
926}
927
935template<typename Scalar, int Dim, int Mode, int Options>
936template<typename RotationType>
939{
940 m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
941 * m_matrix.template block<Dim,HDim>(0,0);
942 return *this;
943}
944
950template<typename Scalar, int Dim, int Mode, int Options>
953{
954 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
955 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
956 VectorType tmp = linear().col(0)*sy + linear().col(1);
957 linear() << linear().col(0) + linear().col(1)*sx, tmp;
958 return *this;
959}
960
966template<typename Scalar, int Dim, int Mode, int Options>
969{
970 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
971 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
972 m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
973 return *this;
974}
975
976/******************************************************
977*** Scaling, Translation and Rotation compatibility ***
978******************************************************/
979
980template<typename Scalar, int Dim, int Mode, int Options>
982{
983 linear().setIdentity();
984 translation() = t.vector();
985 makeAffine();
986 return *this;
987}
988
989template<typename Scalar, int Dim, int Mode, int Options>
990inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
991{
992 Transform res = *this;
993 res.translate(t.vector());
994 return res;
995}
996
997template<typename Scalar, int Dim, int Mode, int Options>
998inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
999{
1000 m_matrix.setZero();
1001 linear().diagonal().fill(s.factor());
1002 makeAffine();
1003 return *this;
1004}
1005
1006template<typename Scalar, int Dim, int Mode, int Options>
1007template<typename Derived>
1008inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
1009{
1010 linear() = internal::toRotationMatrix<Scalar,Dim>(r);
1011 translation().setZero();
1012 makeAffine();
1013 return *this;
1014}
1015
1016template<typename Scalar, int Dim, int Mode, int Options>
1017template<typename Derived>
1018inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
1019{
1020 Transform res = *this;
1021 res.rotate(r.derived());
1022 return res;
1023}
1024
1025/************************
1026*** Special functions ***
1027************************/
1028
1036template<typename Scalar, int Dim, int Mode, int Options>
1037const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType
1039{
1040 LinearMatrixType result;
1041 computeRotationScaling(&result, (LinearMatrixType*)0);
1042 return result;
1043}
1044
1045
1057template<typename Scalar, int Dim, int Mode, int Options>
1058template<typename RotationMatrixType, typename ScalingMatrixType>
1060{
1062
1063 Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
1064 VectorType sv(svd.singularValues());
1065 sv.coeffRef(0) *= x;
1066 if(scaling) scaling->lazyAssign(svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint());
1067 if(rotation)
1068 {
1069 LinearMatrixType m(svd.matrixU());
1070 m.col(0) /= x;
1071 rotation->lazyAssign(m * svd.matrixV().adjoint());
1072 }
1073}
1074
1086template<typename Scalar, int Dim, int Mode, int Options>
1087template<typename ScalingMatrixType, typename RotationMatrixType>
1089{
1091
1092 Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
1093 VectorType sv(svd.singularValues());
1094 sv.coeffRef(0) *= x;
1095 if(scaling) scaling->lazyAssign(svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint());
1096 if(rotation)
1097 {
1098 LinearMatrixType m(svd.matrixU());
1099 m.col(0) /= x;
1100 rotation->lazyAssign(m * svd.matrixV().adjoint());
1101 }
1102}
1103
1107template<typename Scalar, int Dim, int Mode, int Options>
1108template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
1112{
1113 linear() = internal::toRotationMatrix<Scalar,Dim>(orientation);
1114 linear() *= scale.asDiagonal();
1115 translation() = position;
1116 makeAffine();
1117 return *this;
1118}
1119
1120namespace internal {
1121
1122template<int Mode>
1124{
1125 template<typename MatrixType>
1126 static void run(MatrixType &mat)
1127 {
1128 static const int Dim = MatrixType::ColsAtCompileTime-1;
1129 mat.template block<1,Dim>(Dim,0).setZero();
1130 mat.coeffRef(Dim,Dim) = typename MatrixType::Scalar(1);
1131 }
1132};
1133
1134template<>
1136{
1137 template<typename MatrixType> static void run(MatrixType &) { }
1138};
1139
1140// selector needed to avoid taking the inverse of a 3x4 matrix
1141template<typename TransformType, int Mode=TransformType::Mode>
1143{
1144 static inline void run(const TransformType&, TransformType&)
1145 {}
1146};
1147
1148template<typename TransformType>
1150{
1151 static inline void run(const TransformType& m, TransformType& res)
1152 {
1153 res.matrix() = m.matrix().inverse();
1154 }
1155};
1156
1157} // end namespace internal
1158
1159
1180template<typename Scalar, int Dim, int Mode, int Options>
1183{
1184 Transform res;
1185 if (hint == Projective)
1186 {
1188 }
1189 else
1190 {
1191 if (hint == Isometry)
1192 {
1193 res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
1194 }
1195 else if(hint&Affine)
1196 {
1197 res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
1198 }
1199 else
1200 {
1201 eigen_assert(false && "Invalid transform traits in Transform::Inverse");
1202 }
1203 // translation and remaining parts
1204 res.matrix().template topRightCorner<Dim,1>()
1205 = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
1206 res.makeAffine(); // we do need this, because in the beginning res is uninitialized
1207 }
1208 return res;
1209}
1210
1211namespace internal {
1212
1213/*****************************************************
1214*** Specializations of take affine part ***
1215*****************************************************/
1216
1217template<typename TransformType> struct transform_take_affine_part {
1218 typedef typename TransformType::MatrixType MatrixType;
1219 typedef typename TransformType::AffinePart AffinePart;
1220 typedef typename TransformType::ConstAffinePart ConstAffinePart;
1221 static inline AffinePart run(MatrixType& m)
1222 { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
1223 static inline ConstAffinePart run(const MatrixType& m)
1224 { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
1225};
1226
1227template<typename Scalar, int Dim, int Options>
1230 static inline MatrixType& run(MatrixType& m) { return m; }
1231 static inline const MatrixType& run(const MatrixType& m) { return m; }
1232};
1233
1234/*****************************************************
1235*** Specializations of construct from matrix ***
1236*****************************************************/
1237
1238template<typename Other, int Mode, int Options, int Dim, int HDim>
1239struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim>
1240{
1241 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
1242 {
1243 transform->linear() = other;
1244 transform->translation().setZero();
1245 transform->makeAffine();
1246 }
1247};
1248
1249template<typename Other, int Mode, int Options, int Dim, int HDim>
1250struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim>
1251{
1252 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
1253 {
1254 transform->affine() = other;
1255 transform->makeAffine();
1256 }
1257};
1258
1259template<typename Other, int Mode, int Options, int Dim, int HDim>
1260struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim>
1261{
1262 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
1263 { transform->matrix() = other; }
1264};
1265
1266template<typename Other, int Options, int Dim, int HDim>
1267struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim>
1268{
1269 static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other)
1270 { transform->matrix() = other.template block<Dim,HDim>(0,0); }
1271};
1272
1273/**********************************************************
1274*** Specializations of operator* with rhs EigenBase ***
1275**********************************************************/
1276
1277template<int LhsMode,int RhsMode>
1279{
1280 enum
1281 {
1282 Mode =
1283 (LhsMode == (int)Projective || RhsMode == (int)Projective ) ? Projective :
1284 (LhsMode == (int)Affine || RhsMode == (int)Affine ) ? Affine :
1285 (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact :
1286 (LhsMode == (int)Isometry || RhsMode == (int)Isometry ) ? Isometry : Projective
1287 };
1288};
1289
1290template< typename TransformType, typename MatrixType >
1291struct transform_right_product_impl< TransformType, MatrixType, 0 >
1292{
1293 typedef typename MatrixType::PlainObject ResultType;
1294
1295 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
1296 {
1297 return T.matrix() * other;
1298 }
1299};
1300
1301template< typename TransformType, typename MatrixType >
1302struct transform_right_product_impl< TransformType, MatrixType, 1 >
1303{
1304 enum {
1305 Dim = TransformType::Dim,
1306 HDim = TransformType::HDim,
1307 OtherRows = MatrixType::RowsAtCompileTime,
1308 OtherCols = MatrixType::ColsAtCompileTime
1309 };
1310
1311 typedef typename MatrixType::PlainObject ResultType;
1312
1313 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
1314 {
1315 EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
1316
1317 typedef Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime)==Dim> TopLeftLhs;
1318
1319 ResultType res(other.rows(),other.cols());
1320 TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
1321 res.row(OtherRows-1) = other.row(OtherRows-1);
1322
1323 return res;
1324 }
1325};
1326
1327template< typename TransformType, typename MatrixType >
1328struct transform_right_product_impl< TransformType, MatrixType, 2 >
1329{
1330 enum {
1331 Dim = TransformType::Dim,
1332 HDim = TransformType::HDim,
1333 OtherRows = MatrixType::RowsAtCompileTime,
1334 OtherCols = MatrixType::ColsAtCompileTime
1335 };
1336
1337 typedef typename MatrixType::PlainObject ResultType;
1338
1339 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
1340 {
1341 EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
1342
1344 ResultType res(Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(),1,other.cols()));
1345 TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other;
1346
1347 return res;
1348 }
1349};
1350
1351/**********************************************************
1352*** Specializations of operator* with lhs EigenBase ***
1353**********************************************************/
1354
1355// generic HDim x HDim matrix * T => Projective
1356template<typename Other,int Mode, int Options, int Dim, int HDim>
1357struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim>
1358{
1360 typedef typename TransformType::MatrixType MatrixType;
1362 static ResultType run(const Other& other,const TransformType& tr)
1363 { return ResultType(other * tr.matrix()); }
1364};
1365
1366// generic HDim x HDim matrix * AffineCompact => Projective
1367template<typename Other, int Options, int Dim, int HDim>
1368struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim>
1369{
1371 typedef typename TransformType::MatrixType MatrixType;
1373 static ResultType run(const Other& other,const TransformType& tr)
1374 {
1375 ResultType res;
1376 res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix();
1377 res.matrix().col(Dim) += other.col(Dim);
1378 return res;
1379 }
1380};
1381
1382// affine matrix * T
1383template<typename Other,int Mode, int Options, int Dim, int HDim>
1384struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim>
1385{
1387 typedef typename TransformType::MatrixType MatrixType;
1388 typedef TransformType ResultType;
1389 static ResultType run(const Other& other,const TransformType& tr)
1390 {
1391 ResultType res;
1392 res.affine().noalias() = other * tr.matrix();
1393 res.matrix().row(Dim) = tr.matrix().row(Dim);
1394 return res;
1395 }
1396};
1397
1398// affine matrix * AffineCompact
1399template<typename Other, int Options, int Dim, int HDim>
1400struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim>
1401{
1403 typedef typename TransformType::MatrixType MatrixType;
1404 typedef TransformType ResultType;
1405 static ResultType run(const Other& other,const TransformType& tr)
1406 {
1407 ResultType res;
1408 res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix();
1409 res.translation() += other.col(Dim);
1410 return res;
1411 }
1412};
1413
1414// linear matrix * T
1415template<typename Other,int Mode, int Options, int Dim, int HDim>
1416struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim>
1417{
1419 typedef typename TransformType::MatrixType MatrixType;
1420 typedef TransformType ResultType;
1421 static ResultType run(const Other& other, const TransformType& tr)
1422 {
1423 TransformType res;
1424 if(Mode!=int(AffineCompact))
1425 res.matrix().row(Dim) = tr.matrix().row(Dim);
1426 res.matrix().template topRows<Dim>().noalias()
1427 = other * tr.matrix().template topRows<Dim>();
1428 return res;
1429 }
1430};
1431
1432/**********************************************************
1433*** Specializations of operator* with another Transform ***
1434**********************************************************/
1435
1436template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
1438{
1443 static ResultType run(const Lhs& lhs, const Rhs& rhs)
1444 {
1445 ResultType res;
1446 res.linear() = lhs.linear() * rhs.linear();
1447 res.translation() = lhs.linear() * rhs.translation() + lhs.translation();
1448 res.makeAffine();
1449 return res;
1450 }
1451};
1452
1453template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
1455{
1459 static ResultType run(const Lhs& lhs, const Rhs& rhs)
1460 {
1461 return ResultType( lhs.matrix() * rhs.matrix() );
1462 }
1463};
1464
1465template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
1467{
1471 static ResultType run(const Lhs& lhs, const Rhs& rhs)
1472 {
1473 ResultType res;
1474 res.matrix().template topRows<Dim>() = lhs.matrix() * rhs.matrix();
1475 res.matrix().row(Dim) = rhs.matrix().row(Dim);
1476 return res;
1477 }
1478};
1479
1480template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
1482{
1486 static ResultType run(const Lhs& lhs, const Rhs& rhs)
1487 {
1488 ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix());
1489 res.matrix().col(Dim) += lhs.matrix().col(Dim);
1490 return res;
1491 }
1492};
1493
1494} // end namespace internal
1495
1496} // end namespace Eigen
1497
1498#endif // EIGEN_TRANSFORM_H
Expression of a fixed-size or dynamic-size block.
Definition Block.h:106
Pseudo expression representing a solving operation.
Definition Solve.h:63
\geometry_module
Definition Transform.h:201
const MatrixType & matrix() const
Definition Transform.h:394
Block< MatrixType, Dim, Dim, int(Mode)==(AffineCompact) &&(Options &RowMajor)==0 > LinearPart
type of read/write reference to the linear part of the transformation
Definition Transform.h:222
const LinearMatrixType rotation() const
Definition Transform.h:1038
Transform & preshear(const Scalar &sx, const Scalar &sy)
Applies on the left the shear transformation represented by the vector other to *this and returns a r...
Definition Transform.h:968
Transform()
Default constructor without initialization of the meaningful coefficients.
Definition Transform.h:255
Transform & operator=(const EigenBase< OtherDerived > &other)
Set *this from a Dim^2 or (Dim+1)^2 matrix.
Definition Transform.h:302
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
decomposes the linear part of the transformation as a product rotation x scaling, the scaling being n...
Definition Transform.h:1088
Transform(const Transform< OtherScalarType, Dim, Mode, Options > &other)
Copy constructor with scalar type conversion.
Definition Transform.h:617
MatrixType & matrix()
Definition Transform.h:396
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar, _Dim==Dynamic ? Dynamic :(_Dim+1) *(_Dim+1)) enum
Definition Transform.h:203
internal::make_proper_matrix_type< Scalar, Rows, HDim, Options >::type MatrixType
type of the matrix used to represent the transformation
Definition Transform.h:216
const Block< ConstMatrixType, Dim, 1,!(internal::traits< MatrixType >::Flags &RowMajorBit)> ConstTranslationPart
type of a read reference to the translation part of the rotation
Definition Transform.h:238
Matrix< Scalar, Dim, Dim, Options > LinearMatrixType
type of the matrix used to represent the linear part of the transformation
Definition Transform.h:220
Eigen::Index Index
Definition Transform.h:214
_Scalar Scalar
the scalar type of the coefficients
Definition Transform.h:212
Transform< Scalar, Dim, TransformTimeDiagonalMode > TransformTimeDiagonalReturnType
The return type of the product between a diagonal matrix and a transform.
Definition Transform.h:245
static const Transform Identity()
Returns an identity transformation.
Definition Transform.h:538
Scalar * data()
Definition Transform.h:604
internal::cast_return_type< Transform, Transform< NewScalarType, Dim, Mode, Options > >::type cast() const
Definition Transform.h:612
internal::conditional< int(Mode)==int(AffineCompact), MatrixType &, Block< MatrixType, Dim, HDim > >::type AffinePart
type of read/write reference to the affine part of the transformation
Definition Transform.h:228
Translation< Scalar, Dim > TranslationType
corresponding translation type
Definition Transform.h:240
internal::conditional< int(Mode)==int(AffineCompact), constMatrixType &, constBlock< constMatrixType, Dim, HDim > >::type ConstAffinePart
type of read reference to the affine part of the transformation
Definition Transform.h:232
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
decomposes the linear part of the transformation as a product rotation x scaling, the scaling being n...
Definition Transform.h:1059
ConstAffinePart affine() const
Definition Transform.h:404
Scalar operator()(Index row, Index col) const
shortcut for m_matrix(row,col);
Definition Transform.h:388
AffinePart affine()
Definition Transform.h:406
friend const internal::transform_left_product_impl< OtherDerived, Mode, Options, _Dim, _Dim+1 >::ResultType operator*(const EigenBase< OtherDerived > &a, const Transform &b)
Definition Transform.h:452
TranslationPart translation()
Definition Transform.h:411
Block< MatrixType, Dim, 1,!(internal::traits< MatrixType >::Flags &RowMajorBit)> TranslationPart
type of a read/write reference to the translation part of the rotation
Definition Transform.h:236
Matrix< Scalar, Dim, 1 > VectorType
type of a vector
Definition Transform.h:234
Transform inverse(TransformTraits traits=(TransformTraits) Mode) const
Definition Transform.h:1182
bool isApprox(const Transform &other, const typename NumTraits< Scalar >::Real &prec=NumTraits< Scalar >::dummy_precision()) const
Definition Transform.h:627
void makeAffine()
Sets the last row to [0 ... 0 1].
Definition Transform.h:632
const Block< ConstMatrixType, Dim, Dim, int(Mode)==(AffineCompact) &&(Options &RowMajor)==0 > ConstLinearPart
type of read reference to the linear part of the transformation
Definition Transform.h:224
void setIdentity()
Definition Transform.h:532
LinearPart linear()
Definition Transform.h:401
ConstTranslationPart translation() const
Definition Transform.h:409
const Scalar * data() const
Definition Transform.h:602
Transform & shear(const Scalar &sx, const Scalar &sy)
Applies on the right the shear transformation represented by the vector other to *this and returns a ...
Definition Transform.h:952
Transform(const EigenBase< OtherDerived > &other)
Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix.
Definition Transform.h:291
const MatrixType ConstMatrixType
constified MatrixType
Definition Transform.h:218
ConstLinearPart linear() const
Definition Transform.h:399
Definition svm.cpp:197
TransformTraits
Enum used to specify how a particular transformation is stored in a matrix.
Definition Constants.h:445
@ DontAlign
Don't require alignment for the matrix itself (the array of coefficients, if dynamically allocated,...
Definition Constants.h:326
@ RowMajor
Storage order is row major (see TopicStorageOrders).
Definition Constants.h:322
@ ComputeFullV
Used in JacobiSVD to indicate that the square matrix V is to be computed.
Definition Constants.h:387
@ ComputeFullU
Used in JacobiSVD to indicate that the square matrix U is to be computed.
Definition Constants.h:383
@ Affine
Transformation is an affine transformation stored as a (Dim+1)^2 matrix whose last row is assumed to ...
Definition Constants.h:450
@ Projective
Transformation is a general projective transformation stored as a (Dim+1)^2 matrix.
Definition Constants.h:454
@ AffineCompact
Transformation is an affine transformation stored as a (Dim) x (Dim+1) matrix.
Definition Constants.h:452
@ Isometry
Transformation is an isometry.
Definition Constants.h:447
const unsigned int RowMajorBit
for a matrix, this means that the storage order is row-major.
Definition Constants.h:61
The type used to identify a dense storage.
Definition Constants.h:490
Holds information about the various numeric (i.e.
Definition NumTraits.h:108
Definition XprHelper.h:500
Definition Meta.h:34
Definition Meta.h:39
Definition ForwardDeclarations.h:17
Definition Transform.h:1124
Definition Transform.h:21
Definition Meta.h:30