Eigen  5.0.1
 
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// SPDX-License-Identifier: MPL-2.0
12
13#ifndef EIGEN_TRANSFORM_H
14#define EIGEN_TRANSFORM_H
15
16// IWYU pragma: private
17#include "./InternalHeaderCheck.h"
18
19namespace Eigen {
20
21namespace internal {
22
23template <typename Transform>
24struct transform_traits {
25 enum {
26 Dim = Transform::Dim,
27 HDim = Transform::HDim,
28 Mode = Transform::Mode,
29 IsProjective = (int(Mode) == int(Projective))
30 };
31};
32
33template <typename TransformType, typename MatrixType,
34 int Case = transform_traits<TransformType>::IsProjective ? 0
35 : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1
36 : 2,
37 int RhsCols = MatrixType::ColsAtCompileTime>
38struct transform_right_product_impl;
39
40template <typename Other, int Mode, int Options, int Dim, int HDim, int OtherRows = Other::RowsAtCompileTime,
41 int OtherCols = Other::ColsAtCompileTime>
42struct transform_left_product_impl;
43
44template <typename Lhs, typename Rhs,
45 bool AnyProjective = transform_traits<Lhs>::IsProjective || transform_traits<Rhs>::IsProjective>
46struct transform_transform_product_impl;
47
48template <typename Other, int Mode, int Options, int Dim, int HDim, int OtherRows = Other::RowsAtCompileTime,
49 int OtherCols = Other::ColsAtCompileTime>
50struct transform_construct_from_matrix;
51
52template <typename TransformType>
53struct transform_take_affine_part;
54
55template <typename LhsScalar, typename RhsScalar, typename BinaryOp, typename TargetScalar, typename = void>
56struct has_matching_binary_op_traits : std::false_type {};
57
58template <typename LhsScalar, typename RhsScalar, typename BinaryOp, typename TargetScalar>
59struct has_matching_binary_op_traits<LhsScalar, RhsScalar, BinaryOp, TargetScalar,
60 void_t<typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, BinaryOp>::ReturnType>>
61 : std::integral_constant<
62 bool, std::is_convertible<typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, BinaryOp>::ReturnType,
63 TargetScalar>::value ||
64 std::is_assignable<TargetScalar&,
65 typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, BinaryOp>::ReturnType>::value> {};
66
67template <typename TargetScalar, typename Derived, typename LhsScalar, typename RhsScalar, typename BinaryOp,
68 typename = void>
69struct transform_convert_arg {
70 EIGEN_DEVICE_FUNC static auto run(const MatrixBase<Derived>& mat) { return mat.template cast<TargetScalar>(); }
71};
72
73template <typename TargetScalar, typename Derived, typename LhsScalar, typename RhsScalar, typename BinaryOp>
74struct transform_convert_arg<
75 TargetScalar, Derived, LhsScalar, RhsScalar, BinaryOp,
76 std::enable_if_t<std::is_same<typename Derived::Scalar, TargetScalar>::value ||
77 has_matching_binary_op_traits<LhsScalar, RhsScalar, BinaryOp, TargetScalar>::value>> {
78 EIGEN_DEVICE_FUNC static const Derived& run(const MatrixBase<Derived>& mat) { return mat.derived(); }
79};
80
81template <typename Scalar_, int Dim_, int Mode_, int Options_>
82struct traits<Transform<Scalar_, Dim_, Mode_, Options_> > {
83 using Scalar = Scalar_;
84 using StorageIndex = Eigen::Index;
85 using StorageKind = Dense;
86 enum {
87 Dim1 = Dim_ == Dynamic ? Dim_ : Dim_ + 1,
88 RowsAtCompileTime = Mode_ == Projective ? Dim1 : Dim_,
89 ColsAtCompileTime = Dim1,
90 MaxRowsAtCompileTime = RowsAtCompileTime,
91 MaxColsAtCompileTime = ColsAtCompileTime,
92 Flags = 0
93 };
94};
95
96template <int Mode>
97struct transform_make_affine;
98
99} // end namespace internal
100
221template <typename Scalar_, int Dim_, int Mode_, int Options_>
223 public:
225 Dim_ == Dynamic ? Dynamic : (Dim_ + 1) * (Dim_ + 1))
226 enum {
227 Mode = Mode_,
228 Options = Options_,
229 Dim = Dim_,
230 HDim = Dim_ + 1,
231 Rows = int(Mode) == int(AffineCompact) ? Dim : HDim
232 };
233
234 using Scalar = Scalar_;
235 using StorageIndex = Eigen::Index;
236 using Index = Eigen::Index;
238 using MatrixType = typename internal::make_proper_matrix_type<Scalar, Rows, HDim, Options>::type;
244 using LinearPart = Block<MatrixType, Dim, Dim, int(Mode) == (AffineCompact) && (int(Options) & RowMajor) == 0>;
247 const Block<ConstMatrixType, Dim, Dim, int(Mode) == (AffineCompact) && (int(Options) & RowMajor) == 0>;
249 using AffinePart = std::conditional_t<int(Mode) == int(AffineCompact), MatrixType&, Block<MatrixType, Dim, HDim>>;
252 std::conditional_t<int(Mode) == int(AffineCompact), const MatrixType&, const Block<const MatrixType, Dim, HDim>>;
256 using TranslationPart = Block<MatrixType, Dim, 1, !(internal::traits<MatrixType>::Flags & RowMajorBit)>;
259 const Block<ConstMatrixType, Dim, 1, !(internal::traits<MatrixType>::Flags & RowMajorBit)>;
262
264 using TransformTimeDiagonalReturnType = Transform<Scalar, Dim, (Mode == int(Isometry)) ? int(Affine) : int(Mode)>;
265
266 protected:
267 MatrixType m_matrix;
268
269 public:
272 EIGEN_DEVICE_FUNC inline Transform() {
273 check_template_params();
274 internal::transform_make_affine<(int(Mode) == Affine || int(Mode) == Isometry) ? Affine : AffineCompact>::run(
275 m_matrix);
276 }
277
278 // These conversion ctors are intentionally `explicit`: keeping copy-init
279 // (`Transform t = rot;`) from compiling stops a Dim+1 x Dim+1 matrix
280 // from being silently materialized in function-call argument lists.
281 // Use direct-init (`Transform t(rot);`) or assignment (`Transform t; t = rot;`)
282 // instead. See bug #1209.
283 EIGEN_DEVICE_FUNC inline explicit Transform(const TranslationType& t) {
284 check_template_params();
285 *this = t;
286 }
287 EIGEN_DEVICE_FUNC inline explicit Transform(const UniformScaling<Scalar>& s) {
288 check_template_params();
289 *this = s;
290 }
291 template <typename Derived>
292 EIGEN_DEVICE_FUNC inline explicit Transform(const RotationBase<Derived, Dim>& r) {
293 check_template_params();
294 *this = r;
295 }
296
297 using take_affine_part = internal::transform_take_affine_part<Transform>;
298
300 template <typename OtherDerived>
301 EIGEN_DEVICE_FUNC inline explicit Transform(const EigenBase<OtherDerived>& other) {
302 EIGEN_STATIC_ASSERT(
303 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
304 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
305
306 check_template_params();
307 internal::transform_construct_from_matrix<OtherDerived, Mode, Options, Dim, HDim>::run(this, other.derived());
308 }
309
311 template <typename OtherDerived>
312 EIGEN_DEVICE_FUNC inline Transform& operator=(const EigenBase<OtherDerived>& other) {
313 EIGEN_STATIC_ASSERT(
314 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
315 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
316
317 internal::transform_construct_from_matrix<OtherDerived, Mode, Options, Dim, HDim>::run(this, other.derived());
318 return *this;
319 }
320
321 template <int OtherOptions>
322 EIGEN_DEVICE_FUNC inline Transform(const Transform<Scalar, Dim, Mode, OtherOptions>& other) {
323 check_template_params();
324 // only the options change, we can directly copy the matrices
325 m_matrix = other.matrix();
326 }
327
328 template <int OtherMode, int OtherOptions>
329 EIGEN_DEVICE_FUNC inline Transform(const Transform<Scalar, Dim, OtherMode, OtherOptions>& other) {
330 check_template_params();
331 // prevent conversions as:
332 // Affine | AffineCompact | Isometry = Projective
333 EIGEN_STATIC_ASSERT(internal::check_implication(OtherMode == int(Projective), Mode == int(Projective)),
334 YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
335
336 // prevent conversions as:
337 // Isometry = Affine | AffineCompact
338 EIGEN_STATIC_ASSERT(
339 internal::check_implication(OtherMode == int(Affine) || OtherMode == int(AffineCompact), Mode != int(Isometry)),
340 YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
341
342 enum {
343 ModeIsAffineCompact = Mode == int(AffineCompact),
344 OtherModeIsAffineCompact = OtherMode == int(AffineCompact)
345 };
346
347 if (EIGEN_CONST_CONDITIONAL(ModeIsAffineCompact == OtherModeIsAffineCompact)) {
348 // We need the block expression because the code is compiled for all
349 // combinations of transformations and will trigger a compile time error
350 // if one tries to assign the matrices directly
351 m_matrix.template block<Dim, Dim + 1>(0, 0) = other.matrix().template block<Dim, Dim + 1>(0, 0);
352 makeAffine();
353 } else if (EIGEN_CONST_CONDITIONAL(OtherModeIsAffineCompact)) {
355 internal::transform_construct_from_matrix<OtherMatrixType, Mode, Options, Dim, HDim>::run(this, other.matrix());
356 } else {
357 // here we know that Mode == AffineCompact and OtherMode != AffineCompact.
358 // if OtherMode were Projective, the static assert above would already have caught it.
359 // So the only possibility is that OtherMode == Affine
360 linear() = other.linear();
361 translation() = other.translation();
362 }
363 }
364
365 template <typename OtherDerived>
366 EIGEN_DEVICE_FUNC Transform(const ReturnByValue<OtherDerived>& other) {
367 check_template_params();
368 other.evalTo(*this);
369 }
370
371 template <typename OtherDerived>
372 EIGEN_DEVICE_FUNC Transform& operator=(const ReturnByValue<OtherDerived>& other) {
373 other.evalTo(*this);
374 return *this;
375 }
376
377#ifdef EIGEN_QT_SUPPORT
378#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
379 inline Transform(const QMatrix& other);
380 inline Transform& operator=(const QMatrix& other);
381 inline QMatrix toQMatrix(void) const;
382#endif
383 inline Transform(const QTransform& other);
384 inline Transform& operator=(const QTransform& other);
385 inline QTransform toQTransform(void) const;
386#endif
387
388 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept {
389 return int(Mode) == int(Projective) ? m_matrix.cols() : (m_matrix.cols() - 1);
390 }
391 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); }
392
395 EIGEN_DEVICE_FUNC inline Scalar operator()(Index row, Index col) const { return m_matrix(row, col); }
398 EIGEN_DEVICE_FUNC inline Scalar& operator()(Index row, Index col) { return m_matrix(row, col); }
399
400#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
403 EIGEN_DEVICE_FUNC inline Scalar operator[](Index row, Index col) const { return m_matrix[row, col]; }
406 EIGEN_DEVICE_FUNC inline Scalar& operator[](Index row, Index col) { return m_matrix[row, col]; }
407#endif
408
410 EIGEN_DEVICE_FUNC inline const MatrixType& matrix() const { return m_matrix; }
412 EIGEN_DEVICE_FUNC inline MatrixType& matrix() { return m_matrix; }
413
415 EIGEN_DEVICE_FUNC inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix, 0, 0); }
417 EIGEN_DEVICE_FUNC inline LinearPart linear() { return LinearPart(m_matrix, 0, 0); }
418
420 EIGEN_DEVICE_FUNC inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
422 EIGEN_DEVICE_FUNC inline AffinePart affine() { return take_affine_part::run(m_matrix); }
423
425 EIGEN_DEVICE_FUNC inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix, 0, Dim); }
427 EIGEN_DEVICE_FUNC inline TranslationPart translation() { return TranslationPart(m_matrix, 0, Dim); }
428
454 // note: this function is defined here because some compilers cannot find the respective declaration
455 template <typename OtherDerived>
456 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform,
457 OtherDerived>::ResultType
459 return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this, other.derived());
460 }
461
469 template <typename OtherDerived>
470 friend EIGEN_DEVICE_FUNC inline const typename internal::transform_left_product_impl<OtherDerived, Mode, Options,
471 Dim_, Dim_ + 1>::ResultType
473 return internal::transform_left_product_impl<OtherDerived, Mode, Options, Dim, HDim>::run(a.derived(), b);
474 }
475
482 template <typename DiagonalDerived>
483 EIGEN_DEVICE_FUNC inline const TransformTimeDiagonalReturnType operator*(
484 const DiagonalBase<DiagonalDerived>& b) const {
486 res.linearExt() *= b;
487 return res;
488 }
489
496 template <typename DiagonalDerived>
498 const Transform& b) {
500 res.linear().noalias() = a * b.linear();
501 res.translation().noalias() = a * b.translation();
502 if (EIGEN_CONST_CONDITIONAL(Mode != int(AffineCompact))) res.matrix().row(Dim) = b.matrix().row(Dim);
503 return res;
504 }
505
506 template <typename OtherDerived>
507 EIGEN_DEVICE_FUNC inline Transform& operator*=(const MatrixBase<OtherDerived>& other) {
508 return *this = *this * other;
509 }
510
512 EIGEN_DEVICE_FUNC inline const Transform operator*(const Transform& other) const {
513 return internal::transform_transform_product_impl<Transform, Transform>::run(*this, other);
514 }
515
517 template <int OtherMode, int OtherOptions>
518 EIGEN_DEVICE_FUNC inline
519 typename internal::transform_transform_product_impl<Transform,
522 return internal::transform_transform_product_impl<Transform, Transform<Scalar, Dim, OtherMode, OtherOptions> >::run(
523 *this, other);
524 }
525
527 EIGEN_DEVICE_FUNC void setIdentity() { m_matrix.setIdentity(); }
528
533 EIGEN_DEVICE_FUNC static const Transform Identity() { return Transform(MatrixType::Identity()); }
534
535 template <typename OtherDerived>
536 EIGEN_DEVICE_FUNC inline Transform& scale(const MatrixBase<OtherDerived>& other);
537
538 template <typename OtherDerived>
539 EIGEN_DEVICE_FUNC inline Transform& prescale(const MatrixBase<OtherDerived>& other);
540
541 EIGEN_DEVICE_FUNC inline Transform& scale(const Scalar& s);
542 EIGEN_DEVICE_FUNC inline Transform& prescale(const Scalar& s);
543
544 template <typename OtherDerived>
545 EIGEN_DEVICE_FUNC inline Transform& translate(const MatrixBase<OtherDerived>& other);
546
547 template <typename OtherDerived>
548 EIGEN_DEVICE_FUNC inline Transform& pretranslate(const MatrixBase<OtherDerived>& other);
549
550 template <typename RotationType>
551 EIGEN_DEVICE_FUNC inline Transform& rotate(const RotationType& rotation);
552
553 template <typename RotationType>
554 EIGEN_DEVICE_FUNC inline Transform& prerotate(const RotationType& rotation);
555
556 EIGEN_DEVICE_FUNC Transform& shear(const Scalar& sx, const Scalar& sy);
557 EIGEN_DEVICE_FUNC Transform& preshear(const Scalar& sx, const Scalar& sy);
558
559 EIGEN_DEVICE_FUNC inline Transform& operator=(const TranslationType& t);
560
561 EIGEN_DEVICE_FUNC inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
562
563 EIGEN_DEVICE_FUNC inline Transform operator*(const TranslationType& t) const;
564
565 EIGEN_DEVICE_FUNC inline Transform& operator=(const UniformScaling<Scalar>& t);
566
567 EIGEN_DEVICE_FUNC inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
568
569 EIGEN_DEVICE_FUNC inline TransformTimeDiagonalReturnType operator*(const UniformScaling<Scalar>& s) const {
571 res.scale(s.factor());
572 return res;
573 }
574
575 EIGEN_DEVICE_FUNC inline Transform& operator*=(const DiagonalMatrix<Scalar, Dim>& s) {
576 linearExt() *= s;
577 return *this;
578 }
579
580 template <typename Derived>
581 EIGEN_DEVICE_FUNC inline Transform& operator=(const RotationBase<Derived, Dim>& r);
582 template <typename Derived>
583 EIGEN_DEVICE_FUNC inline Transform& operator*=(const RotationBase<Derived, Dim>& r) {
584 return rotate(r.toRotationMatrix());
585 }
586 template <typename Derived>
587 EIGEN_DEVICE_FUNC inline Transform operator*(const RotationBase<Derived, Dim>& r) const;
588
589 using RotationReturnType = std::conditional_t<int(Mode) == Isometry, ConstLinearPart, const LinearMatrixType>;
590 EIGEN_DEVICE_FUNC RotationReturnType rotation() const;
591
592 template <typename RotationMatrixType, typename ScalingMatrixType>
593 EIGEN_DEVICE_FUNC void computeRotationScaling(RotationMatrixType* rotation, ScalingMatrixType* scaling) const;
594 template <typename ScalingMatrixType, typename RotationMatrixType>
595 EIGEN_DEVICE_FUNC void computeScalingRotation(ScalingMatrixType* scaling, RotationMatrixType* rotation) const;
596
597 template <typename PositionDerived, typename OrientationType, typename ScaleDerived>
598 EIGEN_DEVICE_FUNC Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived>& position,
599 const OrientationType& orientation,
600 const MatrixBase<ScaleDerived>& scale);
601
602 EIGEN_DEVICE_FUNC inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
603
605 EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return m_matrix.data(); }
607 EIGEN_DEVICE_FUNC constexpr Scalar* data() { return m_matrix.data(); }
608
614 template <typename NewScalarType>
615 EIGEN_DEVICE_FUNC inline
616 typename internal::cast_return_type<Transform, Transform<NewScalarType, Dim, Mode, Options> >::type
617 cast() const {
618 return typename internal::cast_return_type<Transform, Transform<NewScalarType, Dim, Mode, Options> >::type(*this);
619 }
620
622 template <typename OtherScalarType>
623 EIGEN_DEVICE_FUNC inline explicit Transform(const Transform<OtherScalarType, Dim, Mode, Options>& other) {
624 check_template_params();
625 m_matrix = other.matrix().template cast<Scalar>();
626 }
627
632 EIGEN_DEVICE_FUNC bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec =
633 NumTraits<Scalar>::dummy_precision()) const {
634 return m_matrix.isApprox(other.m_matrix, prec);
635 }
636
639 EIGEN_DEVICE_FUNC void makeAffine() { internal::transform_make_affine<int(Mode)>::run(m_matrix); }
640
645 EIGEN_DEVICE_FUNC inline Block<MatrixType, int(Mode) == int(Projective) ? HDim : Dim, Dim> linearExt() {
646 return m_matrix.template block < int(Mode) == int(Projective) ? HDim : Dim, Dim > (0, 0);
647 }
652 EIGEN_DEVICE_FUNC inline const Block<MatrixType, int(Mode) == int(Projective) ? HDim : Dim, Dim> linearExt() const {
653 return m_matrix.template block < int(Mode) == int(Projective) ? HDim : Dim, Dim > (0, 0);
654 }
655
660 EIGEN_DEVICE_FUNC inline Block<MatrixType, int(Mode) == int(Projective) ? HDim : Dim, 1> translationExt() {
661 return m_matrix.template block < int(Mode) == int(Projective) ? HDim : Dim, 1 > (0, Dim);
662 }
667 EIGEN_DEVICE_FUNC inline const Block<MatrixType, int(Mode) == int(Projective) ? HDim : Dim, 1> translationExt()
668 const {
669 return m_matrix.template block < int(Mode) == int(Projective) ? HDim : Dim, 1 > (0, Dim);
670 }
671
672#ifdef EIGEN_TRANSFORM_PLUGIN
673#include EIGEN_TRANSFORM_PLUGIN
674#endif
675
676 protected:
677#ifndef EIGEN_PARSED_BY_DOXYGEN
678 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void check_template_params() {
679 EIGEN_STATIC_ASSERT((Options & (DontAlign | RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
680 }
681#endif
682};
683
685using Isometry2f = Transform<float, 2, Isometry>;
687using Isometry3f = Transform<float, 3, Isometry>;
689using Isometry2d = Transform<double, 2, Isometry>;
691using Isometry3d = Transform<double, 3, Isometry>;
692
694using Affine2f = Transform<float, 2, Affine>;
696using Affine3f = Transform<float, 3, Affine>;
698using Affine2d = Transform<double, 2, Affine>;
700using Affine3d = Transform<double, 3, Affine>;
701
703using AffineCompact2f = Transform<float, 2, AffineCompact>;
705using AffineCompact3f = Transform<float, 3, AffineCompact>;
707using AffineCompact2d = Transform<double, 2, AffineCompact>;
709using AffineCompact3d = Transform<double, 3, AffineCompact>;
710
712using Projective2f = Transform<float, 2, Projective>;
714using Projective3f = Transform<float, 3, Projective>;
716using Projective2d = Transform<double, 2, Projective>;
718using Projective3d = Transform<double, 3, Projective>;
719
720/**************************
721*** Optional QT support ***
722**************************/
723
724#ifdef EIGEN_QT_SUPPORT
725
726#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
731template <typename Scalar, int Dim, int Mode, int Options>
733 check_template_params();
734 *this = other;
735}
736
741template <typename Scalar, int Dim, int Mode, int Options>
743 EIGEN_STATIC_ASSERT(Dim == 2, YOU_MADE_A_PROGRAMMING_MISTAKE)
744 if (EIGEN_CONST_CONDITIONAL(Mode == int(AffineCompact)))
745 m_matrix << other.m11(), other.m21(), other.dx(), other.m12(), other.m22(), other.dy();
746 else
747 m_matrix << other.m11(), other.m21(), other.dx(), other.m12(), other.m22(), other.dy(), 0, 0, 1;
748 return *this;
749}
750
757template <typename Scalar, int Dim, int Mode, int Options>
759 check_template_params();
760 EIGEN_STATIC_ASSERT(Dim == 2, YOU_MADE_A_PROGRAMMING_MISTAKE)
761 return QMatrix(m_matrix.coeff(0, 0), m_matrix.coeff(1, 0), m_matrix.coeff(0, 1), m_matrix.coeff(1, 1),
762 m_matrix.coeff(0, 2), m_matrix.coeff(1, 2));
763}
764#endif
765
770template <typename Scalar, int Dim, int Mode, int Options>
772 check_template_params();
773 *this = other;
774}
775
780template <typename Scalar, int Dim, int Mode, int Options>
782 check_template_params();
783 EIGEN_STATIC_ASSERT(Dim == 2, YOU_MADE_A_PROGRAMMING_MISTAKE)
784 if (EIGEN_CONST_CONDITIONAL(Mode == int(AffineCompact)))
785 m_matrix << other.m11(), other.m21(), other.dx(), other.m12(), other.m22(), other.dy();
786 else
787 m_matrix << other.m11(), other.m21(), other.dx(), other.m12(), other.m22(), other.dy(), other.m13(), other.m23(),
788 other.m33();
789 return *this;
790}
791
796template <typename Scalar, int Dim, int Mode, int Options>
798 EIGEN_STATIC_ASSERT(Dim == 2, YOU_MADE_A_PROGRAMMING_MISTAKE)
799 if (EIGEN_CONST_CONDITIONAL(Mode == int(AffineCompact)))
800 return QTransform(m_matrix.coeff(0, 0), m_matrix.coeff(1, 0), m_matrix.coeff(0, 1), m_matrix.coeff(1, 1),
801 m_matrix.coeff(0, 2), m_matrix.coeff(1, 2));
802 else
803 return QTransform(m_matrix.coeff(0, 0), m_matrix.coeff(1, 0), m_matrix.coeff(2, 0), m_matrix.coeff(0, 1),
804 m_matrix.coeff(1, 1), m_matrix.coeff(2, 1), m_matrix.coeff(0, 2), m_matrix.coeff(1, 2),
805 m_matrix.coeff(2, 2));
806}
807#endif
808
809/*********************
810*** Procedural API ***
811*********************/
812
817template <typename Scalar, int Dim, int Mode, int Options>
818template <typename OtherDerived>
819EIGEN_DEVICE_FUNC Transform<Scalar, Dim, Mode, Options>& Transform<Scalar, Dim, Mode, Options>::scale(
820 const MatrixBase<OtherDerived>& other) {
821 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived, int(Dim))
822 EIGEN_STATIC_ASSERT(Mode != int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
823 linearExt() = linearExt() * other.asDiagonal();
824 return *this;
825}
826
831template <typename Scalar, int Dim, int Mode, int Options>
832EIGEN_DEVICE_FUNC inline Transform<Scalar, Dim, Mode, Options>& Transform<Scalar, Dim, Mode, Options>::scale(
833 const Scalar& s) {
834 EIGEN_STATIC_ASSERT(Mode != int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
835 linearExt() *= s;
836 return *this;
837}
838
843template <typename Scalar, int Dim, int Mode, int Options>
844template <typename OtherDerived>
845EIGEN_DEVICE_FUNC Transform<Scalar, Dim, Mode, Options>& Transform<Scalar, Dim, Mode, Options>::prescale(
846 const MatrixBase<OtherDerived>& other) {
847 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived, int(Dim))
848 EIGEN_STATIC_ASSERT(Mode != int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
849 affine() = other.asDiagonal() * affine();
850 return *this;
851}
852
857template <typename Scalar, int Dim, int Mode, int Options>
858EIGEN_DEVICE_FUNC inline Transform<Scalar, Dim, Mode, Options>& Transform<Scalar, Dim, Mode, Options>::prescale(
859 const Scalar& s) {
860 EIGEN_STATIC_ASSERT(Mode != int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
861 m_matrix.template topRows<Dim>() *= s;
862 return *this;
863}
864
869template <typename Scalar, int Dim, int Mode, int Options>
870template <typename OtherDerived>
871EIGEN_DEVICE_FUNC Transform<Scalar, Dim, Mode, Options>& Transform<Scalar, Dim, Mode, Options>::translate(
872 const MatrixBase<OtherDerived>& other) {
873 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived, int(Dim))
874 translationExt() +=
875 linearExt() *
876 internal::transform_convert_arg<Scalar, OtherDerived, Scalar, typename OtherDerived::Scalar,
877 internal::fast_mult_op<Scalar, typename OtherDerived::Scalar>>::run(other);
878 return *this;
879}
880
885template <typename Scalar, int Dim, int Mode, int Options>
886template <typename OtherDerived>
887EIGEN_DEVICE_FUNC Transform<Scalar, Dim, Mode, Options>& Transform<Scalar, Dim, Mode, Options>::pretranslate(
888 const MatrixBase<OtherDerived>& other) {
889 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived, int(Dim))
890 if (EIGEN_CONST_CONDITIONAL(int(Mode) == int(Projective)))
891 affine() +=
892 internal::transform_convert_arg<Scalar, OtherDerived, typename OtherDerived::Scalar, Scalar,
893 internal::fast_mult_op<typename OtherDerived::Scalar, Scalar>>::run(other) *
894 m_matrix.row(Dim);
895 else
896 translation() +=
897 internal::transform_convert_arg<Scalar, OtherDerived, Scalar, typename OtherDerived::Scalar,
898 internal::scalar_sum_op<Scalar, typename OtherDerived::Scalar>>::run(other);
899 return *this;
900}
901
902namespace internal {
903
904template <typename TransformType, typename RotationType, typename Enable = void>
905struct transform_rotate_impl {
906 EIGEN_DEVICE_FUNC static inline void run(TransformType& t, const RotationType& rotation) {
907 t.linearExt() *= internal::toRotationMatrix<typename TransformType::Scalar, TransformType::Dim>(rotation);
908 }
909};
910
911template <typename TransformType, typename Derived>
912struct transform_rotate_impl<TransformType, Derived,
913 std::enable_if_t<std::is_base_of<MatrixBase<Derived>, Derived>::value>> {
914 EIGEN_DEVICE_FUNC static inline void run(TransformType& t, const Derived& rotation) {
915 using Scalar = typename TransformType::Scalar;
916 t.linearExt() *= internal::transform_convert_arg<
917 Scalar, Derived, Scalar, typename Derived::Scalar,
918 internal::fast_mult_op<Scalar, typename Derived::Scalar>>::run(rotation);
919 }
920};
921
922template <typename TransformType, typename Derived>
923struct transform_rotate_impl<
924 TransformType, Derived,
925 std::enable_if_t<std::is_base_of<RotationBase<Derived, TransformType::Dim>, Derived>::value>> {
926 EIGEN_DEVICE_FUNC static inline void run(TransformType& t, const Derived& rotation) {
927 t.rotate(rotation.toRotationMatrix());
928 }
929};
930
931template <typename TransformType, typename OtherScalar>
932struct transform_rotate_impl<TransformType, OtherScalar, std::enable_if_t<std::is_scalar<OtherScalar>::value>> {
933 EIGEN_DEVICE_FUNC static inline void run(TransformType& t, const OtherScalar& rotation) {
934 EIGEN_STATIC_ASSERT(TransformType::Dim == 2, YOU_MADE_A_PROGRAMMING_MISTAKE)
935 t.rotate(Rotation2D<OtherScalar>(rotation).toRotationMatrix());
936 }
937};
938
939template <typename TransformType, typename RotationType, typename Enable = void>
940struct transform_prerotate_impl {
941 EIGEN_DEVICE_FUNC static inline void run(TransformType& t, const RotationType& rotation) {
942 t.matrix().template block<TransformType::Dim, TransformType::HDim>(0, 0) =
943 internal::toRotationMatrix<typename TransformType::Scalar, TransformType::Dim>(rotation) *
944 t.matrix().template block<TransformType::Dim, TransformType::HDim>(0, 0);
945 }
946};
947
948template <typename TransformType, typename Derived>
949struct transform_prerotate_impl<TransformType, Derived,
950 std::enable_if_t<std::is_base_of<MatrixBase<Derived>, Derived>::value>> {
951 EIGEN_DEVICE_FUNC static inline void run(TransformType& t, const Derived& rotation) {
952 using Scalar = typename TransformType::Scalar;
953 t.matrix().template block<TransformType::Dim, TransformType::HDim>(0, 0) =
954 internal::transform_convert_arg<
955 Scalar, Derived, typename Derived::Scalar, Scalar,
956 internal::fast_mult_op<typename Derived::Scalar, Scalar>>::run(rotation) *
957 t.matrix().template block<TransformType::Dim, TransformType::HDim>(0, 0);
958 }
959};
960
961template <typename TransformType, typename Derived>
962struct transform_prerotate_impl<
963 TransformType, Derived,
964 std::enable_if_t<std::is_base_of<RotationBase<Derived, TransformType::Dim>, Derived>::value>> {
965 EIGEN_DEVICE_FUNC static inline void run(TransformType& t, const Derived& rotation) {
966 t.prerotate(rotation.toRotationMatrix());
967 }
968};
969
970template <typename TransformType, typename OtherScalar>
971struct transform_prerotate_impl<TransformType, OtherScalar, std::enable_if_t<std::is_scalar<OtherScalar>::value>> {
972 EIGEN_DEVICE_FUNC static inline void run(TransformType& t, const OtherScalar& rotation) {
973 EIGEN_STATIC_ASSERT(TransformType::Dim == 2, YOU_MADE_A_PROGRAMMING_MISTAKE)
974 t.prerotate(Rotation2D<OtherScalar>(rotation).toRotationMatrix());
975 }
976};
977
978} // end namespace internal
979
997template <typename Scalar, int Dim, int Mode, int Options>
998template <typename RotationType>
999EIGEN_DEVICE_FUNC Transform<Scalar, Dim, Mode, Options>& Transform<Scalar, Dim, Mode, Options>::rotate(
1000 const RotationType& rotation) {
1001 internal::transform_rotate_impl<Transform, RotationType>::run(*this, rotation);
1002 return *this;
1003}
1004
1012template <typename Scalar, int Dim, int Mode, int Options>
1013template <typename RotationType>
1014EIGEN_DEVICE_FUNC Transform<Scalar, Dim, Mode, Options>& Transform<Scalar, Dim, Mode, Options>::prerotate(
1015 const RotationType& rotation) {
1016 internal::transform_prerotate_impl<Transform, RotationType>::run(*this, rotation);
1017 return *this;
1018}
1019
1025template <typename Scalar, int Dim, int Mode, int Options>
1027 const Scalar& sx, const Scalar& sy) {
1028 EIGEN_STATIC_ASSERT(int(Dim) == 2, YOU_MADE_A_PROGRAMMING_MISTAKE)
1029 EIGEN_STATIC_ASSERT(Mode != int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
1030 VectorType tmp = linear().col(0) * sy + linear().col(1);
1031 linear() << linear().col(0) + linear().col(1) * sx, tmp;
1032 return *this;
1033}
1034
1040template <typename Scalar, int Dim, int Mode, int Options>
1042 const Scalar& sx, const Scalar& sy) {
1043 EIGEN_STATIC_ASSERT(int(Dim) == 2, YOU_MADE_A_PROGRAMMING_MISTAKE)
1044 EIGEN_STATIC_ASSERT(Mode != int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
1045 m_matrix.template block<Dim, HDim>(0, 0) =
1046 LinearMatrixType({{1, sy}, {sx, 1}}) * m_matrix.template block<Dim, HDim>(0, 0);
1047 return *this;
1048}
1049
1050/******************************************************
1051*** Scaling, Translation and Rotation compatibility ***
1052******************************************************/
1053
1054template <typename Scalar, int Dim, int Mode, int Options>
1056 const TranslationType& t) {
1057 linear().setIdentity();
1058 translation() = t.vector();
1059 makeAffine();
1060 return *this;
1061}
1062
1063template <typename Scalar, int Dim, int Mode, int Options>
1064EIGEN_DEVICE_FUNC inline Transform<Scalar, Dim, Mode, Options> Transform<Scalar, Dim, Mode, Options>::operator*(
1065 const TranslationType& t) const {
1066 Transform res = *this;
1067 res.translate(t.vector());
1068 return res;
1069}
1070
1071template <typename Scalar, int Dim, int Mode, int Options>
1073 const UniformScaling<Scalar>& s) {
1074 m_matrix.setZero();
1075 linear().diagonal().fill(s.factor());
1076 makeAffine();
1077 return *this;
1078}
1079
1080template <typename Scalar, int Dim, int Mode, int Options>
1081template <typename Derived>
1083 const RotationBase<Derived, Dim>& r) {
1084 linear() = internal::toRotationMatrix<Scalar, Dim>(r);
1085 translation().setZero();
1086 makeAffine();
1087 return *this;
1088}
1089
1090template <typename Scalar, int Dim, int Mode, int Options>
1091template <typename Derived>
1093 const RotationBase<Derived, Dim>& r) const {
1094 Transform res = *this;
1095 res.rotate(r.derived());
1096 return res;
1097}
1098
1099/************************
1100*** Special functions ***
1101************************/
1102
1103namespace internal {
1104template <int Mode>
1105struct transform_rotation_impl {
1106 template <typename TransformType>
1107 EIGEN_DEVICE_FUNC static inline const typename TransformType::LinearMatrixType run(const TransformType& t) {
1108 using LinearMatrixType = typename TransformType::LinearMatrixType;
1109 LinearMatrixType result;
1110 t.computeRotationScaling(&result, (LinearMatrixType*)0);
1111 return result;
1112 }
1113};
1114template <>
1115struct transform_rotation_impl<Isometry> {
1116 template <typename TransformType>
1117 EIGEN_DEVICE_FUNC static inline typename TransformType::ConstLinearPart run(const TransformType& t) {
1118 return t.linear();
1119 }
1120};
1121} // namespace internal
1132template <typename Scalar, int Dim, int Mode, int Options>
1133EIGEN_DEVICE_FUNC typename Transform<Scalar, Dim, Mode, Options>::RotationReturnType
1135 return internal::transform_rotation_impl<Mode>::run(*this);
1136}
1137
1149template <typename Scalar, int Dim, int Mode, int Options>
1150template <typename RotationMatrixType, typename ScalingMatrixType>
1152 ScalingMatrixType* scaling) const {
1153 // Note that JacobiSVD is faster than BDCSVD for small matrices.
1155
1156 Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant() < Scalar(0)
1157 ? Scalar(-1)
1158 : Scalar(1); // so x has absolute value 1
1159 VectorType sv(svd.singularValues());
1160 sv.coeffRef(Dim - 1) *= x;
1161 if (scaling) (*scaling).noalias() = svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint();
1162 if (rotation) {
1163 LinearMatrixType m(svd.matrixU());
1164 m.col(Dim - 1) *= x;
1165 (*rotation).noalias() = m * svd.matrixV().adjoint();
1166 }
1167}
1168
1180template <typename Scalar, int Dim, int Mode, int Options>
1181template <typename ScalingMatrixType, typename RotationMatrixType>
1183 ScalingMatrixType* scaling, RotationMatrixType* rotation) const {
1184 // Note that JacobiSVD is faster than BDCSVD for small matrices.
1186
1187 Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant() < Scalar(0)
1188 ? Scalar(-1)
1189 : Scalar(1); // so x has absolute value 1
1190 VectorType sv(svd.singularValues());
1191 sv.coeffRef(Dim - 1) *= x;
1192 if (scaling) *scaling = svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint();
1193 if (rotation) {
1194 LinearMatrixType m(svd.matrixU());
1195 m.col(Dim - 1) *= x;
1196 *rotation = m * svd.matrixV().adjoint();
1197 }
1198}
1199
1203template <typename Scalar, int Dim, int Mode, int Options>
1204template <typename PositionDerived, typename OrientationType, typename ScaleDerived>
1206Transform<Scalar, Dim, Mode, Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived>& position,
1207 const OrientationType& orientation,
1208 const MatrixBase<ScaleDerived>& scale) {
1209 linear() = internal::toRotationMatrix<Scalar, Dim>(orientation);
1210 linear() *= scale.asDiagonal();
1211 translation() = position;
1212 makeAffine();
1213 return *this;
1214}
1215
1216namespace internal {
1217
1218template <int Mode>
1219struct transform_make_affine {
1220 template <typename MatrixType>
1221 EIGEN_DEVICE_FUNC static void run(MatrixType& mat) {
1222 static const int Dim = MatrixType::ColsAtCompileTime - 1;
1223 mat.template block<1, Dim>(Dim, 0).setZero();
1224 mat.coeffRef(Dim, Dim) = typename MatrixType::Scalar(1);
1225 }
1226};
1227
1228template <>
1229struct transform_make_affine<AffineCompact> {
1230 template <typename MatrixType>
1231 EIGEN_DEVICE_FUNC static void run(MatrixType&) {}
1232};
1233
1234// Selector needed to avoid taking the inverse of a 3x4 matrix. Only a Projective transform can store a general
1235// inverse; for every other mode the type itself guarantees the transform is affine, so a Projective hint - which only
1236// asks that no extra structure be assumed - is honoured by the general affine inverse.
1237template <typename TransformType, int Mode = TransformType::Mode>
1238struct projective_transform_inverse {
1239 EIGEN_DEVICE_FUNC static inline void run(const TransformType& m, TransformType& res) { res = m.inverse(Affine); }
1240};
1241
1242template <typename TransformType>
1243struct projective_transform_inverse<TransformType, Projective> {
1244 EIGEN_DEVICE_FUNC static inline void run(const TransformType& m, TransformType& res) {
1245 res.matrix() = m.matrix().inverse();
1246 }
1247};
1248
1249} // end namespace internal
1250
1271template <typename Scalar, int Dim, int Mode, int Options>
1273 TransformTraits hint) const {
1274 Transform res;
1275 if (hint == Projective) {
1276 internal::projective_transform_inverse<Transform>::run(*this, res);
1277 } else {
1278 if (hint == Isometry) {
1279 res.matrix().template topLeftCorner<Dim, Dim>() = linear().transpose();
1280 } else if (hint & Affine) {
1281 res.matrix().template topLeftCorner<Dim, Dim>() = linear().inverse();
1282 } else {
1283 eigen_assert(false && "Invalid transform traits in Transform::Inverse");
1284 }
1285 // translation and remaining parts
1286 res.matrix().template topRightCorner<Dim, 1>().noalias() =
1287 -res.matrix().template topLeftCorner<Dim, Dim>() * translation();
1288 res.makeAffine(); // we do need this, because in the beginning res is uninitialized
1289 }
1290 return res;
1291}
1292
1293namespace internal {
1294
1295/*****************************************************
1296*** Specializations of take affine part ***
1297*****************************************************/
1298
1299template <typename TransformType>
1300struct transform_take_affine_part {
1301 using MatrixType = typename TransformType::MatrixType;
1302 using AffinePart = typename TransformType::AffinePart;
1303 using ConstAffinePart = typename TransformType::ConstAffinePart;
1304 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AffinePart run(MatrixType& m) {
1305 return m.template block<TransformType::Dim, TransformType::HDim>(0, 0);
1306 }
1307 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ConstAffinePart run(const MatrixType& m) {
1308 return m.template block<TransformType::Dim, TransformType::HDim>(0, 0);
1309 }
1310};
1311
1312template <typename Scalar, int Dim, int Options>
1313struct transform_take_affine_part<Transform<Scalar, Dim, AffineCompact, Options> > {
1315 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE MatrixType& run(MatrixType& m) { return m; }
1316 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const MatrixType& run(const MatrixType& m) { return m; }
1317};
1318
1319/*****************************************************
1320*** Specializations of construct from matrix ***
1321*****************************************************/
1322
1323template <typename Other, int Mode, int Options, int Dim, int HDim>
1324struct transform_construct_from_matrix<Other, Mode, Options, Dim, HDim, Dim, Dim> {
1325 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(
1326 Transform<typename Other::Scalar, Dim, Mode, Options>* transform, const Other& other) {
1327 transform->linear() = other;
1328 transform->translation().setZero();
1329 transform->makeAffine();
1330 }
1331};
1332
1333template <typename Other, int Mode, int Options, int Dim, int HDim>
1334struct transform_construct_from_matrix<Other, Mode, Options, Dim, HDim, Dim, HDim> {
1335 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(
1336 Transform<typename Other::Scalar, Dim, Mode, Options>* transform, const Other& other) {
1337 transform->affine() = other;
1338 transform->makeAffine();
1339 }
1340};
1341
1342template <typename Other, int Mode, int Options, int Dim, int HDim>
1343struct transform_construct_from_matrix<Other, Mode, Options, Dim, HDim, HDim, HDim> {
1344 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(
1345 Transform<typename Other::Scalar, Dim, Mode, Options>* transform, const Other& other) {
1346 transform->matrix() = other;
1347 }
1348};
1349
1350template <typename Other, int Options, int Dim, int HDim>
1351struct transform_construct_from_matrix<Other, AffineCompact, Options, Dim, HDim, HDim, HDim> {
1352 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(
1353 Transform<typename Other::Scalar, Dim, AffineCompact, Options>* transform, const Other& other) {
1354 transform->matrix() = other.template block<Dim, HDim>(0, 0);
1355 }
1356};
1357
1358/**********************************************************
1359*** Specializations of operator* with rhs MatrixBase ***
1360**********************************************************/
1361
1362template <int LhsMode, int RhsMode>
1363struct transform_product_result {
1364 enum {
1365 Mode = (LhsMode == (int)Projective || RhsMode == (int)Projective) ? Projective
1366 : (LhsMode == (int)Affine || RhsMode == (int)Affine) ? Affine
1367 : (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact) ? AffineCompact
1368 : (LhsMode == (int)Isometry || RhsMode == (int)Isometry) ? Isometry
1369 : Projective
1370 };
1371};
1372
1373template <typename TransformType, typename MatrixType, int RhsCols>
1374struct transform_right_product_impl<TransformType, MatrixType, 0, RhsCols> {
1375 using ResultType = typename MatrixType::PlainObject;
1376
1377 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) {
1378 return T.matrix() * other;
1379 }
1380};
1381
1382template <typename TransformType, typename MatrixType, int RhsCols>
1383struct transform_right_product_impl<TransformType, MatrixType, 1, RhsCols> {
1384 enum {
1385 Dim = TransformType::Dim,
1386 HDim = TransformType::HDim,
1387 OtherRows = MatrixType::RowsAtCompileTime,
1388 OtherCols = MatrixType::ColsAtCompileTime
1389 };
1390
1391 using ResultType = typename MatrixType::PlainObject;
1392
1393 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) {
1394 EIGEN_STATIC_ASSERT(OtherRows == HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
1395
1396 using TopLeftLhs = Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime) == Dim>;
1397
1398 ResultType res(other.rows(), other.cols());
1399 TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
1400 res.row(OtherRows - 1) = other.row(OtherRows - 1);
1401
1402 return res;
1403 }
1404};
1405
1406template <typename TransformType, typename MatrixType, int RhsCols>
1407struct transform_right_product_impl<TransformType, MatrixType, 2, RhsCols> {
1408 enum {
1409 Dim = TransformType::Dim,
1410 HDim = TransformType::HDim,
1411 OtherRows = MatrixType::RowsAtCompileTime,
1412 OtherCols = MatrixType::ColsAtCompileTime
1413 };
1414
1415 using ResultType = typename MatrixType::PlainObject;
1416
1417 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) {
1418 EIGEN_STATIC_ASSERT(OtherRows == Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
1419
1420 using TopLeftLhs = Block<ResultType, Dim, OtherCols, true>;
1421 ResultType res(
1422 Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(), 1, other.cols()));
1423 TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other;
1424
1425 return res;
1426 }
1427};
1428
1429template <typename TransformType, typename MatrixType>
1430struct transform_right_product_impl<TransformType, MatrixType, 2, 1> // rhs is a vector of size Dim
1431{
1432 using TransformMatrix = typename TransformType::MatrixType;
1433 enum {
1434 Dim = TransformType::Dim,
1435 HDim = TransformType::HDim,
1436 OtherRows = MatrixType::RowsAtCompileTime,
1437 WorkingRows = plain_enum_min(TransformMatrix::RowsAtCompileTime, HDim)
1438 };
1439
1440 using ResultType = typename MatrixType::PlainObject;
1441
1442 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) {
1443 EIGEN_STATIC_ASSERT(OtherRows == Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
1444
1445 Matrix<typename ResultType::Scalar, Dim + 1, 1> rhs;
1446 rhs.template head<Dim>() = other;
1447 rhs[Dim] = typename ResultType::Scalar(1);
1448 Matrix<typename ResultType::Scalar, WorkingRows, 1> res(T.matrix() * rhs);
1449 return res.template head<Dim>();
1450 }
1451};
1452
1453/**********************************************************
1454*** Specializations of operator* with lhs EigenBase ***
1455**********************************************************/
1456
1457// generic HDim x HDim matrix * T => Projective
1458template <typename Other, int Mode, int Options, int Dim, int HDim>
1459struct transform_left_product_impl<Other, Mode, Options, Dim, HDim, HDim, HDim> {
1460 using TransformType = Transform<typename Other::Scalar, Dim, Mode, Options>;
1461 using MatrixType = typename TransformType::MatrixType;
1462 using ResultType = Transform<typename Other::Scalar, Dim, Projective, Options>;
1463 static EIGEN_DEVICE_FUNC ResultType run(const Other& other, const TransformType& tr) {
1464 return ResultType(other * tr.matrix());
1465 }
1466};
1467
1468// generic HDim x HDim matrix * AffineCompact => Projective
1469template <typename Other, int Options, int Dim, int HDim>
1470struct transform_left_product_impl<Other, AffineCompact, Options, Dim, HDim, HDim, HDim> {
1471 using TransformType = Transform<typename Other::Scalar, Dim, AffineCompact, Options>;
1472 using MatrixType = typename TransformType::MatrixType;
1473 using ResultType = Transform<typename Other::Scalar, Dim, Projective, Options>;
1474 static EIGEN_DEVICE_FUNC ResultType run(const Other& other, const TransformType& tr) {
1475 ResultType res;
1476 res.matrix().noalias() = other.template block<HDim, Dim>(0, 0) * tr.matrix();
1477 res.matrix().col(Dim) += other.col(Dim);
1478 return res;
1479 }
1480};
1481
1482// affine matrix * T
1483template <typename Other, int Mode, int Options, int Dim, int HDim>
1484struct transform_left_product_impl<Other, Mode, Options, Dim, HDim, Dim, HDim> {
1485 using TransformType = Transform<typename Other::Scalar, Dim, Mode, Options>;
1486 using MatrixType = typename TransformType::MatrixType;
1487 using ResultType = TransformType;
1488 static EIGEN_DEVICE_FUNC ResultType run(const Other& other, const TransformType& tr) {
1489 ResultType res;
1490 res.affine().noalias() = other * tr.matrix();
1491 res.matrix().row(Dim) = tr.matrix().row(Dim);
1492 return res;
1493 }
1494};
1495
1496// affine matrix * AffineCompact
1497template <typename Other, int Options, int Dim, int HDim>
1498struct transform_left_product_impl<Other, AffineCompact, Options, Dim, HDim, Dim, HDim> {
1499 using TransformType = Transform<typename Other::Scalar, Dim, AffineCompact, Options>;
1500 using MatrixType = typename TransformType::MatrixType;
1501 using ResultType = TransformType;
1502 static EIGEN_DEVICE_FUNC ResultType run(const Other& other, const TransformType& tr) {
1503 ResultType res;
1504 res.matrix().noalias() = other.template block<Dim, Dim>(0, 0) * tr.matrix();
1505 res.translation() += other.col(Dim);
1506 return res;
1507 }
1508};
1509
1510// linear matrix * T
1511template <typename Other, int Mode, int Options, int Dim, int HDim>
1512struct transform_left_product_impl<Other, Mode, Options, Dim, HDim, Dim, Dim> {
1513 using TransformType = Transform<typename Other::Scalar, Dim, Mode, Options>;
1514 using MatrixType = typename TransformType::MatrixType;
1515 using ResultType = TransformType;
1516 static EIGEN_DEVICE_FUNC ResultType run(const Other& other, const TransformType& tr) {
1517 TransformType res;
1518 EIGEN_IF_CONSTEXPR (Mode != int(AffineCompact)) res.matrix().row(Dim) = tr.matrix().row(Dim);
1519 res.matrix().template topRows<Dim>().noalias() = other * tr.matrix().template topRows<Dim>();
1520 return res;
1521 }
1522};
1523
1524/**********************************************************
1525*** Specializations of operator* with another Transform ***
1526**********************************************************/
1527
1528template <typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
1529struct transform_transform_product_impl<Transform<Scalar, Dim, LhsMode, LhsOptions>,
1530 Transform<Scalar, Dim, RhsMode, RhsOptions>, false> {
1531 enum { ResultMode = transform_product_result<LhsMode, RhsMode>::Mode };
1532 using Lhs = Transform<Scalar, Dim, LhsMode, LhsOptions>;
1533 using Rhs = Transform<Scalar, Dim, RhsMode, RhsOptions>;
1534 using ResultType = Transform<Scalar, Dim, ResultMode, LhsOptions>;
1535 static EIGEN_DEVICE_FUNC ResultType run(const Lhs& lhs, const Rhs& rhs) {
1536 ResultType res;
1537 res.linear().noalias() = lhs.linear() * rhs.linear();
1538 res.translation().noalias() = lhs.linear() * rhs.translation() + lhs.translation();
1539 res.makeAffine();
1540 return res;
1541 }
1542};
1543
1544template <typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
1545struct transform_transform_product_impl<Transform<Scalar, Dim, LhsMode, LhsOptions>,
1546 Transform<Scalar, Dim, RhsMode, RhsOptions>, true> {
1547 using Lhs = Transform<Scalar, Dim, LhsMode, LhsOptions>;
1548 using Rhs = Transform<Scalar, Dim, RhsMode, RhsOptions>;
1549 using ResultType = Transform<Scalar, Dim, Projective>;
1550 static EIGEN_DEVICE_FUNC ResultType run(const Lhs& lhs, const Rhs& rhs) {
1551 return ResultType(lhs.matrix() * rhs.matrix());
1552 }
1553};
1554
1555template <typename Scalar, int Dim, int LhsOptions, int RhsOptions>
1556struct transform_transform_product_impl<Transform<Scalar, Dim, AffineCompact, LhsOptions>,
1557 Transform<Scalar, Dim, Projective, RhsOptions>, true> {
1558 using Lhs = Transform<Scalar, Dim, AffineCompact, LhsOptions>;
1559 using Rhs = Transform<Scalar, Dim, Projective, RhsOptions>;
1560 using ResultType = Transform<Scalar, Dim, Projective>;
1561 static EIGEN_DEVICE_FUNC ResultType run(const Lhs& lhs, const Rhs& rhs) {
1562 ResultType res;
1563 res.matrix().template topRows<Dim>().noalias() = lhs.matrix() * rhs.matrix();
1564 res.matrix().row(Dim) = rhs.matrix().row(Dim);
1565 return res;
1566 }
1567};
1568
1569template <typename Scalar, int Dim, int LhsOptions, int RhsOptions>
1570struct transform_transform_product_impl<Transform<Scalar, Dim, Projective, LhsOptions>,
1571 Transform<Scalar, Dim, AffineCompact, RhsOptions>, true> {
1572 using Lhs = Transform<Scalar, Dim, Projective, LhsOptions>;
1573 using Rhs = Transform<Scalar, Dim, AffineCompact, RhsOptions>;
1574 using ResultType = Transform<Scalar, Dim, Projective>;
1575 static EIGEN_DEVICE_FUNC ResultType run(const Lhs& lhs, const Rhs& rhs) {
1576 ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix());
1577 res.matrix().col(Dim) += lhs.matrix().col(Dim);
1578 return res;
1579 }
1580};
1581
1582} // end namespace internal
1583
1584} // end namespace Eigen
1585
1586#endif // EIGEN_TRANSFORM_H
Expression of a fixed-size or dynamic-size block.
Definition Block.h:111
Base class for diagonal matrices and expressions.
Definition DiagonalMatrix.h:34
Two-sided Jacobi SVD decomposition of a rectangular matrix.
Definition JacobiSVD.h:613
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
constexpr const DiagonalWrapper< const Derived > asDiagonal() const
Definition DiagonalMatrix.h:428
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
constexpr Scalar & coeffRef(Index rowId, Index colId)
Definition PlainObjectBase.h:205
Common base class for compact rotation representations.
Definition RotationBase.h:33
const SingularValuesType & singularValues() const
Definition SVDBase.h:203
const MatrixUType & matrixU() const
Definition SVDBase.h:176
const MatrixVType & matrixV() const
Definition SVDBase.h:192
Represents an homogeneous transformation in a N dimensional space.
Definition Transform.h:222
const internal::transform_right_product_impl< Transform, OtherDerived >::ResultType operator*(const MatrixBase< OtherDerived > &other) const
Definition Transform.h:458
ConstAffinePart affine() const
Definition Transform.h:420
ConstLinearPart linear() const
Definition Transform.h:415
static const Transform Identity()
Returns an identity transformation.
Definition Transform.h:533
Transform & preshear(const Scalar &sx, const Scalar &sy)
Definition Transform.h:1041
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
Definition Transform.h:1182
Transform< Scalar, Dim,(Mode==int(Isometry)) ? int(Affine) :int(Mode)> TransformTimeDiagonalReturnType
Definition Transform.h:264
Translation< Scalar, Dim > TranslationType
Definition Transform.h:261
Scalar operator()(Index row, Index col) const
Definition Transform.h:395
Block< MatrixType, Dim, 1, !(internal::traits< MatrixType >::Flags &RowMajorBit)> TranslationPart
Definition Transform.h:256
Scalar & operator()(Index row, Index col)
Definition Transform.h:398
Matrix< Scalar, Dim, 1 > VectorType
Definition Transform.h:254
ConstTranslationPart translation() const
Definition Transform.h:425
Transform & operator=(const QTransform &other)
Definition Transform.h:781
std::conditional_t< int(Mode)==int(AffineCompact), const MatrixType &, const Block< const MatrixType, Dim, HDim > > ConstAffinePart
Definition Transform.h:251
bool isApprox(const Transform &other, const typename NumTraits< Scalar >::Real &prec=NumTraits< Scalar >::dummy_precision()) const
Definition Transform.h:632
Eigen::Index Index
Definition Transform.h:236
AffinePart affine()
Definition Transform.h:422
Transform(const QTransform &other)
Definition Transform.h:771
const Block< ConstMatrixType, Dim, 1, !(internal::traits< MatrixType >::Flags &RowMajorBit)> ConstTranslationPart
Definition Transform.h:258
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
Definition Transform.h:1151
Transform & scale(const Scalar &s)
Definition Transform.h:832
void setIdentity()
Definition Transform.h:527
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar_, Dim_==Dynamic ? Dynamic :(Dim_+1) *(Dim_+1)) enum
Definition Transform.h:224
constexpr Scalar * data()
Definition Transform.h:607
const Transform operator*(const Transform &other) const
Definition Transform.h:512
friend TransformTimeDiagonalReturnType operator*(const DiagonalBase< DiagonalDerived > &a, const Transform &b)
Definition Transform.h:497
Matrix< Scalar, Dim, Dim, Options > LinearMatrixType
Definition Transform.h:242
LinearPart linear()
Definition Transform.h:417
Block< MatrixType, Dim, Dim, int(Mode)==(AffineCompact) &&(int(Options) &RowMajor)==0 > LinearPart
Definition Transform.h:244
const MatrixType & matrix() const
Definition Transform.h:410
friend const internal::transform_left_product_impl< OtherDerived, Mode, Options, Dim_, Dim_+1 >::ResultType operator*(const MatrixBase< OtherDerived > &a, const Transform &b)
Definition Transform.h:472
const TransformTimeDiagonalReturnType operator*(const DiagonalBase< DiagonalDerived > &b) const
Definition Transform.h:483
Transform & prescale(const Scalar &s)
Definition Transform.h:858
Scalar Scalar
Definition Transform.h:234
Transform & operator=(const EigenBase< OtherDerived > &other)
Definition Transform.h:312
Transform(const Transform< OtherScalarType, Dim, Mode, Options > &other)
Definition Transform.h:623
Transform(const EigenBase< OtherDerived > &other)
Definition Transform.h:301
const Block< ConstMatrixType, Dim, Dim, int(Mode)==(AffineCompact) &&(int(Options) &RowMajor)==0 > ConstLinearPart
Definition Transform.h:246
internal::cast_return_type< Transform, Transform< NewScalarType, Dim, Mode, Options > >::type cast() const
Definition Transform.h:617
Transform inverse(TransformTraits traits=(TransformTraits) Mode) const
Definition Transform.h:1272
typename internal::make_proper_matrix_type< Scalar, Rows, HDim, Options >::type MatrixType
Definition Transform.h:238
std::conditional_t< int(Mode)==int(AffineCompact), MatrixType &, Block< MatrixType, Dim, HDim > > AffinePart
Definition Transform.h:249
const MatrixType ConstMatrixType
Definition Transform.h:240
void makeAffine()
Definition Transform.h:639
MatrixType & matrix()
Definition Transform.h:412
internal::transform_transform_product_impl< Transform, Transform< Scalar, Dim, OtherMode, OtherOptions > >::ResultType operator*(const Transform< Scalar, Dim, OtherMode, OtherOptions > &other) const
Definition Transform.h:521
Transform()
Definition Transform.h:272
constexpr const Scalar * data() const
Definition Transform.h:605
Transform & shear(const Scalar &sx, const Scalar &sy)
Definition Transform.h:1026
QTransform toQTransform(void) const
Definition Transform.h:797
TranslationPart translation()
Definition Transform.h:427
Represents a translation transformation.
Definition Translation.h:34
Represents a generic uniform scaling transformation.
Definition Scaling.h:48
TransformTraits
Definition Constants.h:470
@ DontAlign
Definition Constants.h:325
@ RowMajor
Definition Constants.h:321
@ Affine
Definition Constants.h:475
@ Projective
Definition Constants.h:479
@ AffineCompact
Definition Constants.h:477
@ Isometry
Definition Constants.h:472
constexpr unsigned int RowMajorBit
Definition Constants.h:71
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50