From 94d9a3dbdd25a8338f0bfc601be0a9cbdc28e272 Mon Sep 17 00:00:00 2001 From: nicopietroni Date: Mon, 5 Jan 2015 12:57:16 +0000 Subject: [PATCH] * fixed several bugs * added several functions to compute the quality of a polygonal meshing * added the template polygon computation as in "Static Aware Grid Shells" by Pietroni et Al. --- vcg/space/polygon3.h | 512 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 497 insertions(+), 15 deletions(-) diff --git a/vcg/space/polygon3.h b/vcg/space/polygon3.h index d79d1ed7..dd267214 100644 --- a/vcg/space/polygon3.h +++ b/vcg/space/polygon3.h @@ -24,33 +24,515 @@ #ifndef POLYGON_H #define POLYGON_H +#include +#include +#include +#include + namespace vcg { -/* - */ +////return true if the +//template +//bool CheckNormalizedCoords(CoordType dir) +//{ +// typedef typename CoordType::ScalarType ScalarType; +// if(isnan(dir.X()))return false; +// if(isnan(dir.Y()))return false; +// if(isnan(dir.Z()))return false; +// ScalarType Norm=dir.Norm(); +// if(fabs(Norm-1.f)>0.01f)return false; +// return true; +//} -template -typename PolygonType::CoordType PolygonBarycenter(PolygonType &F) +//return per vertex Normals of a polygonal face stored as a vector of coords +template +void GetNormals(std::vector &Pos, + std::vector &Norms) { - typename PolygonType::CoordType bary(0,0,0); - for (int i=0;iP(); - - bary/=(typename PolygonType::ScalarType)F.VN(); - return bary; + Norms.clear(); + int size=Pos.size(); + if (size<=2) return; + for (int i=0;i +CoordType Normal(std::vector &Pos) +{ + std::vector Norms; + GetNormals(Pos,Norms); + if (Norms.size()==0) + return(CoordType(1,0,0)); + + CoordType NSum=CoordType(0,0,0); + for (size_t i=0;i +typename CoordType::ScalarType Area(const std::vector &Pos) +{ + typedef typename CoordType::ScalarType ScalarType; + CoordType bary=CoordType(0,0,0); + for (int i=0;i T(p0,p1,p2); + Area+=(vcg::DoubleArea(T)/2); + } + return Area; +} + +//return per vertex Normals of a polygonal face +template +void PolyNormals(PolygonType &F, + std::vector &Norms) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + + Norms.clear(); + if (F.VN()<=2) return; + for (int i=0;i +typename PolygonType::CoordType PolyBarycenter(PolygonType &F) +{ + typename PolygonType::CoordType bary(0,0,0); + for (int i=0;iP(); + + bary/=(typename PolygonType::ScalarType)F.VN(); + return bary; +} + +//return the area of a polygonal face +template +typename PolygonType::ScalarType PolyArea(PolygonType &F) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + + CoordType bary=PolyBarycenter(F); + ScalarType Area=0; + for (size_t i=0;i T(p0,p1,p2); + Area+=(vcg::DoubleArea(T)/2); + } + return Area; +} + +//return the normal of a polygonal face template typename PolygonType::CoordType PolygonNormal(PolygonType &F) { - typename PolygonType::CoordType n(0,0,0); + typename PolygonType::CoordType n(0,0,0); - for (int i=0;i +typename PolygonType::ScalarType PolyPerimeter(PolygonType &F) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; - } + ScalarType SumL=0; + for (int i=0;i +typename PolygonType::ScalarType PolyNormDeviation(PolygonType &F) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + + std::vector Norms; + PolyNormals(F,Norms); + + //calculate the Avg Normal + CoordType AvgNorm(0,0,0); + for (int i=0;i +void PolyAngleDeviation(PolygonType &F, + typename PolygonType::ScalarType &AvgDev, + typename PolygonType::ScalarType &MaxDev) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + assert(F.VN()>2); + ScalarType IdealAngle=M_PI-(2*M_PI/(ScalarType)F.VN()); + assert(IdealAngle>0); + + //then compute the angle deviation + MaxDev=0; + AvgDev=0; + + for (int i=0;i=0); + ScalarType VAngleDiff=fabs(VAngle-IdealAngle); + + if (VAngleDiff>MaxDev)MaxDev=VAngleDiff; + + AvgDev+=VAngleDiff; + } + AvgDev/=(ScalarType)F.VN(); + + AvgDev/=(M_PI/2.0); + MaxDev/=(M_PI/2.0); + + if (AvgDev>1)AvgDev=1; + if (MaxDev>1)MaxDev=1; +} + +//return the fitting plane of a polygonal face +template +vcg::Plane3 PolyFittingPlane(PolygonType &F) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + vcg::Plane3 BestPL; + assert(F.VN()>=3); + std::vector pointVec; + for (int i=0;i +typename PolygonType::ScalarType PolyFlatness(PolygonType &F) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + + if (F.VN()<=3) + return 0; + + //average lenght + ScalarType SumL=PolyPerimeter(F)/2.0; + + //diagonal distance + vcg::Plane3 BestPL=PolyFittingPlane(F); + + //then project points on the plane + ScalarType Flatness=0; + for (int i=0;i +void PolyPCA(PolygonType &F, + typename PolygonType::CoordType PCA[]) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + + //compute the covariance matrix + Eigen::Matrix3d EigenCovMat; + //ComputeCovarianceMatrix(EigenCovMat); + //compute covariance matrix + ///compute the barycenter + CoordType Barycenter=PolyBarycenter(F); + + // second cycle: compute the covariance matrix + EigenCovMat.setZero(); + Eigen::Vector3d p; + for (int i=0;iP()-Barycenter).ToEigenVector(p); + EigenCovMat+= p*p.transpose(); // outer product + } + + Eigen::SelfAdjointEigenSolver eig(EigenCovMat); + + Eigen::Vector3d eval = eig.eigenvalues(); + Eigen::Matrix3d evec = eig.eigenvectors(); + + eval = eval.cwiseAbs(); + int normInd,maxInd,minInd; + + ///get min and max coff .. + ///the minumum is the Normal + ///the other two the anisotropy directions + eval.minCoeff(&normInd); + eval.maxCoeff(&maxInd); + minInd=(maxInd+1)%3; + + if (minInd==normInd)minInd=(normInd+1)%3; + assert((minInd!=normInd)&&(minInd!=maxInd)&&(minInd!=maxInd)); + + ///maximum direction of PCA + PCA[0][0] = evec(0,maxInd); + PCA[0][1] = evec(1,maxInd); + PCA[0][2] = evec(2,maxInd); + ///minimum direction of PCA + PCA[1][0] = evec(0,minInd); + PCA[1][1] = evec(1,minInd); + PCA[1][2] = evec(2,minInd); + ///Normal direction + PCA[2][0] = evec(0,normInd); + PCA[2][1] = evec(1,normInd); + PCA[2][2] = evec(2,normInd); + + ScalarType LX=sqrt(eval[maxInd]); + ScalarType LY=sqrt(eval[minInd]); + //ScalarType LZ=sqrt(eval[normInd]); + + ///scale the directions + PCA[0]*=LX; + PCA[1]*=LY; + //PCA[2]*=LZ;//.Normalize(); + PCA[2].Normalize(); +} + +//evaluate the PCA directions of a polygonal face +//scaled by the area of the face +template +void PolyScaledPCA(PolygonType &F, + typename PolygonType::CoordType PCA[]) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + + std::vector SwapPos; + + ///compute the barycenter + //CoordType Barycenter=PolyBarycenter(F); + + ///compute the Area + ScalarType Area=PolyArea(F); + + PolyPCA(F,PCA); + + ScalarType Scale=sqrt(Area/(PCA[0].Norm()*PCA[1].Norm())); + PCA[0]*=Scale; + PCA[1]*=Scale; + +} + +//return the base template polygon as +//described by "Static Aware Grid Shells" by Pietroni et Al. +template +void getBaseTemplatePolygon(int N, + std::vector &TemplatePos) +{ + typedef typename CoordType::ScalarType ScalarType; + ///first find positions in the + ///reference frame of the passed matrix + ScalarType AngleInterval=2.0*M_PI/(ScalarType)N; + ScalarType CurrAngle=0; + TemplatePos.resize(N); + for (size_t i=0;i +void GetPolyTemplatePos(PolygonType &F, + std::vector &TemplatePos) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + std::vector UniformPos,UniformTempl; + + CoordType Barycenter=PolyBarycenter(F); + + getBaseTemplatePolygon(F.VN(),TemplatePos); + + CoordType PCA[3]; + PolyPCA(F,PCA); + + vcg::Matrix44 ToPCA,ToPCAInv; + ToPCA.SetIdentity(); + + CoordType dirX=PCA[0]; + CoordType dirY=PCA[1]; + CoordType dirZ=PCA[2]; + + ///set the Rotation matrix + ToPCA.SetColumn(0,dirX); + ToPCA.SetColumn(1,dirY); + ToPCA.SetColumn(2,dirZ); + ToPCAInv=ToPCA; + ToPCA=vcg::Inverse(ToPCA); + + ///then transform the polygon to PCA space + for (int i=0;iP()-Barycenter; + ///rotate + Pos=ToPCA*Pos; + //retranslate + UniformPos.push_back(Pos); + } + + ///calculate the Area + ScalarType AreaTemplate=Area(TemplatePos); + ScalarType AreaUniform=Area(UniformPos); + + ScalarType Scale=sqrt(AreaTemplate/AreaUniform); + + for (size_t i=0;i FixPoints(UniformPos.begin(),UniformPos.end()); + std::vector MovPoints(TemplatePos.begin(),TemplatePos.end()); + + ///add displacement along Z + for (size_t i=0;i Rigid; + ///compute rigid match + vcg::ComputeRigidMatchMatrix(FixPoints,MovPoints,Rigid); + + ///then apply transformation + UniformTempl.resize(TemplatePos.size(),CoordType(0,0,0)); + for (size_t i=0;i +typename PolygonType::ScalarType PolyAspectRatio(PolygonType &F) +{ + typedef typename PolygonType::FaceType FaceType; + typedef typename PolygonType::CoordType CoordType; + typedef typename PolygonType::ScalarType ScalarType; + std::vector TemplatePos; + + GetPolyTemplatePos(F,TemplatePos); + + ScalarType diff=0; + assert((int)TemplatePos.size()==F.VN()); + + ScalarType AreaP=PolyArea(F); + for (size_t i=0;i