old_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 VCG_USE_EIGEN
00025 #include "deprecated_matrix44.h"
00026 #else
00027 
00028 #ifndef __VCGLIB_MATRIX44
00029 #define __VCGLIB_MATRIX44
00030 
00031 #include "eigen.h"
00032 #include <vcg/space/point3.h>
00033 #include <vcg/space/point4.h>
00034 #include <memory.h>
00035 #include <vector>
00036 
00037 namespace vcg{
00038 template<class Scalar> class Matrix44;
00039 }
00040 
00041 namespace Eigen{
00042 template<typename Scalar>
00043 struct ei_traits<vcg::Matrix44<Scalar> > : ei_traits<Eigen::Matrix<Scalar,4,4,RowMajor> > {};
00044 template<typename XprType> struct ei_to_vcgtype<XprType,4,4,RowMajor,4,4>
00045 { typedef vcg::Matrix44<typename XprType::Scalar> type; };
00046 }
00047 
00048 namespace vcg {
00049 
00050         /*
00051         Annotations:
00052 Opengl stores matrix in  column-major order. That is, the matrix is stored as:
00053 
00054         a0  a4  a8  a12
00055         a1  a5  a9  a13
00056         a2  a6  a10 a14
00057         a3  a7  a11 a15
00058 
00059         Usually in opengl (see opengl specs) vectors are 'column' vectors
00060         so usually matrix are PRE-multiplied for a vector.
00061         So the command glTranslate generate a matrix that
00062         is ready to be premultipled for a vector:
00063 
00064         1 0 0 tx
00065         0 1 0 ty
00066         0 0 1 tz
00067         0 0 0  1
00068 
00069 Matrix44 stores matrix in row-major order i.e.
00070 
00071         a0  a1  a2  a3
00072         a4  a5  a6  a7
00073         a8  a9  a10 a11
00074         a12 a13 a14 a15
00075 
00076 So for the use of that matrix in opengl with their supposed meaning you have to transpose them before feeding to glMultMatrix.
00077 This mechanism is hidden by the templated function defined in wrap/gl/math.h;
00078 If your machine has the ARB_transpose_matrix extension it will use the appropriate;
00079 The various gl-like command SetRotate, SetTranslate assume that you are making matrix
00080 for 'column' vectors.
00081 
00082 */
00083 
00084 // Note that we have to pass Dim and HDim because it is not allowed to use a template
00085 // parameter to define a template specialization. To be more precise, in the following
00086 // specializations, it is not allowed to use Dim+1 instead of HDim.
00087 template< typename Other,
00088                   int OtherRows=Eigen::ei_traits<Other>::RowsAtCompileTime,
00089           int OtherCols=Eigen::ei_traits<Other>::ColsAtCompileTime>
00090 struct ei_matrix44_product_impl;
00091 
00096 template<typename _Scalar>
00097 class Matrix44 : public Eigen::Matrix<_Scalar,4,4,Eigen::RowMajor> // FIXME col or row major !
00098 {
00099 
00100         typedef Eigen::Matrix<_Scalar,4,4,Eigen::RowMajor> _Base;
00101 public:
00102 
00103         using _Base::coeff;
00104         using _Base::coeffRef;
00105         using _Base::ElementAt;
00106         using _Base::setZero;
00107 
00108         _EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix44,_Base);
00109         typedef _Scalar ScalarType;
00110         VCG_EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Matrix44)
00111 
00112         Matrix44() : Base() {}
00113         ~Matrix44() {}
00114         Matrix44(const Matrix44 &m) : Base(m) {}
00115         Matrix44(const Scalar * v ) : Base(Eigen::Map<Eigen::Matrix<Scalar,4,4,Eigen::RowMajor> >(v)) {}
00116         template<typename OtherDerived>
00117         Matrix44(const Eigen::MatrixBase<OtherDerived>& other) : Base(other) {}
00118 
00119         const typename Base::RowXpr operator[](int i) const { return Base::row(i); }
00120         typename Base::RowXpr operator[](int i) { return Base::row(i); }
00121 
00122         typename Base::ColXpr GetColumn4(const int& i) const { return Base::col(i); }
00123         const Eigen::Block<Base,3,1> GetColumn3(const int& i) const { return this->template block<3,1>(0,i); }
00124 
00125         typename Base::RowXpr GetRow4(const int& i) const { return Base::row(i); }
00126         Eigen::Block<Base,1,3> GetRow3(const int& i) const { return this->template block<1,3>(i,0); }
00127 
00128         template <class Matrix44Type>
00129         void ToMatrix(Matrix44Type & m) const { m = (*this).template cast<typename Matrix44Type::Scalar>(); }
00130 
00131         void ToEulerAngles(Scalar &alpha, Scalar &beta, Scalar &gamma);
00132 
00133         template <class Matrix44Type>
00134         void FromMatrix(const Matrix44Type & m) { for(int i = 0; i < 16; i++) Base::data()[i] = m.data()[i]; }
00135 
00136         void FromEulerAngles(Scalar alpha, Scalar beta, Scalar gamma);
00137         void SetDiagonal(const Scalar k);
00138         Matrix44 &SetScale(const Scalar sx, const Scalar sy, const Scalar sz);
00139         Matrix44 &SetScale(const Point3<Scalar> &t);
00140         Matrix44 &SetTranslate(const Point3<Scalar> &t);
00141         Matrix44 &SetTranslate(const Scalar sx, const Scalar sy, const Scalar sz);
00142         Matrix44 &SetShearXY(const Scalar sz);
00143         Matrix44 &SetShearXZ(const Scalar sy);
00144         Matrix44 &SetShearYZ(const Scalar sx);
00145 
00147         Matrix44 &SetRotateDeg(Scalar AngleDeg, const Point3<Scalar> & axis);
00148         Matrix44 &SetRotateRad(Scalar AngleRad, const Point3<Scalar> & axis);
00149 
00157         template<typename OtherDerived>
00158         inline const typename ei_matrix44_product_impl<OtherDerived>::ResultType
00159         operator * (const Eigen::MatrixBase<OtherDerived> &other) const
00160         { return ei_matrix44_product_impl<OtherDerived>::run(*this,other.derived()); }
00161 
00162         void print() {std::cout << *this << "\n\n";}
00163 
00164 };
00165 
00166 //return NULL matrix if not invertible
00167 template <class T> Matrix44<T> &Invert(Matrix44<T> &m);
00168 template <class T> Matrix44<T> Inverse(const Matrix44<T> &m);
00169 
00170 typedef Matrix44<short>  Matrix44s;
00171 typedef Matrix44<int>    Matrix44i;
00172 typedef Matrix44<float>  Matrix44f;
00173 typedef Matrix44<double> Matrix44d;
00174 
00175 template < class PointType , class T > void operator*=( std::vector<PointType> &vert, const Matrix44<T> & m ) {
00176         typename std::vector<PointType>::iterator ii;
00177         for(ii=vert.begin();ii!=vert.end();++ii)
00178                 (*ii).P()=m * (*ii).P();
00179 }
00180 
00181 template <class T>
00182 void Matrix44<T>::ToEulerAngles(Scalar &alpha, Scalar &beta, Scalar &gamma)
00183 {
00184         alpha = atan2(coeff(1,2), coeff(2,2));
00185         beta = asin(-coeff(0,2));
00186         gamma = atan2(coeff(0,1), coeff(1,1));
00187 }
00188 
00189 template <class T>
00190 void Matrix44<T>::FromEulerAngles(Scalar alpha, Scalar beta, Scalar gamma)
00191 {
00192         this->SetZero();
00193 
00194         T cosalpha = cos(alpha);
00195         T cosbeta = cos(beta);
00196         T cosgamma = cos(gamma);
00197         T sinalpha = sin(alpha);
00198         T sinbeta = sin(beta);
00199         T singamma = sin(gamma);
00200 
00201         ElementAt(0,0) = cosbeta * cosgamma;
00202         ElementAt(1,0) = -cosalpha * singamma + sinalpha * sinbeta * cosgamma;
00203         ElementAt(2,0) = sinalpha * singamma + cosalpha * sinbeta * cosgamma;
00204 
00205         ElementAt(0,1) = cosbeta * singamma;
00206         ElementAt(1,1) = cosalpha * cosgamma + sinalpha * sinbeta * singamma;
00207         ElementAt(2,1) = -sinalpha * cosgamma + cosalpha * sinbeta * singamma;
00208 
00209         ElementAt(0,2) = -sinbeta;
00210         ElementAt(1,2) = sinalpha * cosbeta;
00211         ElementAt(2,2) = cosalpha * cosbeta;
00212 
00213         ElementAt(3,3) = 1;
00214 }
00215 
00216 template <class T> void Matrix44<T>::SetDiagonal(const Scalar k) {
00217         setZero();
00218         ElementAt(0, 0) = k;
00219         ElementAt(1, 1) = k;
00220         ElementAt(2, 2) = k;
00221         ElementAt(3, 3) = 1;
00222 }
00223 
00224 template <class T> Matrix44<T> &Matrix44<T>::SetScale(const Point3<Scalar> &t) {
00225         SetScale(t[0], t[1], t[2]);
00226         return *this;
00227 }
00228 template <class T> Matrix44<T> &Matrix44<T>::SetScale(const Scalar sx, const Scalar sy, const Scalar sz) {
00229         setZero();
00230         ElementAt(0, 0) = sx;
00231         ElementAt(1, 1) = sy;
00232         ElementAt(2, 2) = sz;
00233         ElementAt(3, 3) = 1;
00234         return *this;
00235 }
00236 
00237 template <class T> Matrix44<T> &Matrix44<T>::SetTranslate(const Point3<Scalar> &t) {
00238         SetTranslate(t[0], t[1], t[2]);
00239         return *this;
00240 }
00241 template <class T> Matrix44<T> &Matrix44<T>::SetTranslate(const Scalar tx, const Scalar ty, const Scalar tz) {
00242         Base::setIdentity();
00243         ElementAt(0, 3) = tx;
00244         ElementAt(1, 3) = ty;
00245         ElementAt(2, 3) = tz;
00246         return *this;
00247 }
00248 
00249 template <class T> Matrix44<T> &Matrix44<T>::SetRotateDeg(Scalar AngleDeg, const Point3<Scalar> & axis) {
00250         return SetRotateRad(math::ToRad(AngleDeg),axis);
00251 }
00252 
00253 template <class T> Matrix44<T> &Matrix44<T>::SetRotateRad(Scalar AngleRad, const Point3<Scalar> & axis) {
00254         //angle = angle*(T)3.14159265358979323846/180; e' in radianti!
00255         T c = math::Cos(AngleRad);
00256         T s = math::Sin(AngleRad);
00257         T q = 1-c;
00258         Point3<T> t = axis;
00259         t.Normalize();
00260         ElementAt(0,0) = t[0]*t[0]*q + c;
00261         ElementAt(0,1) = t[0]*t[1]*q - t[2]*s;
00262         ElementAt(0,2) = t[0]*t[2]*q + t[1]*s;
00263         ElementAt(0,3) = 0;
00264         ElementAt(1,0) = t[1]*t[0]*q + t[2]*s;
00265         ElementAt(1,1) = t[1]*t[1]*q + c;
00266         ElementAt(1,2) = t[1]*t[2]*q - t[0]*s;
00267         ElementAt(1,3) = 0;
00268         ElementAt(2,0) = t[2]*t[0]*q -t[1]*s;
00269         ElementAt(2,1) = t[2]*t[1]*q +t[0]*s;
00270         ElementAt(2,2) = t[2]*t[2]*q +c;
00271         ElementAt(2,3) = 0;
00272         ElementAt(3,0) = 0;
00273         ElementAt(3,1) = 0;
00274         ElementAt(3,2) = 0;
00275         ElementAt(3,3) = 1;
00276         return *this;
00277 }
00278 
00279 /* Shear Matrixes
00280 XY
00281 1 k 0 0   x    x+ky
00282 0 1 0 0   y     y
00283 0 0 1 0   z     z
00284 0 0 0 1   1     1
00285 
00286 1 0 k 0   x    x+kz
00287 0 1 0 0   y     y
00288 0 0 1 0   z     z
00289 0 0 0 1   1     1
00290 
00291 1 1 0 0   x     x
00292 0 1 k 0   y     y+kz
00293 0 0 1 0   z     z
00294 0 0 0 1   1     1
00295 
00296 */
00297 
00298         template <class T> Matrix44<T> & Matrix44<T>::SetShearXY( const Scalar sh)      {// shear the X coordinate as the Y coordinate change
00299                 Base::setIdentity();
00300                 ElementAt(0,1) = sh;
00301                 return *this;
00302         }
00303 
00304         template <class T> Matrix44<T> & Matrix44<T>::SetShearXZ( const Scalar sh)      {// shear the X coordinate as the Z coordinate change
00305                 Base::setIdentity();
00306                 ElementAt(0,2) = sh;
00307                 return *this;
00308         }
00309 
00310         template <class T> Matrix44<T> &Matrix44<T>::SetShearYZ( const Scalar sh)       {// shear the Y coordinate as the Z coordinate change
00311                 Base::setIdentity();
00312                 ElementAt(1,2) = sh;
00313                 return *this;
00314         }
00315 
00316 
00317 /*
00318 Given a non singular, non projective matrix (e.g. with the last row equal to [0,0,0,1] )
00319 This procedure decompose it in a sequence of
00320         Scale,Shear,Rotation e Translation
00321 
00322 - ScaleV and Tranv are obiviously scaling and translation.
00323 - ShearV contains three scalars with, respectively
00324                         ShearXY, ShearXZ e ShearYZ
00325 - RotateV contains the rotations (in degree!) around the x,y,z axis
00326         The input matrix is modified leaving inside it a simple roto translation.
00327 
00328         To obtain the original matrix the above transformation have to be applied in the strict following way:
00329 
00330         OriginalMatrix =  Trn * Rtx*Rty*Rtz  * ShearYZ*ShearXZ*ShearXY * Scl
00331 
00332 Example Code:
00333 double srv() { return (double(rand()%40)-20)/2.0; } // small random value
00334 
00335         srand(time(0));
00336         Point3d ScV(10+srv(),10+srv(),10+srv()),ScVOut(-1,-1,-1);
00337         Point3d ShV(srv(),srv(),srv()),ShVOut(-1,-1,-1);
00338         Point3d RtV(10+srv(),srv(),srv()),RtVOut(-1,-1,-1);
00339         Point3d TrV(srv(),srv(),srv()),TrVOut(-1,-1,-1);
00340 
00341         Matrix44d Scl; Scl.SetScale(ScV);
00342         Matrix44d Sxy; Sxy.SetShearXY(ShV[0]);
00343         Matrix44d Sxz; Sxz.SetShearXZ(ShV[1]);
00344         Matrix44d Syz; Syz.SetShearYZ(ShV[2]);
00345         Matrix44d Rtx; Rtx.SetRotate(math::ToRad(RtV[0]),Point3d(1,0,0));
00346         Matrix44d Rty; Rty.SetRotate(math::ToRad(RtV[1]),Point3d(0,1,0));
00347         Matrix44d Rtz; Rtz.SetRotate(math::ToRad(RtV[2]),Point3d(0,0,1));
00348         Matrix44d Trn; Trn.SetTranslate(TrV);
00349 
00350         Matrix44d StartM =  Trn * Rtx*Rty*Rtz  * Syz*Sxz*Sxy *Scl;
00351         Matrix44d ResultM=StartM;
00352         Decompose(ResultM,ScVOut,ShVOut,RtVOut,TrVOut);
00353 
00354         Scl.SetScale(ScVOut);
00355         Sxy.SetShearXY(ShVOut[0]);
00356         Sxz.SetShearXZ(ShVOut[1]);
00357         Syz.SetShearYZ(ShVOut[2]);
00358         Rtx.SetRotate(math::ToRad(RtVOut[0]),Point3d(1,0,0));
00359         Rty.SetRotate(math::ToRad(RtVOut[1]),Point3d(0,1,0));
00360         Rtz.SetRotate(math::ToRad(RtVOut[2]),Point3d(0,0,1));
00361         Trn.SetTranslate(TrVOut);
00362 
00363         // Now Rebuild is equal to StartM
00364         Matrix44d RebuildM =  Trn * Rtx*Rty*Rtz  * Syz*Sxz*Sxy * Scl ;
00365 */
00366 template <class T>
00367 bool Decompose(Matrix44<T> &M, Point3<T> &ScaleV, Point3<T> &ShearV, Point3<T> &RotV,Point3<T> &TranV)
00368 {
00369         if(!(M(3,0)==0 && M(3,1)==0 && M(3,2)==0 && M(3,3)==1) ) // the matrix is projective
00370                 return false;
00371         if(math::Abs(M.Determinant())<1e-10) return false; // matrix should be at least invertible...
00372 
00373         // First Step recover the traslation
00374         TranV=M.GetColumn3(3);
00375 
00376         // Second Step Recover Scale and Shearing interleaved
00377         ScaleV[0]=Norm(M.GetColumn3(0));
00378         Point3<T> R[3];
00379         R[0]=M.GetColumn3(0);
00380         R[0].Normalize();
00381 
00382         ShearV[0]=R[0].dot(M.GetColumn3(1)); // xy shearing
00383         R[1]= M.GetColumn3(1)-R[0]*ShearV[0];
00384         assert(math::Abs(R[1].dot(R[0]))<1e-10);
00385         ScaleV[1]=Norm(R[1]);   // y scaling
00386         R[1]=R[1]/ScaleV[1];
00387         ShearV[0]=ShearV[0]/ScaleV[1];
00388 
00389         ShearV[1]=R[0].dot(M.GetColumn3(2)); // xz shearing
00390         R[2]= M.GetColumn3(2)-R[0]*ShearV[1];
00391         assert(math::Abs(R[2].dot(R[0]))<1e-10);
00392 
00393         R[2] = R[2]-R[1]*(R[2].dot(R[1]));
00394         assert(math::Abs(R[2].dot(R[1]))<1e-10);
00395         assert(math::Abs(R[2].dot(R[0]))<1e-10);
00396 
00397         ScaleV[2]=Norm(R[2]);
00398         ShearV[1]=ShearV[1]/ScaleV[2];
00399         R[2]=R[2]/ScaleV[2];
00400         assert(math::Abs(R[2].dot(R[1]))<1e-10);
00401         assert(math::Abs(R[2].dot(R[0]))<1e-10);
00402 
00403         ShearV[2]=R[1].dot(M.GetColumn3(2)); // yz shearing
00404         ShearV[2]=ShearV[2]/ScaleV[2];
00405         int i,j;
00406         for(i=0;i<3;++i)
00407                 for(j=0;j<3;++j)
00408                                 M(i,j)=R[j][i];
00409 
00410         // Third and last step: Recover the rotation
00411         //now the matrix should be a pure rotation matrix so its determinant is +-1
00412         double det=M.Determinant();
00413         if(math::Abs(det)<1e-10) return false; // matrix should be at least invertible...
00414         assert(math::Abs(math::Abs(det)-1.0)<1e-10); // it should be +-1...
00415         if(det<0) {
00416                 ScaleV  *= -1;
00417                 M *= -1;
00418         }
00419 
00420         double alpha,beta,gamma; // rotations around the x,y and z axis
00421         beta=asin( M(0,2));
00422         double cosbeta=cos(beta);
00423         if(math::Abs(cosbeta) > 1e-5)
00424                 {
00425                         alpha=asin(-M(1,2)/cosbeta);
00426                         if((M(2,2)/cosbeta) < 0 ) alpha=M_PI-alpha;
00427                         gamma=asin(-M(0,1)/cosbeta);
00428                         if((M(0,0)/cosbeta)<0) gamma = M_PI-gamma;
00429                 }
00430         else
00431                 {
00432                         alpha=asin(-M(1,0));
00433                         if(M(1,1)<0) alpha=M_PI-alpha;
00434                         gamma=0;
00435                 }
00436 
00437         RotV[0]=math::ToDeg(alpha);
00438         RotV[1]=math::ToDeg(beta);
00439         RotV[2]=math::ToDeg(gamma);
00440 
00441         return true;
00442 }
00443 
00444 /*
00445 To invert a matrix you can
00446 either invert the matrix inplace calling
00447 
00448 vcg::Invert(yourMatrix);
00449 
00450 or get the inverse matrix of a given matrix without touching it:
00451 
00452 invertedMatrix = vcg::Inverse(untouchedMatrix);
00453 
00454 */
00455 template <class T> Matrix44<T> & Invert(Matrix44<T> &m) {
00456         return m = m.lu().inverse();
00457 }
00458 
00459 template <class T> Matrix44<T> Inverse(const Matrix44<T> &m) {
00460         return m.lu().inverse();
00461 }
00462 
00463 template<typename Other,int OtherCols>
00464 struct ei_matrix44_product_impl<Other, 4,OtherCols>
00465 {
00466         typedef typename Other::Scalar Scalar;
00467         typedef typename Eigen::ProductReturnType<typename Matrix44<Scalar>::Base,Other>::Type ResultType;
00468         static ResultType run(const Matrix44<Scalar>& tr, const Other& other)
00469         { return (static_cast<const typename Matrix44<Scalar>::Base&>(tr)) * other; }
00470 };
00471 
00472 template<typename Other>
00473 struct ei_matrix44_product_impl<Other, 3,1>
00474 {
00475         typedef typename Other::Scalar Scalar;
00476         typedef Eigen::Matrix<Scalar,3,1> ResultType;
00477         static ResultType run(const Matrix44<Scalar>& tr, const Other& p)
00478         {
00479                 Scalar w;
00480                 Eigen::Matrix<Scalar,3,1> s;
00481                 s[0] = tr.ElementAt(0, 0)*p[0] + tr.ElementAt(0, 1)*p[1] + tr.ElementAt(0, 2)*p[2] + tr.ElementAt(0, 3);
00482                 s[1] = tr.ElementAt(1, 0)*p[0] + tr.ElementAt(1, 1)*p[1] + tr.ElementAt(1, 2)*p[2] + tr.ElementAt(1, 3);
00483                 s[2] = tr.ElementAt(2, 0)*p[0] + tr.ElementAt(2, 1)*p[1] + tr.ElementAt(2, 2)*p[2] + tr.ElementAt(2, 3);
00484                         w = tr.ElementAt(3, 0)*p[0] + tr.ElementAt(3, 1)*p[1] + tr.ElementAt(3, 2)*p[2] + tr.ElementAt(3, 3);
00485                 if(w!= 0) s /= w;
00486                 return s;
00487         }
00488 };
00489 
00490 } //namespace
00491 #endif
00492 
00493 #endif


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