matrix44.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #ifndef __VCGLIB_MATRIX44
00025 #define __VCGLIB_MATRIX44
00026 
00027 #include <memory.h>
00028 #include <vcg/math/base.h>
00029 #include <vcg/space/point3.h>
00030 #include <vcg/space/point4.h>
00031 #include <vector>
00032 #include <iostream>
00033 #include <eigenlib/Eigen/Core>
00034 #include <eigenlib/Eigen/LU>
00035 
00036 namespace vcg {
00037 
00038 /*
00039     Annotations:
00040 Opengl stores matrix in  column-major order. That is, the matrix is stored as:
00041 
00042     a0  a4  a8  a12
00043     a1  a5  a9  a13
00044     a2  a6  a10 a14
00045     a3  a7  a11 a15
00046 
00047   Usually in opengl (see opengl specs) vectors are 'column' vectors
00048   so usually matrix are PRE-multiplied for a vector.
00049   So the command glTranslate generate a matrix that
00050   is ready to be premultipled for a vector:
00051 
00052     1 0 0 tx
00053     0 1 0 ty
00054     0 0 1 tz
00055     0 0 0  1
00056 
00057 Matrix44 stores matrix in row-major order i.e.
00058 
00059     a0  a1  a2  a3
00060     a4  a5  a6  a7
00061     a8  a9  a10 a11
00062     a12 a13 a14 a15
00063 
00064 So for the use of that matrix in opengl with their supposed meaning you have to transpose them before feeding to glMultMatrix.
00065 This mechanism is hidden by the templated function defined in wrap/gl/math.h;
00066 If your machine has the ARB_transpose_matrix extension it will use the appropriate;
00067 The various gl-like command SetRotate, SetTranslate assume that you are making matrix
00068 for 'column' vectors.
00069 
00070 */
00071 
00074 template <class T> class Matrix44 {
00075 protected:
00076     T _a[16];
00077 
00078 public:
00079     typedef T ScalarType;
00080 
00082 
00086     Matrix44() {}
00087     ~Matrix44() {}
00088     Matrix44(const Matrix44 &m);
00089     Matrix44(const T v[]);
00090 
00091     T &ElementAt(const int row, const int col);
00092     T ElementAt(const int row, const int col) const;
00093     //T &operator[](const int i);
00094     //const T &operator[](const int i) const;
00095     T *V();
00096     const T *V() const ;
00097 
00098     T *operator[](const int i);
00099     const T *operator[](const int i) const;
00100 
00101     // return a copy of the i-th column
00102     Point4<T> GetColumn4(const int& i)const{
00103         assert(i>=0 && i<4);
00104         return Point4<T>(ElementAt(0,i),ElementAt(1,i),ElementAt(2,i),ElementAt(3,i));
00105         //return Point4<T>(_a[i],_a[i+4],_a[i+8],_a[i+12]);
00106     }
00107 
00108     Point3<T> GetColumn3(const int& i)const{
00109         assert(i>=0 && i<4);
00110         return Point3<T>(ElementAt(0,i),ElementAt(1,i),ElementAt(2,i));
00111     }
00112 
00113     Point4<T> GetRow4(const int& i)const{
00114         assert(i>=0 && i<4);
00115         return Point4<T>(ElementAt(i,0),ElementAt(i,1),ElementAt(i,2),ElementAt(i,3));
00116         // return *((Point4<T>*)(&_a[i<<2])); alternativa forse + efficiente
00117     }
00118 
00119     Point3<T> GetRow3(const int& i)const{
00120         assert(i>=0 && i<4);
00121         return Point3<T>(ElementAt(i,0),ElementAt(i,1),ElementAt(i,2));
00122         // return *((Point4<T>*)(&_a[i<<2])); alternativa forse + efficiente
00123     }
00124 
00125     Matrix44 operator+(const Matrix44 &m) const;
00126     Matrix44 operator-(const Matrix44 &m) const;
00127     Matrix44 operator*(const Matrix44 &m) const;
00128     Point4<T> operator*(const Point4<T> &v) const;
00129 
00130     bool operator==(const  Matrix44 &m) const;
00131     bool operator!= (const  Matrix44 &m) const;
00132 
00133     Matrix44 operator-() const;
00134     Matrix44 operator*(const T k) const;
00135     void operator+=(const Matrix44 &m);
00136     void operator-=(const Matrix44 &m);
00137     void operator*=( const Matrix44 & m );
00138     void operator*=( const T k );
00139 
00140     template <class Matrix44Type>
00141     void ToMatrix(Matrix44Type & m) const {for(int i = 0; i < 16; i++) m.V()[i]=V()[i];}
00142 
00143     void ToEulerAngles(T &alpha, T &beta, T &gamma);
00144 
00145     template <class Matrix44Type>
00146     void FromMatrix(const Matrix44Type & m){for(int i = 0; i < 16; i++) V()[i]=m.V()[i];}
00147 
00148     template <class EigenMatrix44Type>
00149     void ToEigenMatrix(EigenMatrix44Type & m) const {
00150         for(int i = 0; i < 4; i++)
00151             for(int j = 0; j < 4; j++)
00152                 m(i,j)=(*this)[i][j];
00153     }
00154 
00155     template <class EigenMatrix44Type>
00156     void FromEigenMatrix(const EigenMatrix44Type & m){
00157         for(int i = 0; i < 4; i++)
00158             for(int j = 0; j < 4; j++)
00159                 ElementAt(i,j)=T(m(i,j));
00160     }
00161 
00162     void FromEulerAngles(T alpha, T beta, T gamma);
00163     void SetZero();
00164     void SetIdentity();
00165     void SetDiagonal(const T k);
00166     Matrix44 &SetScale(const T sx, const T sy, const T sz);
00167     Matrix44 &SetScale(const Point3<T> &t);
00168     Matrix44<T>& SetColumn(const unsigned int ii,const Point4<T> &t);
00169     Matrix44<T>& SetColumn(const unsigned int ii,const Point3<T> &t);
00170     Matrix44 &SetTranslate(const Point3<T> &t);
00171     Matrix44 &SetTranslate(const T sx, const T sy, const T sz);
00172     Matrix44 &SetShearXY(const T sz);
00173     Matrix44 &SetShearXZ(const T sy);
00174     Matrix44 &SetShearYZ(const T sx);
00175 
00177     Matrix44 &SetRotateDeg(T AngleDeg, const Point3<T> & axis);
00178     Matrix44 &SetRotateRad(T AngleRad, const Point3<T> & axis);
00179 
00180     T Determinant() const;
00181 
00182     template <class Q> void Import(const Matrix44<Q> &m) {
00183         for(int i = 0; i < 16; i++)
00184             _a[i] = (T)(m.V()[i]);
00185     }
00186     template <class Q>
00187     static inline Matrix44 Construct( const Matrix44<Q> & b )
00188     {
00189         Matrix44<T> tmp; tmp.FromMatrix(b);
00190         return tmp;
00191     }
00192 
00193     static inline const Matrix44 &Identity( )
00194     {
00195         static Matrix44<T> tmp; tmp.SetIdentity();
00196         return tmp;
00197     }
00198 
00199     // for the transistion to eigen
00200     Matrix44 transpose() const
00201     {
00202         Matrix44 res = *this;
00203         Transpose(res);
00204         return res;
00205     }
00206     void transposeInPlace() { Transpose(*this); }
00207 
00208     void print() {
00209         unsigned int i, j, p;
00210         for (i=0, p=0; i<4; i++, p+=4)
00211         {
00212             std::cout << "[\t";
00213             for (j=0; j<4; j++)
00214                 std::cout << _a[p+j] << "\t";
00215 
00216             std::cout << "]\n";
00217         }
00218         std::cout << "\n";
00219     }
00220 
00221 };
00222 
00223 /*** Postmultiply */
00224 //template <class T> Point3<T> operator*(const Point3<T> &p, const Matrix44<T> &m);
00225 
00227 template <class T> Point3<T> operator*(const Matrix44<T> &m, const Point3<T> &p);
00228 
00229 template <class T> Matrix44<T> &Transpose(Matrix44<T> &m);
00230 //return NULL matrix if not invertible
00231 template <class T> Matrix44<T> Inverse(const Matrix44<T> &m);
00232 
00233 typedef Matrix44<short>  Matrix44s;
00234 typedef Matrix44<int>    Matrix44i;
00235 typedef Matrix44<float>  Matrix44f;
00236 typedef Matrix44<double> Matrix44d;
00237 
00238 
00239 
00240 template <class T> Matrix44<T>::Matrix44(const Matrix44<T> &m) {
00241     memcpy((T *)_a, (const T *)m._a, 16 * sizeof(T));
00242 }
00243 
00244 template <class T> Matrix44<T>::Matrix44(const T v[]) {
00245     memcpy((T *)_a, v, 16 * sizeof(T));
00246 }
00247 
00248 template <class T> T &Matrix44<T>::ElementAt(const int row, const int col) {
00249     assert(row >= 0 && row < 4);
00250     assert(col >= 0 && col < 4);
00251     return _a[(row<<2) + col];
00252 }
00253 
00254 template <class T> T Matrix44<T>::ElementAt(const int row, const int col) const {
00255     assert(row >= 0 && row < 4);
00256     assert(col >= 0 && col < 4);
00257     return _a[(row<<2) + col];
00258 }
00259 
00260 //template <class T> T &Matrix44<T>::operator[](const int i) {
00261 //      assert(i >= 0 && i < 16);
00262 //      return ((T *)_a)[i];
00263 //}
00264 //
00265 //template <class T> const T &Matrix44<T>::operator[](const int i) const {
00266 //      assert(i >= 0 && i < 16);
00267 //      return ((T *)_a)[i];
00268 //}
00269 template <class T> T *Matrix44<T>::operator[](const int i) {
00270     assert(i >= 0 && i < 4);
00271     return _a+i*4;
00272 }
00273 
00274 template <class T> const T *Matrix44<T>::operator[](const int i) const {
00275     assert(i >= 0 && i < 4);
00276     return _a+i*4;
00277 }
00278 template <class T>  T *Matrix44<T>::V()  { return _a;}
00279 template <class T> const T *Matrix44<T>::V() const { return _a;}
00280 
00281 
00282 template <class T> Matrix44<T> Matrix44<T>::operator+(const Matrix44 &m) const {
00283     Matrix44<T> ret;
00284     for(int i = 0; i < 16; i++)
00285         ret.V()[i] = V()[i] + m.V()[i];
00286     return ret;
00287 }
00288 
00289 template <class T> Matrix44<T> Matrix44<T>::operator-(const Matrix44 &m) const {
00290     Matrix44<T> ret;
00291     for(int i = 0; i < 16; i++)
00292         ret.V()[i] = V()[i] - m.V()[i];
00293     return ret;
00294 }
00295 
00296 template <class T> Matrix44<T> Matrix44<T>::operator*(const Matrix44 &m) const {
00297     Matrix44 ret;
00298     for(int i = 0; i < 4; i++)
00299         for(int j = 0; j < 4; j++) {
00300             T t = 0.0;
00301             for(int k = 0; k < 4; k++)
00302                 t += ElementAt(i, k) * m.ElementAt(k, j);
00303             ret.ElementAt(i, j) = t;
00304         }
00305     return ret;
00306 }
00307 
00308 template <class T> Point4<T> Matrix44<T>::operator*(const Point4<T> &v) const {
00309     Point4<T> ret;
00310     for(int i = 0; i < 4; i++){
00311         T t = 0.0;
00312         for(int k = 0; k < 4; k++)
00313             t += ElementAt(i,k) * v[k];
00314         ret[i] = t;
00315     }
00316     return ret;
00317 }
00318 
00319 
00320 template <class T> bool Matrix44<T>::operator==(const  Matrix44 &m) const {
00321     for(int i = 0; i < 4; ++i)
00322         for(int j = 0; j < 4; ++j)
00323             if(ElementAt(i,j) != m.ElementAt(i,j))
00324                 return false;
00325     return true;
00326 }
00327 template <class T> bool Matrix44<T>::operator!=(const  Matrix44 &m) const {
00328     for(int i = 0; i < 4; ++i)
00329         for(int j = 0; j < 4; ++j)
00330             if(ElementAt(i,j) != m.ElementAt(i,j))
00331                 return true;
00332     return false;
00333 }
00334 
00335 template <class T> Matrix44<T> Matrix44<T>::operator-() const {
00336     Matrix44<T> res;
00337     for(int i = 0; i < 16; i++)
00338         res.V()[i] = -V()[i];
00339     return res;
00340 }
00341 
00342 template <class T> Matrix44<T> Matrix44<T>::operator*(const T k) const {
00343     Matrix44<T> res;
00344     for(int i = 0; i < 16; i++)
00345         res.V()[i] =V()[i] * k;
00346     return res;
00347 }
00348 
00349 template <class T> void Matrix44<T>::operator+=(const Matrix44 &m) {
00350     for(int i = 0; i < 16; i++)
00351         V()[i] += m.V()[i];
00352 }
00353 template <class T> void Matrix44<T>::operator-=(const Matrix44 &m) {
00354     for(int i = 0; i < 16; i++)
00355         V()[i] -= m.V()[i];
00356 }
00357 template <class T> void Matrix44<T>::operator*=( const Matrix44 & m ) {
00358     *this = *this *m;
00359 }
00360 
00361 template < class PointType , class T > void operator*=( std::vector<PointType> &vert, const Matrix44<T> & m ) {
00362     typename std::vector<PointType>::iterator ii;
00363     for(ii=vert.begin();ii!=vert.end();++ii)
00364         (*ii).P()=m * (*ii).P();
00365 }
00366 
00367 template <class T> void Matrix44<T>::operator*=( const T k ) {
00368     for(int i = 0; i < 16; i++)
00369         _a[i] *= k;
00370 }
00371 
00372 template <class T>
00373 void Matrix44<T>::ToEulerAngles(T &alpha, T &beta, T &gamma)
00374 {
00375     alpha = atan2(ElementAt(1,2), ElementAt(2,2));
00376     beta = asin(-ElementAt(0,2));
00377     gamma = atan2(ElementAt(0,1), ElementAt(0,0));
00378 }
00379 
00380 template <class T>
00381 void Matrix44<T>::FromEulerAngles(T alpha, T beta, T gamma)
00382 {
00383     this->SetZero();
00384 
00385     T cosalpha = cos(alpha);
00386     T cosbeta = cos(beta);
00387     T cosgamma = cos(gamma);
00388     T sinalpha = sin(alpha);
00389     T sinbeta = sin(beta);
00390     T singamma = sin(gamma);
00391 
00392     ElementAt(0,0) = cosbeta * cosgamma;
00393     ElementAt(1,0) = -cosalpha * singamma + sinalpha * sinbeta * cosgamma;
00394     ElementAt(2,0) = sinalpha * singamma + cosalpha * sinbeta * cosgamma;
00395 
00396     ElementAt(0,1) = cosbeta * singamma;
00397     ElementAt(1,1) = cosalpha * cosgamma + sinalpha * sinbeta * singamma;
00398     ElementAt(2,1) = -sinalpha * cosgamma + cosalpha * sinbeta * singamma;
00399 
00400     ElementAt(0,2) = -sinbeta;
00401     ElementAt(1,2) = sinalpha * cosbeta;
00402     ElementAt(2,2) = cosalpha * cosbeta;
00403 
00404     ElementAt(3,3) = 1;
00405 }
00406 
00407 template <class T> void Matrix44<T>::SetZero() {
00408     memset((T *)_a, 0, 16 * sizeof(T));
00409 }
00410 
00411 template <class T> void Matrix44<T>::SetIdentity() {
00412     SetDiagonal(1);
00413 }
00414 
00415 template <class T> void Matrix44<T>::SetDiagonal(const T k) {
00416     SetZero();
00417     ElementAt(0, 0) = k;
00418     ElementAt(1, 1) = k;
00419     ElementAt(2, 2) = k;
00420     ElementAt(3, 3) = 1;
00421 }
00422 
00423 template <class T> Matrix44<T> &Matrix44<T>::SetScale(const Point3<T> &t) {
00424     SetScale(t[0], t[1], t[2]);
00425     return *this;
00426 }
00427 template <class T> Matrix44<T> &Matrix44<T>::SetScale(const T sx, const T sy, const T sz) {
00428     SetZero();
00429     ElementAt(0, 0) = sx;
00430     ElementAt(1, 1) = sy;
00431     ElementAt(2, 2) = sz;
00432     ElementAt(3, 3) = 1;
00433     return *this;
00434 }
00435 
00436 template <class T> Matrix44<T> &Matrix44<T>::SetTranslate(const Point3<T> &t) {
00437     SetTranslate(t[0], t[1], t[2]);
00438     return *this;
00439 }
00440 template <class T> Matrix44<T> &Matrix44<T>::SetTranslate(const T tx, const T ty, const T tz) {
00441     SetIdentity();
00442     ElementAt(0, 3) = tx;
00443     ElementAt(1, 3) = ty;
00444     ElementAt(2, 3) = tz;
00445     return *this;
00446 }
00447 
00448 template <class T> Matrix44<T> &Matrix44<T>::SetColumn(const unsigned int ii,const Point3<T> &t) {
00449     assert( ii < 4 );
00450     ElementAt(0, ii) = t.X();
00451     ElementAt(1, ii) = t.Y();
00452     ElementAt(2, ii) = t.Z();
00453     return *this;
00454 }
00455 
00456 template <class T> Matrix44<T> &Matrix44<T>::SetColumn(const unsigned int ii,const Point4<T> &t) {
00457     assert( ii < 4 );
00458     ElementAt(0, ii) = t[0];
00459     ElementAt(1, ii) = t[1];
00460     ElementAt(2, ii) = t[2];
00461     ElementAt(3, ii) = t[3];
00462     return *this;
00463 }
00464 
00465 
00466 template <class T> Matrix44<T> &Matrix44<T>::SetRotateDeg(T AngleDeg, const Point3<T> & axis) {
00467     return SetRotateRad(math::ToRad(AngleDeg),axis);
00468 }
00469 
00470 template <class T> Matrix44<T> &Matrix44<T>::SetRotateRad(T AngleRad, const Point3<T> & axis) {
00471     //angle = angle*(T)3.14159265358979323846/180; e' in radianti!
00472     T c = math::Cos(AngleRad);
00473     T s = math::Sin(AngleRad);
00474     T q = 1-c;
00475     Point3<T> t = axis;
00476     t.Normalize();
00477     ElementAt(0,0) = t[0]*t[0]*q + c;
00478     ElementAt(0,1) = t[0]*t[1]*q - t[2]*s;
00479     ElementAt(0,2) = t[0]*t[2]*q + t[1]*s;
00480     ElementAt(0,3) = 0;
00481     ElementAt(1,0) = t[1]*t[0]*q + t[2]*s;
00482     ElementAt(1,1) = t[1]*t[1]*q + c;
00483     ElementAt(1,2) = t[1]*t[2]*q - t[0]*s;
00484     ElementAt(1,3) = 0;
00485     ElementAt(2,0) = t[2]*t[0]*q -t[1]*s;
00486     ElementAt(2,1) = t[2]*t[1]*q +t[0]*s;
00487     ElementAt(2,2) = t[2]*t[2]*q +c;
00488     ElementAt(2,3) = 0;
00489     ElementAt(3,0) = 0;
00490     ElementAt(3,1) = 0;
00491     ElementAt(3,2) = 0;
00492     ElementAt(3,3) = 1;
00493     return *this;
00494 }
00495 
00496 /*
00497 Given a non singular, non projective matrix (e.g. with the last row equal to [0,0,0,1] )
00498 This procedure decompose it in a sequence of
00499 - Scale,Shear,Rotation e Translation
00500 
00501 - ScaleV and Tranv are obiviously scaling and translation.
00502 - ShearV contains three scalars with, respectively,
00503       ShearXY, ShearXZ and ShearYZ
00504 - RotateV contains the rotations (in degree!) around the x,y,z axis
00505   The input matrix is modified leaving inside it a simple roto translation.
00506 
00507   To obtain the original matrix the above transformation have to be applied in the strict following way:
00508 
00509   OriginalMatrix =  Trn * Rtx*Rty*Rtz  * ShearYZ*ShearXZ*ShearXY * Scl
00510 
00511 Example Code:
00512 double srv() { return (double(rand()%40)-20)/2.0; } // small random value
00513 
00514   srand(time(0));
00515   Point3d ScV(10+srv(),10+srv(),10+srv()),ScVOut(-1,-1,-1);
00516   Point3d ShV(srv(),srv(),srv()),ShVOut(-1,-1,-1);
00517   Point3d RtV(10+srv(),srv(),srv()),RtVOut(-1,-1,-1);
00518   Point3d TrV(srv(),srv(),srv()),TrVOut(-1,-1,-1);
00519 
00520   Matrix44d Scl; Scl.SetScale(ScV);
00521   Matrix44d Sxy; Sxy.SetShearXY(ShV[0]);
00522   Matrix44d Sxz; Sxz.SetShearXZ(ShV[1]);
00523   Matrix44d Syz; Syz.SetShearYZ(ShV[2]);
00524   Matrix44d Rtx; Rtx.SetRotate(math::ToRad(RtV[0]),Point3d(1,0,0));
00525   Matrix44d Rty; Rty.SetRotate(math::ToRad(RtV[1]),Point3d(0,1,0));
00526   Matrix44d Rtz; Rtz.SetRotate(math::ToRad(RtV[2]),Point3d(0,0,1));
00527   Matrix44d Trn; Trn.SetTranslate(TrV);
00528 
00529   Matrix44d StartM =  Trn * Rtx*Rty*Rtz  * Syz*Sxz*Sxy *Scl;
00530   Matrix44d ResultM=StartM;
00531   Decompose(ResultM,ScVOut,ShVOut,RtVOut,TrVOut);
00532 
00533   Scl.SetScale(ScVOut);
00534   Sxy.SetShearXY(ShVOut[0]);
00535   Sxz.SetShearXZ(ShVOut[1]);
00536   Syz.SetShearYZ(ShVOut[2]);
00537   Rtx.SetRotate(math::ToRad(RtVOut[0]),Point3d(1,0,0));
00538   Rty.SetRotate(math::ToRad(RtVOut[1]),Point3d(0,1,0));
00539   Rtz.SetRotate(math::ToRad(RtVOut[2]),Point3d(0,0,1));
00540   Trn.SetTranslate(TrVOut);
00541 
00542   // Now Rebuild is equal to StartM
00543   Matrix44d RebuildM =  Trn * Rtx*Rty*Rtz  * Syz*Sxz*Sxy * Scl ;
00544 */
00545 
00546 template <class T>
00547 bool Decompose(Matrix44<T> &M, Point3<T> &ScaleV, Point3<T> &ShearV, Point3<T> &RotV,Point3<T> &TranV)
00548 {
00549     if(!(M[3][0]==0 && M[3][1]==0 && M[3][2]==0 && M[3][3]==1) ) // the matrix is projective
00550         return false;
00551     if(math::Abs(M.Determinant())<1e-10) return false; // matrix should be at least invertible...
00552 
00553     // First Step recover the traslation
00554     TranV=M.GetColumn3(3);
00555 
00556     // Second Step Recover Scale and Shearing interleaved
00557     ScaleV[0]=Norm(M.GetColumn3(0));
00558     Point3<T> R[3];
00559     R[0]=M.GetColumn3(0);
00560     R[0].Normalize();
00561 
00562     ShearV[0]=R[0]*M.GetColumn3(1); // xy shearing
00563     R[1]= M.GetColumn3(1)-R[0]*ShearV[0];
00564     assert(math::Abs(R[1]*R[0])<1e-10);
00565     ScaleV[1]=Norm(R[1]);   // y scaling
00566     R[1]=R[1]/ScaleV[1];
00567     ShearV[0]=ShearV[0]/ScaleV[1];
00568 
00569     ShearV[1]=R[0]*M.GetColumn3(2); // xz shearing
00570     R[2]= M.GetColumn3(2)-R[0]*ShearV[1];
00571     assert(math::Abs(R[2]*R[0])<1e-10);
00572 
00573     R[2] = R[2]-R[1]*(R[2]*R[1]);
00574     assert(math::Abs(R[2]*R[1])<1e-10);
00575     assert(math::Abs(R[2]*R[0])<1e-10);
00576 
00577     ScaleV[2]=Norm(R[2]);
00578     ShearV[1]=ShearV[1]/ScaleV[2];
00579     R[2]=R[2]/ScaleV[2];
00580     assert(math::Abs(R[2]*R[1])<1e-10);
00581     assert(math::Abs(R[2]*R[0])<1e-10);
00582 
00583     ShearV[2]=R[1]*M.GetColumn3(2); // yz shearing
00584     ShearV[2]=ShearV[2]/ScaleV[2];
00585     int i,j;
00586     for(i=0;i<3;++i)
00587         for(j=0;j<3;++j)
00588             M[i][j]=R[j][i];
00589 
00590     // Third and last step: Recover the rotation
00591     //now the matrix should be a pure rotation matrix so its determinant is +-1
00592     double det=M.Determinant();
00593     if(math::Abs(det)<1e-10) return false; // matrix should be at least invertible...
00594     assert(math::Abs(math::Abs(det)-1.0)<1e-10); // it should be +-1...
00595     if(det<0) {
00596         ScaleV  *= -1;
00597         M *= -1;
00598     }
00599 
00600     double alpha,beta,gamma; // rotations around the x,y and z axis
00601     beta=asin( M[0][2]);
00602     double cosbeta=cos(beta);
00603     if(math::Abs(cosbeta) > 1e-5)
00604     {
00605         alpha=asin(-M[1][2]/cosbeta);
00606         if((M[2][2]/cosbeta) < 0 ) alpha=M_PI-alpha;
00607         gamma=asin(-M[0][1]/cosbeta);
00608         if((M[0][0]/cosbeta)<0) gamma = M_PI-gamma;
00609     }
00610     else
00611     {
00612         alpha=asin(-M[1][0]);
00613         if(M[1][1]<0) alpha=M_PI-alpha;
00614         gamma=0;
00615     }
00616 
00617     RotV[0]=math::ToDeg(alpha);
00618     RotV[1]=math::ToDeg(beta);
00619     RotV[2]=math::ToDeg(gamma);
00620 
00621     return true;
00622 }
00623 
00624 
00625 
00626 
00627 template <class T> T Matrix44<T>::Determinant() const {
00628     Eigen::Matrix4d mm;
00629     this->ToEigenMatrix(mm);
00630     return mm.determinant();
00631 }
00632 
00633 
00634 template <class T> Point3<T> operator*(const Matrix44<T> &m, const Point3<T> &p) {
00635     T w;
00636     Point3<T> s;
00637     s[0] = m.ElementAt(0, 0)*p[0] + m.ElementAt(0, 1)*p[1] + m.ElementAt(0, 2)*p[2] + m.ElementAt(0, 3);
00638     s[1] = m.ElementAt(1, 0)*p[0] + m.ElementAt(1, 1)*p[1] + m.ElementAt(1, 2)*p[2] + m.ElementAt(1, 3);
00639     s[2] = m.ElementAt(2, 0)*p[0] + m.ElementAt(2, 1)*p[1] + m.ElementAt(2, 2)*p[2] + m.ElementAt(2, 3);
00640     w = m.ElementAt(3, 0)*p[0] + m.ElementAt(3, 1)*p[1] + m.ElementAt(3, 2)*p[2] + m.ElementAt(3, 3);
00641     if(w!= 0) s /= w;
00642     return s;
00643 }
00644 
00645 template <class T> Matrix44<T> &Transpose(Matrix44<T> &m) {
00646     for(int i = 1; i < 4; i++)
00647         for(int j = 0; j < i; j++) {
00648             std::swap(m.ElementAt(i, j), m.ElementAt(j, i));
00649         }
00650     return m;
00651 }
00652 
00653 template <class T> Matrix44<T> Inverse(const Matrix44<T> &m) {
00654     Eigen::Matrix4d mm,mmi;
00655     m.ToEigenMatrix(mm);
00656     mmi=mm.inverse();
00657     Matrix44<T> res;
00658     res.FromEigenMatrix(mmi);
00659     return res;
00660 }
00661 
00662 } //namespace
00663 #endif
00664 
00665 


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:32:59