diff --git a/src/Math/DualComplex.h b/src/Math/DualComplex.h index d4484727a..acb3154a0 100644 --- a/src/Math/DualComplex.h +++ b/src/Math/DualComplex.h @@ -249,6 +249,20 @@ template class DualComplex: public Dual> { return DualComplex(this->real().invertedNormalized(), {{}, {}})*DualComplex({}, -this->dual()); } + /** + * @brief Rotate and translate point with dual complex number + * + * See transformPointNormalized(), which is faster for normalized dual + * complex number. @f[ + * v' = \hat c v = \hat c ((0 + i) + \epsilon(v_x + iv_y)) + * @f] + * @see DualComplex(const Vector2&), dual(), Matrix3::transformPoint(), + * Complex::transformVector(), DualQuaternion::transformPoint() + */ + inline Vector2 transformPoint(const Vector2& vector) const { + return Vector2(((*this)*DualComplex(vector)).dual()); + } + /* Verbatim copy of DUAL_SUBCLASS_IMPLEMENTATION(), as we need to hide Dual's operator*() and operator/() */ #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Math/DualQuaternion.h b/src/Math/DualQuaternion.h index b9a9f67ad..9e10be0aa 100644 --- a/src/Math/DualQuaternion.h +++ b/src/Math/DualQuaternion.h @@ -253,7 +253,7 @@ template class DualQuaternion: public Dual> { * v' = \hat q v \overline{\hat q^{-1}} = \hat q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^{-1}} * @f] * @see DualQuaternion(const Vector3&), dual(), Matrix4::transformPoint(), - * Quaternion::transformVector() + * Quaternion::transformVector(), DualComplex::transformPoint() */ inline Vector3 transformPoint(const Vector3& vector) const { return ((*this)*DualQuaternion(vector)*inverted().dualConjugated()).dual().vector(); @@ -267,7 +267,7 @@ template class DualQuaternion: public Dual> { * v' = \hat q v \overline{\hat q^{-1}} = \hat q v \overline{\hat q^*} = \hat q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^*} * @f] * @see DualQuaternion(const Vector3&), dual(), Matrix4::transformPoint(), - * Quaternion::transformVectorNormalized() + * Quaternion::transformVectorNormalized(), DualComplex::transformPointNormalized() */ inline Vector3 transformPointNormalized(const Vector3& vector) const { CORRADE_ASSERT(lengthSquared() == Dual(1), diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index e36b9a7ef..4bd73a8ec 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -29,7 +29,8 @@ namespace Magnum { namespace Math { @tparam T Underlying data type Represents 2D transformation. See @ref matrix-vector for brief introduction. -@see Magnum::Matrix3, Magnum::Matrix3d, SceneGraph::MatrixTransformation2D +@see Magnum::Matrix3, Magnum::Matrix3d, DualComplex, + SceneGraph::MatrixTransformation2D @configurationvalueref{Magnum::Math::Matrix3} */ template class Matrix3: public Matrix<3, T> { @@ -234,7 +235,7 @@ template class Matrix3: public Matrix<3, T> { * transformation. @f[ * \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ 1 \end{pmatrix} * @f] - * @see Matrix4::transformPoint() + * @see DualComplex::transformPoint(), Matrix4::transformPoint() */ inline Vector2 transformPoint(const Vector2& vector) const { return ((*this)*Vector3(vector, T(1))).xy(); diff --git a/src/Math/Test/DualComplexTest.cpp b/src/Math/Test/DualComplexTest.cpp index acc5bd03e..242688540 100644 --- a/src/Math/Test/DualComplexTest.cpp +++ b/src/Math/Test/DualComplexTest.cpp @@ -47,6 +47,7 @@ class DualComplexTest: public Corrade::TestSuite::Tester { void translation(); void combinedTransformParts(); void matrix(); + void transformPoint(); void debug(); }; @@ -82,6 +83,7 @@ DualComplexTest::DualComplexTest() { &DualComplexTest::translation, &DualComplexTest::combinedTransformParts, &DualComplexTest::matrix, + &DualComplexTest::transformPoint, &DualComplexTest::debug); } @@ -216,6 +218,22 @@ void DualComplexTest::matrix() { CORRADE_COMPARE(a.matrix(), m); } +void DualComplexTest::transformPoint() { + DualComplex a = DualComplex::translation({2.0f, 3.0f})*DualComplex::rotation(Deg(23.0f)); + DualComplex b = DualComplex::rotation(Deg(23.0f))*DualComplex::translation({2.0f, 3.0f}); + Matrix3 m = Matrix3::translation({2.0f, 3.0f})*Matrix3::rotation(Deg(23.0f)); + Matrix3 n = Matrix3::rotation(Deg(23.0f))*Matrix3::translation({2.0f, 3.0f}); + Vector2 v(-3.6f, 0.7f); + + Vector2 transformedA = a.transformPoint(v); + CORRADE_COMPARE(transformedA, m.transformPoint(v)); + CORRADE_COMPARE(transformedA, Vector2(-1.58733f, 2.237721f)); + + Vector2 transformedB = b.transformPoint(v); + CORRADE_COMPARE(transformedB, n.transformPoint(v)); + CORRADE_COMPARE(transformedB, Vector2(-2.918512f, 2.780698f)); +} + void DualComplexTest::debug() { std::ostringstream o;