00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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;
00073 int B;
00074 int C;
00075
00076
00077 double P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
00078
00079
00080 double Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
00081
00082
00083 double T0, T1[3], T2[3], TP[3];
00084
00085 public:
00091 Inertia(MeshType &m) {Compute(m);}
00092
00093
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
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
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
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();
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
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
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
00342 CoordType X(1/6.0,1/6.0,0);
00343 vcg::Matrix33<ScalarType> A,
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
00361
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
00373 DC*=da;
00374 C+=DC;
00375 }
00376
00377 }
00378 };
00379
00380 }
00381 }
00382
00383
00384 #endif