Wm4Matrix3.h

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.2 (2006/09/05)
00016 
00017 #ifndef WM4MATRIX3_H
00018 #define WM4MATRIX3_H
00019 
00020 // Matrix operations are applied on the left.  For example, given a matrix M
00021 // and a vector V, matrix-times-vector is M*V.  That is, V is treated as a
00022 // column vector.  Some graphics APIs use V*M where V is treated as a row
00023 // vector.  In this context the "M" matrix is really a transpose of the M as
00024 // represented in Wild Magic.  Similarly, to apply two matrix operations M0
00025 // and M1, in that order, you compute M1*M0 so that the transform of a vector
00026 // is (M1*M0)*V = M1*(M0*V).  Some graphics APIs use M0*M1, but again these
00027 // matrices are the transpose of those as represented in Wild Magic.  You
00028 // must therefore be careful about how you interface the transformation code
00029 // with graphics APIS.
00030 //
00031 // For memory organization it might seem natural to chose Real[N][N] for the
00032 // matrix storage, but this can be a problem on a platform/console that
00033 // chooses to store the data in column-major rather than row-major format.
00034 // To avoid potential portability problems, the matrix is stored as Real[N*N]
00035 // and organized in row-major order.  That is, the entry of the matrix in row
00036 // r (0 <= r < N) and column c (0 <= c < N) is stored at index i = c+N*r
00037 // (0 <= i < N*N).
00038 
00039 // The (x,y,z) coordinate system is assumed to be right-handed.  Coordinate
00040 // axis rotation matrices are of the form
00041 //   RX =    1       0       0
00042 //           0     cos(t) -sin(t)
00043 //           0     sin(t)  cos(t)
00044 // where t > 0 indicates a counterclockwise rotation in the yz-plane
00045 //   RY =  cos(t)    0     sin(t)
00046 //           0       1       0
00047 //        -sin(t)    0     cos(t)
00048 // where t > 0 indicates a counterclockwise rotation in the zx-plane
00049 //   RZ =  cos(t) -sin(t)    0
00050 //         sin(t)  cos(t)    0
00051 //           0       0       1
00052 // where t > 0 indicates a counterclockwise rotation in the xy-plane.
00053 
00054 #include "Wm4FoundationLIB.h"
00055 #include "Wm4Vector3.h"
00056 
00057 namespace Wm4
00058 {
00059 
00060 template <class Real>
00061 class Matrix3
00062 {
00063 public:
00064     // If bZero is true, create the zero matrix.  Otherwise, create the
00065     // identity matrix.
00066     Matrix3 (bool bZero = true);
00067 
00068     // copy constructor
00069     Matrix3 (const Matrix3& rkM);
00070 
00071     // input Mrc is in row r, column c.
00072     Matrix3 (Real fM00, Real fM01, Real fM02,
00073              Real fM10, Real fM11, Real fM12,
00074              Real fM20, Real fM21, Real fM22);
00075 
00076     // Create a matrix from an array of numbers.  The input array is
00077     // interpreted based on the Boolean input as
00078     //   true:  entry[0..8]={m00,m01,m02,m10,m11,m12,m20,m21,m22} [row major]
00079     //   false: entry[0..8]={m00,m10,m20,m01,m11,m21,m02,m12,m22} [col major]
00080     Matrix3 (const Real afEntry[9], bool bRowMajor);
00081 
00082     // Create matrices based on vector input.  The Boolean is interpreted as
00083     //   true: vectors are columns of the matrix
00084     //   false: vectors are rows of the matrix
00085     Matrix3 (const Vector3<Real>& rkU, const Vector3<Real>& rkV,
00086         const Vector3<Real>& rkW, bool bColumns);
00087     Matrix3 (const Vector3<Real>* akV, bool bColumns);
00088 
00089     // create a diagonal matrix
00090     Matrix3 (Real fM00, Real fM11, Real fM22);
00091 
00092     // Create rotation matrices (positive angle - counterclockwise).  The
00093     // angle must be in radians, not degrees.
00094     Matrix3 (const Vector3<Real>& rkAxis, Real fAngle);
00095 
00096     // create a tensor product U*V^T
00097     Matrix3 (const Vector3<Real>& rkU, const Vector3<Real>& rkV);
00098 
00099     // create various matrices
00100     Matrix3& MakeZero ();
00101     Matrix3& MakeIdentity ();
00102     Matrix3& MakeDiagonal (Real fM00, Real fM11, Real fM22);
00103     Matrix3& FromAxisAngle (const Vector3<Real>& rkAxis, Real fAngle);
00104     Matrix3& MakeTensorProduct (const Vector3<Real>& rkU,
00105         const Vector3<Real>& rkV);
00106 
00107     // member access
00108     operator const Real* () const;
00109     operator Real* ();
00110     const Real* operator[] (int iRow) const;
00111     Real* operator[] (int iRow);
00112     Real operator() (int iRow, int iCol) const;
00113     Real& operator() (int iRow, int iCol);
00114     void SetRow (int iRow, const Vector3<Real>& rkV);
00115     Vector3<Real> GetRow (int iRow) const;
00116     void SetColumn (int iCol, const Vector3<Real>& rkV);
00117     Vector3<Real> GetColumn (int iCol) const;
00118     void GetColumnMajor (Real* afCMajor) const;
00119 
00120     // assignment
00121     Matrix3& operator= (const Matrix3& rkM);
00122 
00123     // comparison
00124     bool operator== (const Matrix3& rkM) const;
00125     bool operator!= (const Matrix3& rkM) const;
00126     bool operator<  (const Matrix3& rkM) const;
00127     bool operator<= (const Matrix3& rkM) const;
00128     bool operator>  (const Matrix3& rkM) const;
00129     bool operator>= (const Matrix3& rkM) const;
00130 
00131     // arithmetic operations
00132     Matrix3 operator+ (const Matrix3& rkM) const;
00133     Matrix3 operator- (const Matrix3& rkM) const;
00134     Matrix3 operator* (const Matrix3& rkM) const;
00135     Matrix3 operator* (Real fScalar) const;
00136     Matrix3 operator/ (Real fScalar) const;
00137     Matrix3 operator- () const;
00138 
00139     // arithmetic updates
00140     Matrix3& operator+= (const Matrix3& rkM);
00141     Matrix3& operator-= (const Matrix3& rkM);
00142     Matrix3& operator*= (Real fScalar);
00143     Matrix3& operator/= (Real fScalar);
00144 
00145     // matrix times vector
00146     Vector3<Real> operator* (const Vector3<Real>& rkV) const;  // M * v
00147 
00148     // other operations
00149     Matrix3 Transpose () const;  // M^T
00150     Matrix3 TransposeTimes (const Matrix3& rkM) const;  // this^T * M
00151     Matrix3 TimesTranspose (const Matrix3& rkM) const;  // this * M^T
00152     Matrix3 Inverse () const;
00153     Matrix3 Adjoint () const;
00154     Real Determinant () const;
00155     Real QForm (const Vector3<Real>& rkU,
00156         const Vector3<Real>& rkV) const;  // u^T*M*v
00157     Matrix3 TimesDiagonal (const Vector3<Real>& rkDiag) const;  // M*D
00158     Matrix3 DiagonalTimes (const Vector3<Real>& rkDiag) const;  // D*M
00159 
00160     // The matrix must be a rotation for these functions to be valid.  The
00161     // last function uses Gram-Schmidt orthonormalization applied to the
00162     // columns of the rotation matrix.  The angle must be in radians, not
00163     // degrees.
00164     void ToAxisAngle (Vector3<Real>& rkAxis, Real& rfAngle) const;
00165     void Orthonormalize ();
00166 
00167     // The matrix must be symmetric.  Factor M = R * D * R^T where
00168     // R = [u0|u1|u2] is a rotation matrix with columns u0, u1, and u2 and
00169     // D = diag(d0,d1,d2) is a diagonal matrix whose diagonal entries are d0,
00170     // d1, and d2.  The eigenvector u[i] corresponds to eigenvector d[i].
00171     // The eigenvalues are ordered as d0 <= d1 <= d2.
00172     void EigenDecomposition (Matrix3& rkRot, Matrix3& rkDiag) const;
00173 
00174     // Create rotation matrices from Euler angles.
00175     Matrix3& FromEulerAnglesXYZ (Real fXAngle, Real fYAngle, Real fZAngle);
00176     Matrix3& FromEulerAnglesXZY (Real fXAngle, Real fZAngle, Real fYAngle);
00177     Matrix3& FromEulerAnglesYXZ (Real fYAngle, Real fXAngle, Real fZAngle);
00178     Matrix3& FromEulerAnglesYZX (Real fYAngle, Real fZAngle, Real fXAngle);
00179     Matrix3& FromEulerAnglesZXY (Real fZAngle, Real fXAngle, Real fYAngle);
00180     Matrix3& FromEulerAnglesZYX (Real fZAngle, Real fYAngle, Real fXAngle);
00181 
00182     // Extract Euler angles from rotation matrices.  The return value is
00183     // 'true' iff the factorization is unique relative to certain angle
00184     // ranges.  That is, if (U,V,W) is some permutation of (X,Y,Z), the angle
00185     // ranges for the outputs from ToEulerAnglesUVW(uAngle,vAngle,wAngle) are
00186     // uAngle in [-pi,pi], vAngle in [-pi/2,pi/2], and wAngle in [-pi,pi].  If
00187     // the function returns 'false', wAngle is 0 and vAngle is either pi/2 or
00188     // -pi/2.
00189     bool ToEulerAnglesXYZ (Real& rfXAngle, Real& rfYAngle, Real& rfZAngle)
00190         const;
00191     bool ToEulerAnglesXZY (Real& rfXAngle, Real& rfZAngle, Real& rfYAngle)
00192         const;
00193     bool ToEulerAnglesYXZ (Real& rfYAngle, Real& rfXAngle, Real& rfZAngle)
00194         const;
00195     bool ToEulerAnglesYZX (Real& rfYAngle, Real& rfZAngle, Real& rfXAngle)
00196         const;
00197     bool ToEulerAnglesZXY (Real& rfZAngle, Real& rfXAngle, Real& rfYAngle)
00198         const;
00199     bool ToEulerAnglesZYX (Real& rfZAngle, Real& rfYAngle, Real& rfXAngle)
00200         const;
00201 
00202     // SLERP (spherical linear interpolation) without quaternions.  Computes
00203     // R(t) = R0*(Transpose(R0)*R1)^t.  If Q is a rotation matrix with
00204     // unit-length axis U and angle A, then Q^t is a rotation matrix with
00205     // unit-length axis U and rotation angle t*A.
00206     Matrix3& Slerp (Real fT, const Matrix3& rkR0, const Matrix3& rkR1);
00207 
00208     // Singular value decomposition, M = L*S*R, where L and R are orthogonal
00209     // and S is a diagonal matrix whose diagonal entries are nonnegative.
00210     void SingularValueDecomposition (Matrix3& rkL, Matrix3& rkS,
00211         Matrix3& rkR) const;
00212     void SingularValueComposition (const Matrix3& rkL, const Matrix3& rkS,
00213         const Matrix3& rkR);
00214 
00215     // factor M = Q*D*U with orthogonal Q, diagonal D, upper triangular U
00216     void QDUDecomposition (Matrix3& rkQ, Matrix3& rkD, Matrix3& rkU) const;
00217 
00218     // special matrices
00219     WM4_FOUNDATION_ITEM static const Matrix3 ZERO;
00220     WM4_FOUNDATION_ITEM static const Matrix3 IDENTITY;
00221 
00222 private:
00223     // Support for eigendecomposition.  The Tridiagonalize function applies
00224     // a Householder transformation to the matrix.  If that transformation
00225     // is the identity (the matrix is already tridiagonal), then the return
00226     // value is 'false'.  Otherwise, the transformation is a reflection and
00227     // the return value is 'true'.  The QLAlgorithm returns 'true' iff the
00228     // QL iteration scheme converged.
00229     bool Tridiagonalize (Real afDiag[3], Real afSubd[2]);
00230     bool QLAlgorithm (Real afDiag[3], Real afSubd[2]);
00231 
00232     // support for singular value decomposition
00233     static void Bidiagonalize (Matrix3& rkA, Matrix3& rkL, Matrix3& rkR);
00234     static void GolubKahanStep (Matrix3& rkA, Matrix3& rkL, Matrix3& rkR);
00235 
00236     // support for comparisons
00237     int CompareArrays (const Matrix3& rkM) const;
00238 
00239     Real m_afEntry[9];
00240 };
00241 
00242 // c * M
00243 template <class Real>
00244 Matrix3<Real> operator* (Real fScalar, const Matrix3<Real>& rkM);
00245 
00246 // v^T * M
00247 template <class Real>
00248 Vector3<Real> operator* (const Vector3<Real>& rkV, const Matrix3<Real>& rkM);
00249 
00250 } //namespace Wm4
00251 
00252 #include "Wm4Matrix3.inl"
00253 
00254 namespace Wm4
00255 {
00256 typedef Matrix3<float> Matrix3f;
00257 typedef Matrix3<double> Matrix3d;
00258 }
00259 
00260 #endif

Generated on Wed Nov 23 19:01:05 2011 for FreeCAD by  doxygen 1.6.1