Browse Source

Math: transforming vectors with complex numbers.

pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
d59b620fd9
  1. 29
      src/Math/Complex.h
  2. 6
      src/Math/DualQuaternion.h
  3. 8
      src/Math/Matrix3.h
  4. 9
      src/Math/Matrix4.h
  5. 11
      src/Math/Quaternion.h
  6. 30
      src/Math/Test/ComplexTest.cpp
  7. 2
      src/Math/Test/QuaternionTest.cpp

29
src/Math/Complex.h

@ -340,6 +340,35 @@ template<class T> class Complex {
return conjugated();
}
/**
* @brief Rotate vector with complex number
*
* See transformVectorNormalized(), which is faster for normalized
* complex numbers. @f[
* v' = \frac c {|c|} v = \frac c {|c|} (v_x + iv_y)
* @f]
* @see Complex(const Vector2&), operator Vector2(), Matrix3::transformVector()
*/
inline Vector2<T> transformVector(const Vector2<T>& vector) const {
return Vector2<T>(normalized()*Complex<T>(vector));
}
/**
* @brief Rotate vector with normalized complex number
*
* Faster alternative to transformVector(), expects that the complex
* number is normalized. @f[
* v' = \frac c {|c|} v = cv = c(v_x + iv_y)
* @f]
* @see Complex(const Vector2&), operator Vector2(), Matrix3::transformVector()
*/
inline Vector2<T> transformVectorNormalized(const Vector2<T>& vector) const {
CORRADE_ASSERT(MathTypeTraits<T>::equals(dot(), T(1)),
"Math::Complex::transformVectorNormalized(): complex number must be normalized",
Vector2<T>(std::numeric_limits<T>::quiet_NaN()));
return Vector2<T>((*this)*Complex<T>(vector));
}
private:
T _real, _imaginary;
};

6
src/Math/DualQuaternion.h

@ -251,7 +251,8 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* quaternions. @f[
* v' = qv \overline{\hat q^{-1}} = q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^{-1}}
* @f]
* @see DualQuaternion(const Vector3&), Matrix4::transformPoint(), Quaternion::transformVector()
* @see DualQuaternion(const Vector3&), dual(), Matrix4::transformPoint(),
* Quaternion::transformVector()
*/
inline Vector3<T> transformPoint(const Vector3<T>& vector) const {
return ((*this)*DualQuaternion<T>(vector)*inverted().dualConjugated()).dual().vector();
@ -264,7 +265,8 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* quaternion is normalized. @f[
* v' = qv \overline{\hat q^{-1}} = qv \overline{\hat q^*} = q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^*}
* @f]
* @see DualQuaternion(const Vector3&), Matrix4::transformPoint(), Quaternion::transformVectorNormalized()
* @see DualQuaternion(const Vector3&), dual(), Matrix4::transformPoint(),
* Quaternion::transformVectorNormalized()
*/
inline Vector3<T> transformPointNormalized(const Vector3<T>& vector) const {
CORRADE_ASSERT(MathTypeTraits<Dual<T>>::equals(lengthSquared(), Dual<T>(1)),

8
src/Math/Matrix3.h

@ -212,10 +212,11 @@ template<class T> class Matrix3: public Matrix<3, T> {
/**
* @brief Transform 2D vector with the matrix
*
* Translation is not involved in the transformation. @f[
* Unlike in transformPoint(), translation is not involved in the
* transformation. @f[
* \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ 0 \end{pmatrix}
* @f]
* @see transformPoint(), Matrix4::transformVector()
* @see Complex::transformVector(), Matrix4::transformVector()
*/
inline Vector2<T> transformVector(const Vector2<T>& vector) const {
return ((*this)*Vector3<T>(vector, T(0))).xy();
@ -224,7 +225,8 @@ template<class T> class Matrix3: public Matrix<3, T> {
/**
* @brief Transform 2D point with the matrix
*
* Unlike in transformVector(), translation is also involved. @f[
* Unlike in transformVector(), translation is also involved in the
* transformation. @f[
* \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ 1 \end{pmatrix}
* @f]
* @see Matrix4::transformPoint()

9
src/Math/Matrix4.h

@ -359,11 +359,11 @@ template<class T> class Matrix4: public Matrix<4, T> {
/**
* @brief Transform 3D vector with the matrix
*
* Translation is not involved in the transformation. @f[
* Unlike in transformVector(), translation is not involved in the
* transformation. @f[
* \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ v_z \\ 0 \end{pmatrix}
* @f]
* @see transformPoint(), Quaternion::transformVector(),
* Matrix3::transformVector()
* @see Quaternion::transformVector(), Matrix3::transformVector()
*/
inline Vector3<T> transformVector(const Vector3<T>& vector) const {
return ((*this)*Vector4<T>(vector, T(0))).xyz();
@ -372,7 +372,8 @@ template<class T> class Matrix4: public Matrix<4, T> {
/**
* @brief Transform 3D point with the matrix
*
* Unlike in transformVector(), translation is also involved. @f[
* Unlike in transformVector(), translation is also involved in the
* transformation. @f[
* \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ v_z \\ 1 \end{pmatrix}
* @f]
* @see DualQuaternion::transformPoint(), Matrix3::transformPoint()

11
src/Math/Quaternion.h

@ -408,7 +408,8 @@ template<class T> class Quaternion {
* quaternions. @f[
* v' = qvq^{-1} = q [\boldsymbol v, 0] q^{-1}
* @f]
* @see Quaternion(const Vector3&), Matrix4::transformVector(), DualQuaternion::transformPoint()
* @see Quaternion(const Vector3&), vector(), Matrix4::transformVector(),
* DualQuaternion::transformPoint(), Complex::transformVector()
*/
inline Vector3<T> transformVector(const Vector3<T>& vector) const {
return ((*this)*Quaternion<T>(vector)*inverted()).vector();
@ -417,11 +418,13 @@ template<class T> class Quaternion {
/**
* @brief Rotate vector with normalized quaternion
*
* Faster alternative to transformVector(), expects that the quaternion is
* normalized. @f[
* Faster alternative to transformVector(), expects that the quaternion
* is normalized. @f[
* v' = qvq^{-1} = qvq^* = q [\boldsymbol v, 0] q^*
* @f]
* @see Quaternion(const Vector3&), Matrix4::transformVector(), DualQuaternion::transformPointNormalized()
* @see Quaternion(const Vector3&), vector(), Matrix4::transformVector(),
* DualQuaternion::transformPointNormalized(),
* Complex::transformVectorNormalized()
*/
inline Vector3<T> transformVectorNormalized(const Vector3<T>& vector) const {
CORRADE_ASSERT(MathTypeTraits<T>::equals(dot(), T(1)),

30
src/Math/Test/ComplexTest.cpp

@ -49,6 +49,8 @@ class ComplexTest: public Corrade::TestSuite::Tester {
void angle();
void rotation();
void matrix();
void transformVector();
void transformVectorNormalized();
void debug();
};
@ -78,6 +80,8 @@ ComplexTest::ComplexTest() {
&ComplexTest::angle,
&ComplexTest::rotation,
&ComplexTest::matrix,
&ComplexTest::transformVector,
&ComplexTest::transformVectorNormalized,
&ComplexTest::debug);
}
@ -266,6 +270,32 @@ void ComplexTest::matrix() {
CORRADE_COMPARE(a.matrix(), m);
}
void ComplexTest::transformVector() {
Complex a = Complex::rotation(Deg(23.0f));
Matrix3 m = Matrix3::rotation(Deg(23.0f));
Vector2 v(-3.6f, 0.7f);
Vector2 rotated = a.transformVector(v);
CORRADE_COMPARE(rotated, m.transformVector(v));
CORRADE_COMPARE(rotated, Vector2(-3.58733f, -0.762279f));
}
void ComplexTest::transformVectorNormalized() {
Complex a = Complex::rotation(Deg(23.0f));
Matrix3 m = Matrix3::rotation(Deg(23.0f));
Vector2 v(-3.6f, 0.7f);
std::ostringstream o;
Error::setOutput(&o);
Vector2 notRotated = (a*2).transformVectorNormalized(v);
CORRADE_VERIFY(notRotated != notRotated);
CORRADE_COMPARE(o.str(), "Math::Complex::transformVectorNormalized(): complex number must be normalized\n");
Vector2 rotated = a.transformVectorNormalized(v);
CORRADE_COMPARE(rotated, m.transformVector(v));
CORRADE_COMPARE(rotated, a.transformVector(v));
}
void ComplexTest::debug() {
std::ostringstream o;

2
src/Math/Test/QuaternionTest.cpp

@ -340,7 +340,7 @@ void QuaternionTest::transformVectorNormalized() {
Vector3 v(5.0f, -3.6f, 0.7f);
std::ostringstream o;
Corrade::Utility::Error::setOutput(&o);
Error::setOutput(&o);
Vector3 notRotated = (a*2).transformVectorNormalized(v);
CORRADE_VERIFY(notRotated != notRotated);
CORRADE_COMPARE(o.str(), "Math::Quaternion::transformVectorNormalized(): quaternion must be normalized\n");

Loading…
Cancel
Save