polygon3.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 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 //template <class CoordType>
00036 //bool CheckNormalizedCoords(CoordType dir)
00037 //{
00038 //    typedef typename CoordType::ScalarType ScalarType;
00039 //    if(isnan(dir.X()))return false;
00040 //    if(isnan(dir.Y()))return false;
00041 //    if(isnan(dir.Z()))return false;
00042 //    ScalarType Norm=dir.Norm();
00043 //    if(fabs(Norm-1.f)>0.01f)return false;
00044 //    return true;
00045 //}
00046 
00047 //return per vertex Normals of a polygonal face stored as a vector of coords
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 //return the normal of a polygonal face stored as a vector of coords
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 //return the area of a polygonal face stored as a vector of coords
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 //return per vertex Normals of a polygonal face
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 //return the barycenter of a polygonal face
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 //return the area of a polygonal face
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 //return the normal of a polygonal face
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 //return the perimeter of a polygonal face
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 //return a Scalar value that encode the variance of the normals
00169 //wrt the average one (1 means hight variance, 0 no variance)
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     //calculate the Avg Normal
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     //if (!CheckNormalizedCoords(AvgNorm))return 1;
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 //return a Scalar value that encode the distance wrt ideal angle for each
00198 //wrt the average one (1 correspond to hight variance, 0 no variance)
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     //then compute the angle deviation
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 //return the fitting plane of a polygonal face
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 //return the flatness of a polygonal face as avg distance to the best fitting plane divided by half perimeter
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     //average lenght
00263     ScalarType SumL=PolyPerimeter(F)/2.0;
00264 
00265     //diagonal distance
00266     vcg::Plane3<ScalarType> BestPL=PolyFittingPlane(F);
00267 
00268     //then project points on the plane
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 //evaluate the PCA directions of a polygonal face
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     //compute the covariance matrix
00289     Eigen::Matrix3d EigenCovMat;
00290     //ComputeCovarianceMatrix(EigenCovMat);
00291     //compute covariance matrix
00293     CoordType Barycenter=PolyBarycenter(F);
00294 
00295     // second cycle: compute the covariance matrix
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(); // outer product
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     //ScalarType LZ=sqrt(eval[normInd]);
00338 
00340     PCA[0]*=LX;
00341     PCA[1]*=LY;
00342     //PCA[2]*=LZ;//.Normalize();
00343     PCA[2].Normalize();
00344 }
00345 
00346 //evaluate the PCA directions of a polygonal face
00347 //scaled by the area of the face
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     //CoordType Barycenter=PolyBarycenter(F);
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 //return the base template polygon as
00372 //described by "Static Aware Grid Shells" by Pietroni et Al.
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         //            TemplatePos[i].Normalize();
00390         //            TemplatePos[i].X()*=Anisotropy;
00391         //            TemplatePos[i].Y()*=(1-Anisotropy);
00392 
00394         CurrAngle+=AngleInterval;
00395     }
00396 }
00397 
00398 //return the rigidly aligned template polygon as
00399 //described by "Static Aware Grid Shells" by Pietroni et Al.
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 //        CoordType dirXN=dirX;dirXN.Normalize();
00429 //        CoordType dirYN=dirY;dirYN.Normalize();
00430 //        CoordType dirZN=dirZ;dirZN.Normalize();
00431 
00432 //        dirX=dirX*0.8+dirXN*0.2;
00433 //        dirY=dirY*0.8+dirYN*0.2;
00434 //        dirZ=dirZ*0.8+dirZN*0.2;
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         //retranslate
00452         UniformPos.push_back(Pos);
00453     }
00454 
00456     ScalarType AreaTemplate=Area(TemplatePos);
00457     ScalarType AreaUniform=Area(UniformPos);
00458 
00459 //    if (TargetArea>0)
00460 //    {
00461 //        AreaUniform*=(AreaUniform/TargetArea);
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 //compute the aspect ratio using the rigidly aligned template polygon as
00512 //described by "Static Aware Grid Shells" by Pietroni et Al.
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


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