diff --git a/src/Math/Complex.h b/src/Math/Complex.h index de6e0334c..665523e1c 100644 --- a/src/Math/Complex.h +++ b/src/Math/Complex.h @@ -140,6 +140,7 @@ template class Complex { * @f[ * \theta = atan2(b, a) * @f] + * @see rotation(), DualComplex::rotationAngle() */ inline Rad rotationAngle() const { return Rad(std::atan2(_imaginary, _real)); diff --git a/src/Math/DualComplex.h b/src/Math/DualComplex.h index 10e3a7a5a..483011ee7 100644 --- a/src/Math/DualComplex.h +++ b/src/Math/DualComplex.h @@ -35,6 +35,20 @@ template class DualComplex: public Dual> { public: typedef T Type; /**< @brief Underlying data type */ + /** + * @brief Rotation dual complex number + * @param angle Rotation angle (counterclockwise) + * + * @f[ + * \hat c = (cos \theta + i sin \theta) + \epsilon (0 + i0) + * @f] + * @see rotationAngle(), Complex::rotation(), Matrix3::rotation(), + * DualQuaternion::rotation() + */ + inline static DualComplex rotation(Rad angle) { + return {Complex::rotation(angle), {{}, {}}}; + } + /** * @brief Default constructor * @@ -58,6 +72,18 @@ template class DualComplex: public Dual> { */ inline constexpr /*implicit*/ DualComplex(const Complex& real, const Complex& dual): Dual>(real, dual) {} + /** + * @brief Rotation angle of dual complex number + * + * @f[ + * \theta = atan2(b_0, a_0) + * @f] + * @see rotation(), Complex::rotationAngle() + */ + inline Rad rotationAngle() const { + return this->real().rotationAngle(); + } + /** * @brief Complex-conjugated dual complex number * diff --git a/src/Math/DualQuaternion.h b/src/Math/DualQuaternion.h index 8000e8480..3f58a20bd 100644 --- a/src/Math/DualQuaternion.h +++ b/src/Math/DualQuaternion.h @@ -38,15 +38,15 @@ template class DualQuaternion: public Dual> { /** * @brief Rotation dual quaternion - * @param angle Rotation angle (counterclockwise, in radians) + * @param angle Rotation angle (counterclockwise) * @param normalizedAxis Normalized rotation axis * * Expects that the rotation axis is normalized. @f[ * \hat q = [\boldsymbol a \cdot sin \frac \theta 2, cos \frac \theta 2] + \epsilon [\boldsymbol 0, 0] * @f] * @see rotationAngle(), rotationAxis(), Quaternion::rotation(), - * Matrix4::rotation(), Vector3::xAxis(), Vector3::yAxis(), - * Vector3::zAxis() + * Matrix4::rotation(), DualComplex::rotation(), Vector3::xAxis(), + * Vector3::yAxis(), Vector3::zAxis() */ inline static DualQuaternion rotation(Rad angle, const Vector3& normalizedAxis) { return {Quaternion::rotation(angle, normalizedAxis), {{}, T(0)}}; diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index e67e909cf..8f9ae7002 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -64,7 +64,7 @@ template class Matrix3: public Matrix<3, T> { * @brief 2D rotation matrix * @param angle Rotation angle (counterclockwise) * - * @see rotation() const, Complex::rotation(), + * @see rotation() const, Complex::rotation(), DualComplex::rotation(), * Matrix4::rotation(Rad, const Vector3&) */ static Matrix3 rotation(Rad angle) { diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index dfa9dad5f..8333b2271 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -76,9 +76,9 @@ template class Matrix4: public Matrix<4, T> { * * Expects that the rotation axis is normalized. If possible, use * faster alternatives like rotationX(), rotationY() and rotationZ(). - * @see rotation() const, DualQuaternion::rotation(), - * Quaternion::rotation(), Matrix3::rotation(Rad), Vector3::xAxis(), - * Vector3::yAxis(), Vector3::zAxis() + * @see rotation() const, Quaternion::rotation(), DualQuaternion::rotation(), + * Matrix3::rotation(Rad), Vector3::xAxis(), Vector3::yAxis(), + * Vector3::zAxis() */ static Matrix4 rotation(Rad angle, const Vector3& normalizedAxis) { CORRADE_ASSERT(MathTypeTraits::equals(normalizedAxis.dot(), T(1)), diff --git a/src/Math/Quaternion.h b/src/Math/Quaternion.h index de204ca00..8592e26f9 100644 --- a/src/Math/Quaternion.h +++ b/src/Math/Quaternion.h @@ -175,7 +175,7 @@ template class Quaternion { * Expects that the quaternion is normalized. @f[ * \theta = 2 \cdot acos q_S * @f] - * @see rotationAxis(), rotation() + * @see rotationAxis(), rotation(), DualQuaternion::rotationAngle() */ inline Rad rotationAngle() const { CORRADE_ASSERT(MathTypeTraits::equals(dot(), T(1)), diff --git a/src/Math/Test/DualComplexTest.cpp b/src/Math/Test/DualComplexTest.cpp index 15b9644f9..38cc9e38b 100644 --- a/src/Math/Test/DualComplexTest.cpp +++ b/src/Math/Test/DualComplexTest.cpp @@ -39,9 +39,13 @@ class DualComplexTest: public Corrade::TestSuite::Tester { void inverted(); void invertedNormalized(); + void rotation(); + void debug(); }; +typedef Math::Deg Deg; +typedef Math::Rad Rad; typedef Math::Complex Complex; typedef Math::Dual Dual; typedef Math::DualComplex DualComplex; @@ -62,6 +66,8 @@ DualComplexTest::DualComplexTest() { &DualComplexTest::inverted, &DualComplexTest::invertedNormalized, + &DualComplexTest::rotation, + &DualComplexTest::debug); } @@ -149,6 +155,12 @@ void DualComplexTest::invertedNormalized() { CORRADE_COMPARE(inverted, b/Math::sqrt(Dual(7.25f, -43.5f))); } +void DualComplexTest::rotation() { + DualComplex a = DualComplex::rotation(Deg(120.0f)); + CORRADE_COMPARE(a, DualComplex({-0.5f, 0.8660254f}, {0.0f, 0.0f})); + CORRADE_COMPARE_AS(a.rotationAngle(), Deg(120.0f), Rad); +} + void DualComplexTest::debug() { std::ostringstream o;