00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef POLYGON_H
00025 #define POLYGON_H
00026
00027 #include <vcg/space/plane3.h>
00028 #include <vcg/space/fitting3.h>
00029 #include <vcg/space/point_matching.h>
00030 #include <vcg/math/matrix33.h>
00031
00032 namespace vcg {
00033
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 template <class CoordType>
00049 void GetNormals(std::vector<CoordType> &Pos,
00050 std::vector<CoordType> &Norms)
00051 {
00052 Norms.clear();
00053 int size=Pos.size();
00054 if (size<=2) return;
00055 for (int i=0;i<size;i++)
00056 Norms.push_back(Normal(Pos[i],Pos[(i+1)%size],Pos[(i+2)%size]).Normalize());
00057 }
00058
00059
00060 template <class CoordType>
00061 CoordType Normal(std::vector<CoordType> &Pos)
00062 {
00063 std::vector<CoordType> Norms;
00064 GetNormals(Pos,Norms);
00065 if (Norms.size()==0)
00066 return(CoordType(1,0,0));
00067
00068 CoordType NSum=CoordType(0,0,0);
00069 for (size_t i=0;i<Norms.size();i++)
00070 NSum+=Norms[i];
00071
00072 NSum.Normalize();
00073 return (NSum);
00074 }
00075
00076
00077 template <class CoordType>
00078 typename CoordType::ScalarType Area(const std::vector<CoordType> &Pos)
00079 {
00080 typedef typename CoordType::ScalarType ScalarType;
00081 CoordType bary=CoordType(0,0,0);
00082 for (int i=0;i<Pos.size();i++)
00083 bary+=Pos[i];
00084
00085 bary/=Pos.size();
00086 ScalarType Area=0;
00087 for (size_t i=0;i<Pos.size();i++)
00088 {
00089 CoordType p0=Pos[i];
00090 CoordType p1=Pos[(i+1)% Pos.size()];
00091 CoordType p2=bary;
00092 vcg::Triangle3<ScalarType> T(p0,p1,p2);
00093 Area+=(vcg::DoubleArea(T)/2);
00094 }
00095 return Area;
00096 }
00097
00098
00099 template<class PolygonType>
00100 void PolyNormals(const PolygonType &F,
00101 std::vector<typename PolygonType::CoordType> &Norms)
00102 {
00103 Norms.clear();
00104 if (F.VN()<=2) return;
00105 for (int i=0;i<F.VN();i++)
00106 Norms.push_back(Normal(F.cP0(i),F.cP1(i),F.cP2(i)).Normalize());
00107 }
00108
00109
00110 template<class PolygonType>
00111 typename PolygonType::CoordType PolyBarycenter(const PolygonType &F)
00112 {
00113 typename PolygonType::CoordType bary(0,0,0);
00114 for (int i=0;i<F.VN();i++)
00115 bary+=F.cP(i);
00116
00117 bary/=(typename PolygonType::ScalarType)F.VN();
00118 return bary;
00119 }
00120
00121
00122 template<class PolygonType>
00123 typename PolygonType::ScalarType PolyArea(const PolygonType &F)
00124 {
00125 typedef typename PolygonType::CoordType CoordType;
00126 typedef typename PolygonType::ScalarType ScalarType;
00127
00128 CoordType bary=PolyBarycenter(F);
00129 ScalarType Area=0;
00130 for (size_t i=0;i<F.VN();i++)
00131 {
00132 CoordType p0=F.cP0(i);
00133 CoordType p1=F.cP1(i);
00134 CoordType p2=bary;
00135 vcg::Triangle3<ScalarType> T(p0,p1,p2);
00136 Area+=(vcg::DoubleArea(T)/2);
00137 }
00138 return Area;
00139 }
00140
00141
00142 template<class PolygonType>
00143 typename PolygonType::CoordType PolygonNormal(const PolygonType &F)
00144 {
00145 typename PolygonType::CoordType n(0,0,0);
00146
00147 for (int i=0;i<F.VN();i++)
00148 n+=Normal(F.cP0(i),F.cP1(i),F.cP2(i)).Normalize();
00149
00150 return n.Normalize();
00151 }
00152
00153
00154 template<class PolygonType>
00155 typename PolygonType::ScalarType PolyPerimeter(const PolygonType &F)
00156 {
00157 typedef typename PolygonType::ScalarType ScalarType;
00158
00159 ScalarType SumL=0;
00160 for (int i=0;i<F.VN();i++)
00161 {
00162 ScalarType L=(F.cP0(i)-F.cP1(i)).Norm();
00163 SumL+=L;
00164 }
00165 return (SumL);
00166 }
00167
00168
00169
00170 template<class PolygonType>
00171 typename PolygonType::ScalarType PolyNormDeviation(const PolygonType &F)
00172 {
00173 typedef typename PolygonType::CoordType CoordType;
00174 typedef typename PolygonType::ScalarType ScalarType;
00175
00176 std::vector<CoordType> Norms;
00177 PolyNormals(F,Norms);
00178
00179
00180 CoordType AvgNorm(0,0,0);
00181 for (int i=0;i<Norms.size();i++)
00182 AvgNorm+=Norms[i];
00183
00184 AvgNorm.Normalize();
00185
00186
00187
00188 ScalarType Dev=0;
00189 for (int i=0;i<Norms.size();i++)
00190 Dev+=pow((Norms[i]-AvgNorm).Norm()/2.0,2);
00191
00192 Dev/=(ScalarType)Norms.size();
00193 Dev=sqrt(Dev);
00194 return Dev;
00195 }
00196
00197
00198
00199 template<class PolygonType>
00200 void PolyAngleDeviation(const PolygonType &F,
00201 typename PolygonType::ScalarType &AvgDev,
00202 typename PolygonType::ScalarType &MaxDev)
00203 {
00204 typedef typename PolygonType::CoordType CoordType;
00205 typedef typename PolygonType::ScalarType ScalarType;
00206 assert(F.VN()>2);
00207 ScalarType IdealAngle=M_PI-(2*M_PI/(ScalarType)F.VN());
00208 assert(IdealAngle>0);
00209
00210
00211 MaxDev=0;
00212 AvgDev=0;
00213
00214 for (int i=0;i<F.VN();i++)
00215 {
00216 CoordType dir0=F.cP0(i)-F.cP1(i);
00217 CoordType dir1=F.cP2(i)-F.cP1(i);
00218
00219 ScalarType VAngle=vcg::Angle(dir0,dir1);
00220 assert(VAngle>=0);
00221 ScalarType VAngleDiff=fabs(VAngle-IdealAngle);
00222
00223 if (VAngleDiff>MaxDev)MaxDev=VAngleDiff;
00224
00225 AvgDev+=VAngleDiff;
00226 }
00227 AvgDev/=(ScalarType)F.VN();
00228
00229 AvgDev/=(M_PI/2.0);
00230 MaxDev/=(M_PI/2.0);
00231
00232 if (AvgDev>1)AvgDev=1;
00233 if (MaxDev>1)MaxDev=1;
00234 }
00235
00236
00237 template<class PolygonType>
00238 vcg::Plane3<typename PolygonType::ScalarType> PolyFittingPlane(const PolygonType &F)
00239 {
00240 typedef typename PolygonType::CoordType CoordType;
00241 typedef typename PolygonType::ScalarType ScalarType;
00242 vcg::Plane3<ScalarType> BestPL;
00243 assert(F.VN()>=3);
00244 std::vector<CoordType> pointVec;
00245 for (int i=0;i<F.VN();i++)
00246 pointVec.push_back(F.cP(i));
00247
00248 vcg::FitPlaneToPointSet(pointVec,BestPL);
00249 return BestPL;
00250 }
00251
00252
00253 template<class PolygonType>
00254 typename PolygonType::ScalarType PolyFlatness(const PolygonType &F)
00255 {
00256 typedef typename PolygonType::CoordType CoordType;
00257 typedef typename PolygonType::ScalarType ScalarType;
00258
00259 if (F.VN()<=3)
00260 return 0;
00261
00262
00263 ScalarType SumL=PolyPerimeter(F)/2.0;
00264
00265
00266 vcg::Plane3<ScalarType> BestPL=PolyFittingPlane(F);
00267
00268
00269 ScalarType Flatness=0;
00270 for (int i=0;i<F.VN();i++)
00271 {
00272 CoordType pos=F.cP(i);
00273 CoordType proj=BestPL.Projection(pos);
00274 Flatness+=(pos-proj).Norm();
00275 }
00276 Flatness/=(ScalarType)F.VN();
00277 return((Flatness)/SumL);
00278 }
00279
00280
00281 template<class PolygonType>
00282 void PolyPCA(const PolygonType &F,
00283 typename PolygonType::CoordType PCA[])
00284 {
00285 typedef typename PolygonType::CoordType CoordType;
00286 typedef typename PolygonType::ScalarType ScalarType;
00287
00288
00289 Eigen::Matrix3d EigenCovMat;
00290
00291
00293 CoordType Barycenter=PolyBarycenter(F);
00294
00295
00296 EigenCovMat.setZero();
00297 Eigen::Vector3d p;
00298 for (int i=0;i<F.VN();i++)
00299 {
00300 (F.cP(i)-Barycenter).ToEigenVector(p);
00301 EigenCovMat+= p*p.transpose();
00302 }
00303
00304 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d > eig(EigenCovMat);
00305
00306 Eigen::Vector3d eval = eig.eigenvalues();
00307 Eigen::Matrix3d evec = eig.eigenvectors();
00308
00309 eval = eval.cwiseAbs();
00310 int normInd,maxInd,minInd;
00311
00315 eval.minCoeff(&normInd);
00316 eval.maxCoeff(&maxInd);
00317 minInd=(maxInd+1)%3;
00318
00319 if (minInd==normInd)minInd=(normInd+1)%3;
00320 assert((minInd!=normInd)&&(minInd!=maxInd)&&(minInd!=maxInd));
00321
00323 PCA[0][0] = evec(0,maxInd);
00324 PCA[0][1] = evec(1,maxInd);
00325 PCA[0][2] = evec(2,maxInd);
00327 PCA[1][0] = evec(0,minInd);
00328 PCA[1][1] = evec(1,minInd);
00329 PCA[1][2] = evec(2,minInd);
00331 PCA[2][0] = evec(0,normInd);
00332 PCA[2][1] = evec(1,normInd);
00333 PCA[2][2] = evec(2,normInd);
00334
00335 ScalarType LX=sqrt(eval[maxInd]);
00336 ScalarType LY=sqrt(eval[minInd]);
00337
00338
00340 PCA[0]*=LX;
00341 PCA[1]*=LY;
00342
00343 PCA[2].Normalize();
00344 }
00345
00346
00347
00348 template<class PolygonType>
00349 void PolyScaledPCA(const PolygonType &F,
00350 typename PolygonType::CoordType PCA[])
00351 {
00352 typedef typename PolygonType::CoordType CoordType;
00353 typedef typename PolygonType::ScalarType ScalarType;
00354
00355 std::vector<CoordType> SwapPos;
00356
00358
00359
00361 ScalarType Area=PolyArea(F);
00362
00363 PolyPCA(F,PCA);
00364
00365 ScalarType Scale=sqrt(Area/(PCA[0].Norm()*PCA[1].Norm()));
00366 PCA[0]*=Scale;
00367 PCA[1]*=Scale;
00368
00369 }
00370
00371
00372
00373 template<class CoordType>
00374 void getBaseTemplatePolygon(int N,
00375 std::vector<CoordType> &TemplatePos)
00376 {
00377 typedef typename CoordType::ScalarType ScalarType;
00380 ScalarType AngleInterval=2.0*M_PI/(ScalarType)N;
00381 ScalarType CurrAngle=0;
00382 TemplatePos.resize(N);
00383 for (size_t i=0;i<TemplatePos.size();i++)
00384 {
00386 TemplatePos[i].X()=cos(CurrAngle);
00387 TemplatePos[i].Y()=sin(CurrAngle);
00388 TemplatePos[i].Z()=0;
00389
00390
00391
00392
00394 CurrAngle+=AngleInterval;
00395 }
00396 }
00397
00398
00399
00400 template<class PolygonType>
00401 void GetPolyTemplatePos(const PolygonType &F,
00402 std::vector<typename PolygonType::CoordType> &TemplatePos,
00403 bool force_isotropy=false)
00404 {
00405 typedef typename PolygonType::CoordType CoordType;
00406 typedef typename PolygonType::ScalarType ScalarType;
00407 std::vector<CoordType> UniformPos,UniformTempl;
00408
00409 CoordType Barycenter=PolyBarycenter(F);
00410
00411 getBaseTemplatePolygon(F.VN(),TemplatePos);
00412
00413 CoordType PCA[3];
00414 PolyPCA(F,PCA);
00415
00416 vcg::Matrix44<ScalarType> ToPCA,ToPCAInv;
00417 ToPCA.SetIdentity();
00418
00419 CoordType dirX=PCA[0];
00420 CoordType dirY=PCA[1];
00421 CoordType dirZ=PCA[2];
00422
00423 if (force_isotropy)
00424 {
00425 dirX.Normalize();
00426 dirY.Normalize();
00427 dirZ.Normalize();
00428
00429
00430
00431
00432
00433
00434
00435 }
00436
00438 ToPCA.SetColumn(0,dirX);
00439 ToPCA.SetColumn(1,dirY);
00440 ToPCA.SetColumn(2,dirZ);
00441 ToPCAInv=ToPCA;
00442 ToPCA=vcg::Inverse(ToPCA);
00443
00445 for (int i=0;i<F.VN();i++)
00446 {
00448 CoordType Pos=F.cP(i)-Barycenter;
00450 Pos=ToPCA*Pos;
00451
00452 UniformPos.push_back(Pos);
00453 }
00454
00456 ScalarType AreaTemplate=Area(TemplatePos);
00457 ScalarType AreaUniform=Area(UniformPos);
00458
00459
00460
00461
00462
00463
00464 ScalarType Scale=sqrt(AreaTemplate/AreaUniform);
00465
00466 for (size_t i=0;i<UniformPos.size();i++)
00467 UniformPos[i]*=Scale;
00468
00470 CoordType N0=Normal(UniformPos);
00471 CoordType N1=Normal(TemplatePos);
00472 if ((N0*N1)<0)std::reverse(TemplatePos.begin(),TemplatePos.end());
00473
00475 std::vector<CoordType> FixPoints(UniformPos.begin(),UniformPos.end());
00476 std::vector<CoordType> MovPoints(TemplatePos.begin(),TemplatePos.end());
00477
00479 for (size_t i=0;i<FixPoints.size();i++)
00480 {
00481 FixPoints[i]+=CoordType(0,0,0.1);
00482 MovPoints[i]+=CoordType(0,0,0.1);
00483 }
00485 FixPoints.insert(FixPoints.end(),UniformPos.begin(),UniformPos.end());
00486 MovPoints.insert(MovPoints.end(),TemplatePos.begin(),TemplatePos.end());
00487
00489 vcg::Matrix44<ScalarType> Rigid;
00491 vcg::ComputeRigidMatchMatrix<ScalarType>(FixPoints,MovPoints,Rigid);
00492
00494 UniformTempl.resize(TemplatePos.size(),CoordType(0,0,0));
00495 for (size_t i=0;i<TemplatePos.size();i++)
00496 UniformTempl[i]=Rigid*TemplatePos[i];
00497
00499 for (size_t i=0;i<TemplatePos.size();i++)
00500 {
00501 TemplatePos[i]=UniformTempl[i];
00502 TemplatePos[i]*=1/Scale;
00503 TemplatePos[i]=ToPCAInv*TemplatePos[i];
00504 }
00505
00506 for (size_t i=0;i<TemplatePos.size();i++)
00507 TemplatePos[i]+=Barycenter;
00508
00509 }
00510
00511
00512
00513 template<class PolygonType>
00514 typename PolygonType::ScalarType PolyAspectRatio(const PolygonType &F,
00515 bool isotropic=false)
00516 {
00517 typedef typename PolygonType::CoordType CoordType;
00518 typedef typename PolygonType::ScalarType ScalarType;
00519 std::vector<CoordType> TemplatePos;
00520
00521 GetPolyTemplatePos(F,TemplatePos,isotropic);
00522
00523 ScalarType diff=0;
00524 assert((int)TemplatePos.size()==F.VN());
00525
00526 ScalarType AreaP=PolyArea(F);
00527 for (size_t i=0;i<TemplatePos.size();i++)
00528 diff+=pow((TemplatePos[i]-F.cP(i)).Norm(),2)/AreaP;
00529
00530 return(diff);
00531 }
00532
00533 }
00534 #endif // POLYGON_H