inertia.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) 2005                                                \/)\/    *
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 #ifndef _VCG_INERTIA_
00024 #define _VCG_INERTIA_
00025 
00026 
00027 #include <eigenlib/Eigen/Core>
00028 #include <eigenlib/Eigen/Eigenvalues>
00029 #include <vcg/complex/algorithms/update/normal.h>
00030 
00031 namespace vcg
00032 {
00033   namespace tri
00034   {
00053 template <class MeshType>
00054 class Inertia
00055 {
00056         typedef typename MeshType::VertexType     VertexType;
00057         typedef typename MeshType::VertexPointer  VertexPointer;
00058         typedef typename MeshType::VertexIterator VertexIterator;
00059         typedef typename MeshType::ScalarType                   ScalarType;
00060         typedef typename MeshType::FaceType       FaceType;
00061         typedef typename MeshType::FacePointer    FacePointer;
00062         typedef typename MeshType::FaceIterator   FaceIterator;
00063         typedef typename MeshType::ConstFaceIterator   ConstFaceIterator;
00064         typedef typename MeshType::FaceContainer  FaceContainer;
00065         typedef typename MeshType::CoordType  CoordType;
00066 
00067 private :
00068         enum {X=0,Y=1,Z=2};
00069         inline ScalarType SQR(ScalarType &x) const { return x*x;}
00070         inline ScalarType CUBE(ScalarType &x) const { return x*x*x;}
00071 
00072  int A;   /* alpha */
00073  int B;   /* beta */
00074  int C;   /* gamma */
00075 
00076 /* projection integrals */
00077  double P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
00078 
00079 /* face integrals */
00080  double Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
00081 
00082 /* volume integrals */
00083  double T0, T1[3], T2[3], TP[3];
00084 
00085 public:
00091  Inertia(MeshType &m) {Compute(m);}
00092 
00093 /* compute various integrations over projection of face */
00094  void compProjectionIntegrals(FaceType &f)
00095 {
00096   double a0, a1, da;
00097   double b0, b1, db;
00098   double a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
00099   double a1_2, a1_3, b1_2, b1_3;
00100   double C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
00101   double Cab, Kab, Caab, Kaab, Cabb, Kabb;
00102   int i;
00103 
00104   P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0;
00105 
00106   for (i = 0; i < 3; i++) {
00107     a0 = f.V(i)->P()[A];
00108     b0 = f.V(i)->P()[B];
00109     a1 = f.V1(i)->P()[A];
00110     b1 = f.V1(i)->P()[B];
00111     da = a1 - a0;
00112     db = b1 - b0;
00113     a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0;
00114     b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0;
00115     a1_2 = a1 * a1; a1_3 = a1_2 * a1;
00116     b1_2 = b1 * b1; b1_3 = b1_2 * b1;
00117 
00118     C1 = a1 + a0;
00119     Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4;
00120     Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4;
00121     Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2;
00122     Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3;
00123     Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
00124     Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
00125 
00126     P1 += db*C1;
00127     Pa += db*Ca;
00128     Paa += db*Caa;
00129     Paaa += db*Caaa;
00130     Pb += da*Cb;
00131     Pbb += da*Cbb;
00132     Pbbb += da*Cbbb;
00133     Pab += db*(b1*Cab + b0*Kab);
00134     Paab += db*(b1*Caab + b0*Kaab);
00135     Pabb += da*(a1*Cabb + a0*Kabb);
00136   }
00137 
00138   P1 /= 2.0;
00139   Pa /= 6.0;
00140   Paa /= 12.0;
00141   Paaa /= 20.0;
00142   Pb /= -6.0;
00143   Pbb /= -12.0;
00144   Pbbb /= -20.0;
00145   Pab /= 24.0;
00146   Paab /= 60.0;
00147   Pabb /= -60.0;
00148 }
00149 
00150 
00151 void CompFaceIntegrals(FaceType &f)
00152 {
00153         Point3<ScalarType>  n;
00154         ScalarType w;
00155   double k1, k2, k3, k4;
00156 
00157   compProjectionIntegrals(f);
00158 
00159   n = f.N();
00160   w = -f.V(0)->P()*n;
00161   k1 = 1 / n[C]; k2 = k1 * k1; k3 = k2 * k1; k4 = k3 * k1;
00162 
00163   Fa = k1 * Pa;
00164   Fb = k1 * Pb;
00165   Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1);
00166 
00167   Faa = k1 * Paa;
00168   Fbb = k1 * Pbb;
00169   Fcc = k3 * (SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb
00170      + w*(2*(n[A]*Pa + n[B]*Pb) + w*P1));
00171 
00172   Faaa = k1 * Paaa;
00173   Fbbb = k1 * Pbbb;
00174   Fccc = -k4 * (CUBE(n[A])*Paaa + 3*SQR(n[A])*n[B]*Paab
00175        + 3*n[A]*SQR(n[B])*Pabb + CUBE(n[B])*Pbbb
00176        + 3*w*(SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb)
00177        + w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1));
00178 
00179   Faab = k1 * Paab;
00180   Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb);
00181   Fcca = k3 * (SQR(n[A])*Paaa + 2*n[A]*n[B]*Paab + SQR(n[B])*Pabb
00182      + w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa));
00183 }
00184 
00185 
00191 void Compute(MeshType &m)
00192 {
00193   tri::UpdateNormal<MeshType>::PerFaceNormalized(m);
00194   double nx, ny, nz;
00195 
00196   T0 = T1[X] = T1[Y] = T1[Z]
00197      = T2[X] = T2[Y] = T2[Z]
00198      = TP[X] = TP[Y] = TP[Z] = 0;
00199     FaceIterator fi;
00200     for (fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD() && vcg::DoubleArea(*fi)>std::numeric_limits<float>::min()) {
00201         FaceType &f=(*fi);
00202 
00203     nx = fabs(f.N()[0]);
00204     ny = fabs(f.N()[1]);
00205     nz = fabs(f.N()[2]);
00206     if (nx > ny && nx > nz) C = X;
00207     else C = (ny > nz) ? Y : Z;
00208     A = (C + 1) % 3;
00209     B = (A + 1) % 3;
00210 
00211     CompFaceIntegrals(f);
00212 
00213     T0 += f.N()[X] * ((A == X) ? Fa : ((B == X) ? Fb : Fc));
00214 
00215     T1[A] += f.N()[A] * Faa;
00216     T1[B] += f.N()[B] * Fbb;
00217     T1[C] += f.N()[C] * Fcc;
00218     T2[A] += f.N()[A] * Faaa;
00219     T2[B] += f.N()[B] * Fbbb;
00220     T2[C] += f.N()[C] * Fccc;
00221     TP[A] += f.N()[A] * Faab;
00222     TP[B] += f.N()[B] * Fbbc;
00223     TP[C] += f.N()[C] * Fcca;
00224   }
00225 
00226   T1[X] /= 2; T1[Y] /= 2; T1[Z] /= 2;
00227   T2[X] /= 3; T2[Y] /= 3; T2[Z] /= 3;
00228   TP[X] /= 2; TP[Y] /= 2; TP[Z] /= 2;
00229 }
00230 
00235 ScalarType Mass()
00236 {
00237     return static_cast<ScalarType>(T0);
00238 }
00239 
00244 Point3<ScalarType>  CenterOfMass()
00245 {
00246     Point3<ScalarType>  r;
00247   r[X] = T1[X] / T0;
00248   r[Y] = T1[Y] / T0;
00249   r[Z] = T1[Z] / T0;
00250     return r;
00251 }
00252 void InertiaTensor(Matrix33<ScalarType> &J ){
00253     Point3<ScalarType>  r;
00254   r[X] = T1[X] / T0;
00255   r[Y] = T1[Y] / T0;
00256   r[Z] = T1[Z] / T0;
00257   /* compute inertia tensor */
00258   J[X][X] = (T2[Y] + T2[Z]);
00259   J[Y][Y] = (T2[Z] + T2[X]);
00260   J[Z][Z] = (T2[X] + T2[Y]);
00261   J[X][Y] = J[Y][X] = - TP[X];
00262   J[Y][Z] = J[Z][Y] = - TP[Y];
00263   J[Z][X] = J[X][Z] = - TP[Z];
00264 
00265   J[X][X] -= T0 * (r[Y]*r[Y] + r[Z]*r[Z]);
00266   J[Y][Y] -= T0 * (r[Z]*r[Z] + r[X]*r[X]);
00267   J[Z][Z] -= T0 * (r[X]*r[X] + r[Y]*r[Y]);
00268   J[X][Y] = J[Y][X] += T0 * r[X] * r[Y];
00269   J[Y][Z] = J[Z][Y] += T0 * r[Y] * r[Z];
00270   J[Z][X] = J[X][Z] += T0 * r[Z] * r[X];
00271 }
00272 
00273 //void InertiaTensor(Matrix44<ScalarType> &J )
00274 void InertiaTensor(Eigen::Matrix3d &J )
00275 {
00276   J=Eigen::Matrix3d::Identity();
00277   Point3d  r;
00278   r[X] = T1[X] / T0;
00279   r[Y] = T1[Y] / T0;
00280   r[Z] = T1[Z] / T0;
00281   /* compute inertia tensor */
00282   J(X,X) = (T2[Y] + T2[Z]);
00283   J(Y,Y) = (T2[Z] + T2[X]);
00284   J(Z,Z) = (T2[X] + T2[Y]);
00285   J(X,Y) = J(Y,X) = - TP[X];
00286   J(Y,Z) = J(Z,Y) = - TP[Y];
00287   J(Z,X) = J(X,Z) = - TP[Z];
00288 
00289   J(X,X) -= T0 * (r[Y]*r[Y] + r[Z]*r[Z]);
00290   J(Y,Y) -= T0 * (r[Z]*r[Z] + r[X]*r[X]);
00291   J(Z,Z) -= T0 * (r[X]*r[X] + r[Y]*r[Y]);
00292   J(X,Y) = J(Y,X) += T0 * r[X] * r[Y];
00293   J(Y,Z) = J(Z,Y) += T0 * r[Y] * r[Z];
00294   J(Z,X) = J(X,Z) += T0 * r[Z] * r[X];
00295 }
00296 
00297 
00298 
00303 void InertiaTensorEigen(Matrix33<ScalarType> &EV, Point3<ScalarType> &ev )
00304 {
00305         Eigen::Matrix3d it;
00306         InertiaTensor(it);
00307         Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig(it);
00308         Eigen::Vector3d c_val = eig.eigenvalues();
00309         Eigen::Matrix3d c_vec = eig.eigenvectors(); // eigenvector are stored as columns.
00310         EV.FromEigenMatrix(c_vec);
00311         EV.transposeInPlace();
00312         ev.FromEigenVector(c_val);
00313 }
00314 
00318 static void Covariance(const MeshType & m, vcg::Point3<ScalarType> & bary, vcg::Matrix33<ScalarType> &C)
00319 {
00320         // find the barycenter
00321         ConstFaceIterator fi;
00322         ScalarType area = 0.0;
00323         bary.SetZero();
00324         for(fi = m.face.begin(); fi != m.face.end(); ++fi)
00325                 if(!(*fi).IsD())
00326                         {
00327                                 bary += vcg::Barycenter( *fi )* vcg::DoubleArea(*fi);
00328                                 area+=vcg::DoubleArea(*fi);
00329                         }
00330         bary/=area;
00331 
00332 
00333         C.SetZero();
00334         // C as covariance of triangle (0,0,0)(1,0,0)(0,1,0)
00335         vcg::Matrix33<ScalarType> C0;
00336         C0.SetZero();
00337         C0[0][0] = C0[1][1] = 2.0;
00338         C0[0][1] = C0[1][0] = 1.0;
00339         C0*=1/24.0;
00340 
00341         // integral of (x,y,0) in the same triangle
00342         CoordType X(1/6.0,1/6.0,0);
00343         vcg::Matrix33<ScalarType> A, // matrix that bring the vertices to (v1-v0,v2-v0,n)
00344                                                                                                         DC;
00345         for(fi = m.face.begin(); fi != m.face.end(); ++fi)
00346                 if(!(*fi).IsD())
00347                 {
00348                         const CoordType &P0 = (*fi).cP(0);
00349                         const CoordType &P1 = (*fi).cP(1);
00350                         const CoordType &P2 = (*fi).cP(2);
00351                         CoordType  n = ((P1-P0)^(P2-P0));
00352                         const float da = n.Norm();
00353                         n/=da*da;
00354 
00355                         A.SetColumn(0, P1-P0);
00356                         A.SetColumn(1, P2-P0);
00357                         A.SetColumn(2, n);
00358                         CoordType delta = P0 - bary;
00359 
00360                         /* DC is calculated as integral of (A*x+delta) * (A*x+delta)^T over the triangle,
00361                                  where delta = v0-bary
00362                         */
00363 
00364                         DC.SetZero();
00365                         DC+= A*C0*A.transpose();
00366                         vcg::Matrix33<ScalarType> tmp;
00367                         tmp.OuterProduct(A*X,delta);
00368                         DC += tmp + tmp.transpose();
00369                         DC+= tmp;
00370                         tmp.OuterProduct(delta,delta);
00371                         DC+=tmp*0.5;
00372 //              DC*=fabs(A.Determinant());      // the determinant of A is the jacobian of the change of variables A*x+delta
00373                         DC*=da;                                                                                 // the determinant of A is also the double area of *fi
00374                         C+=DC;
00375         }
00376 
00377 }
00378 }; // end class Inertia
00379 
00380   } // end namespace tri
00381 } // end namespace vcg
00382 
00383 
00384 #endif


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