27 #ifndef VCGLIB_UPDATE_CURVATURE_FITTING 
   28 #define VCGLIB_UPDATE_CURVATURE_FITTING 
   30 #include <vcg/space/index/grid_static_ptr.h> 
   31 #include <vcg/simplex/face/topology.h> 
   32 #include <vcg/simplex/face/pos.h> 
   33 #include <vcg/simplex/face/jumping_pos.h> 
   34 #include <vcg/container/simple_temporary_data.h> 
   35 #include <vcg/complex/algorithms/update/normal.h> 
   36 #include <vcg/complex/algorithms/point_sampling.h> 
   37 #include <vcg/complex/algorithms/intersection.h> 
   38 #include <vcg/complex/algorithms/inertia.h> 
   39 #include <vcg/complex/algorithms/nring.h> 
   45 #include <Eigen/Eigenvalues> 
   60 template <
class MeshType>
 
   65     typedef typename MeshType::FaceType FaceType;
 
   66     typedef typename MeshType::FacePointer FacePointer;
 
   67     typedef typename MeshType::FaceIterator FaceIterator;
 
   68     typedef typename MeshType::VertexIterator VertexIterator;
 
   69     typedef typename MeshType::VertContainer VertContainer;
 
   70     typedef typename MeshType::VertexType VertexType;
 
   71     typedef typename MeshType::VertexPointer VertexPointer;
 
   72         typedef typename MeshType::VertexPointer VertexTypeP;
 
   73     typedef vcg::face::VFIterator<FaceType> VFIteratorType;
 
   74     typedef typename MeshType::CoordType CoordType;
 
   75     typedef typename CoordType::ScalarType ScalarType;
 
   81     Quadric(
double av, 
double bv, 
double cv, 
double dv, 
double ev)
 
   90     double& a() { 
return data[0];}
 
   91     double& b() { 
return data[1];}
 
   92     double& c() { 
return data[2];}
 
   93     double& d() { 
return data[3];}
 
   94     double& e() { 
return data[4];}
 
   98     double evaluate(
double u, 
double v)
 
  100         return a()*u*u + b()*u*v + c()*v*v + d()*u + e()*v;
 
  103     double du(
double u, 
double v)
 
  105         return 2.0*a()*u + b()*v + d();
 
  108     double dv(
double u, 
double v)
 
  110         return 2.0*c()*v + b()*u + e();
 
  113     double duv(
double , 
double )
 
  118     double duu(
double , 
double )
 
  123     double dvv(
double , 
double )
 
  128     static Quadric fit(std::vector<CoordType> VV)
 
  130         assert(VV.size() >= 5);
 
  131         Eigen::MatrixXf A(VV.size(),5);
 
  132         Eigen::MatrixXf b(VV.size(),1);
 
  133         Eigen::MatrixXf sol(VV.size(),1);
 
  135         for(
unsigned int c=0; c < VV.size(); ++c)
 
  137             double u = VV[c].X();
 
  138             double v = VV[c].Y();
 
  139             double n = VV[c].Z();
 
  150         sol = ((A.transpose()*A).inverse()*A.transpose())*b;
 
  151         return Quadric(sol(0,0),sol(1,0),sol(2,0),sol(3,0),sol(4,0));
 
  155     static CoordType project(VertexType* v, VertexType* vp)
 
  157       return vp->P() - (v->N() * ((vp->P() - v->P()) * v->N()));
 
  161     static std::vector<CoordType> computeReferenceFrames(VertexTypeP vi)
 
  163       vcg::face::VFIterator<FaceType> vfi(vi);
 
  165       int i = (vfi.I()+1)%3;
 
  166       VertexTypeP vp = vfi.F()->V(i);
 
  168       CoordType x = (project(&*vi,vp) - vi->P()).Normalize();
 
  171       std::vector<CoordType> res(3);
 
  174       res[1] = (vi->N() ^ res[0]).Normalize();
 
  175       res[2] = (vi->N())/(vi->N()).Norm();
 
  180     static std::set<CoordType> getSecondRing(VertexTypeP v)
 
  182         std::set<VertexTypeP> ris;
 
  183         std::set<CoordType> coords;
 
  185         vcg::face::VFIterator<FaceType> vvi(v);
 
  186         for(;!vvi.End();++vvi)
 
  188             vcg::face::VFIterator<FaceType> vvi2(vvi.F()->V((vvi.I()+1)%3));
 
  189             for(;!vvi2.End();++vvi2)
 
  191                 ris.insert(vvi2.F()->V((vvi2.I()+1)%3));
 
  194                 typename std::set<VertexTypeP>::iterator it;
 
  195         for(it = ris.begin(); it != ris.end(); ++it)
 
  196             coords.insert((*it)->P());
 
  201     static Quadric fitQuadric(VertexTypeP v, std::vector<CoordType>& ref)
 
  203         std::set<CoordType> ring = getSecondRing(v);
 
  205             return Quadric(1,1,1,1,1);
 
  206         std::vector<CoordType> points;
 
  208         typename std::set<CoordType>::iterator b = ring.begin();
 
  209         typename std::set<CoordType>::iterator e = ring.end();
 
  214             CoordType vTang = *b - v->P();
 
  216             double x = vTang * ref[0];
 
  217             double y = vTang * ref[1];
 
  218             double z = vTang * ref[2];
 
  219             points.push_back(CoordType(x,y,z));
 
  222         return Quadric::fit(points);
 
  226     static void computeCurvature(MeshType & m)
 
  229       tri::RequireCompactness(m);
 
  230       tri::RequireVFAdjacency(m);
 
  239         for(vi = m.vert.begin(); vi!=m.vert.end(); ++vi )
 
  241             std::vector<CoordType> ref = computeReferenceFrames(&*vi);
 
  243             Quadric q = fitQuadric(&*vi,ref);
 
  250             double E = 1.0 + d*d;
 
  252             double G = 1.0 + e*e;
 
  254             CoordType n = CoordType(-d,-e,1.0).Normalize();
 
  256             vi->N() = ref[0] * n[0] + ref[1] * n[1] + ref[2] * n[2];
 
  258             double L = 2.0 * a * n.Z();
 
  259             double M = b * n.Z();
 
  260             double N = 2 * c * n.Z();
 
  264             m << L*G - M*F, M*E-L*F, M*E-L*F, N*E-M*F;
 
  266             Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eig(m);
 
  268             Eigen::Vector2d c_val = eig.eigenvalues();
 
  269             Eigen::Matrix2d c_vec = eig.eigenvectors();
 
  288             CoordType v1global = ref[0] * v1[0] + ref[1] * v1[1] + ref[2] * v1[2];
 
  289             CoordType v2global = ref[0] * v2[0] + ref[1] * v2[1] + ref[2] * v2[2];
 
  291             v1global.Normalize();
 
  292             v2global.Normalize();
 
  294             if (c_val[0] > c_val[1])
 
  296                 (*vi).PD1().Import(v1global);
 
  297                 (*vi).PD2().Import(v2global);
 
  298                 (*vi).K1()  = c_val[0];
 
  299                 (*vi).K2()  = c_val[1];
 
  303                 (*vi).PD1().Import(v2global);
 
  304                 (*vi).PD2().Import(v1global);
 
  305                 (*vi).K1()  = c_val[1];
 
  306                 (*vi).K2()  = c_val[0];
 
  320             a() = b() = c() = d() = e() = 1.0;
 
  323         QuadricLocal (
double av, 
double bv, 
double cv, 
double dv, 
double ev)
 
  332         double& a() { 
return data[0];}
 
  333         double& b() { 
return data[1];}
 
  334         double& c() { 
return data[2];}
 
  335         double& d() { 
return data[3];}
 
  336         double& e() { 
return data[4];}
 
  340         double evaluate(
double u, 
double v)
 
  342             return a()*u*u + b()*u*v + c()*v*v + d()*u + e()*v;
 
  345         double du(
double u, 
double v)
 
  347             return 2.0*a()*u + b()*v + d();
 
  350         double dv(
double u, 
double v)
 
  352             return 2.0*c()*v + b()*u + e();
 
  355         double duv(
double , 
double )
 
  360         double duu(
double , 
double )
 
  365         double dvv(
double , 
double )
 
  371         static QuadricLocal fit(std::vector<CoordType> &VV, 
bool svdRes, 
bool detCheck)
 
  373             assert(VV.size() >= 5);
 
  374             Eigen::MatrixXd A(VV.size(),5);
 
  375             Eigen::VectorXd b(VV.size());
 
  376             Eigen::VectorXd sol(5);
 
  378             for(
unsigned int c=0; c < VV.size(); ++c)
 
  380                 double u = VV[c].X();
 
  381                 double v = VV[c].Y();
 
  382                 double n = VV[c].Z();
 
  394             static int count = 0, index = 0;
 
  395             double min = 0.000000000001; 
 
  401             if (detCheck && ((A.transpose()*A).determinant() < min && (A.transpose()*A).determinant() > -min))
 
  405                 printf(
"Quadric: unsolvable vertex %d %d\n", count, ++index);
 
  408                 Eigen::JacobiSVD<Eigen::MatrixXd> svd(A);
 
  410                 return QuadricLocal(sol[0],sol[1],sol[2],sol[3],sol[4]);
 
  418                   Eigen::JacobiSVD<Eigen::MatrixXd> svd(A);
 
  423                     sol = ((A.transpose()*A).inverse()*A.transpose())*b;
 
  427             return QuadricLocal(sol[0],sol[1],sol[2],sol[3],sol[4]);
 
  431     static void expandMaxLocal (MeshType & mesh, VertexType *v, 
int max, std::vector<VertexType*> *vv)
 
  433     Nring<MeshType> rw = Nring<MeshType> (v, &mesh);
 
  434     do rw.expand (); 
while (rw.allV.size() < max+1);
 
  436         printf (
"rw.allV[0] != *v\n");
 
  437     vv->reserve ((
size_t)max);
 
  438     for (
int i = 1; i < max+1; i++)
 
  439         vv->push_back(rw.allV[i]);
 
  445     static void expandSphereLocal (MeshType & mesh, VertexType *v, 
float r, 
int min, std::vector<VertexType*> *vv)
 
  447     Nring<MeshType> rw = Nring<MeshType> (v, &mesh);
 
  449     bool isInside = 
true;
 
  453         vv->reserve(rw.allV.size());
 
  455         typename std::vector<VertexType*>::iterator b = rw.lastV.begin();
 
  456         typename std::vector<VertexType*>::iterator e = rw.lastV.end();
 
  460         if (((*b)->P() - v->P()).Norm() < r)
 
  471     if (vv->size() < min)
 
  474         expandMaxLocal (mesh, v, min, vv);
 
  479     static void getAverageNormal (VertexType *vp, std::vector<VertexType*> &vv, CoordType *ppn)
 
  481     *ppn = CoordType (0,0,0);
 
  482     for (
typename std::vector<VertexType*>::iterator vpi = vv.begin(); vpi != vv.end(); ++vpi)
 
  485     *ppn /= vv.size() + 1;
 
  490     static void applyProjOnPlane (CoordType ppn, std::vector<VertexType*> &vin, std::vector<VertexType*> *vout)
 
  492     for (
typename std::vector<VertexType*>::iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
 
  493         if ((*vpi)->N() * ppn > 0.0f)
 
  494         vout->push_back (*vpi);
 
  497     static CoordType projectLocal(VertexType* v, VertexType* vp, CoordType ppn)
 
  499         return vp->P() - (ppn * ((vp->P() - v->P()) * ppn));
 
  503     static void computeReferenceFramesLocal (VertexType *v, CoordType ppn, std::vector<CoordType> *ref)
 
  505     vcg::face::VFIterator<FaceType> vfi (v);
 
  507     int i = (vfi.I() + 1) % 3;
 
  508     VertexTypeP vp = vfi.F()->V(i);
 
  510     CoordType x = (projectLocal (v, vp, ppn) - v->P()).Normalize();
 
  512     assert(fabs(x * ppn) < 0.1);
 
  514     *ref = std::vector<CoordType>(3);
 
  517     (*ref)[1] = (ppn ^ (*ref)[0]).Normalize();
 
  518     (*ref)[2] = ppn.Normalize(); 
 
  522     static void fitQuadricLocal (VertexType *v, std::vector<CoordType> ref, std::vector<VertexType*> &vv, QuadricLocal *q)
 
  524     bool svdResolution = 
false;
 
  525     bool zeroDeterminantCheck = 
false;
 
  527     std::vector<CoordType> points;
 
  528     points.reserve (vv.size());
 
  530     typename std::vector<VertexType*>::iterator b = vv.begin();
 
  531     typename std::vector<VertexType*>::iterator e = vv.end();
 
  535         CoordType cp = (*b)->P();
 
  538         CoordType vTang = cp - v->P();
 
  540         double x = vTang * ref[0];
 
  541         double y = vTang * ref[1];
 
  542         double z = vTang * ref[2];
 
  543         points.push_back(CoordType(x,y,z));
 
  547     *q = QuadricLocal::fit (points, svdResolution, zeroDeterminantCheck);
 
  551     static void finalEigenStuff (VertexType *v, std::vector<CoordType> ref, QuadricLocal q)
 
  559     double E = 1.0 + d*d;
 
  561     double G = 1.0 + e*e;
 
  563     CoordType n = CoordType(-d,-e,1.0).Normalize();
 
  565     v->N() = ref[0] * n[0] + ref[1] * n[1] + ref[2] * n[2];
 
  567     double L = 2.0 * a * n.Z();
 
  568     double M = b * n.Z();
 
  569     double N = 2 * c * n.Z();
 
  573     m << L*G - M*F, M*E-L*F, M*E-L*F, N*E-M*F;
 
  575     Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eig(m);
 
  577     Eigen::Vector2d c_val = eig.eigenvalues();
 
  578     Eigen::Matrix2d c_vec = eig.eigenvectors();
 
  585     v1[2] = d * v1[0] + e * v1[1];
 
  589     v2[2] = d * v2[0] + e * v2[1];
 
  594     CoordType v1global = ref[0] * v1[0] + ref[1] * v1[1] + ref[2] * v1[2];
 
  595     CoordType v2global = ref[0] * v2[0] + ref[1] * v2[1] + ref[2] * v2[2];
 
  597     v1global.Normalize();
 
  598     v2global.Normalize();
 
  600     v1global *= c_val[0];
 
  601     v2global *= c_val[1];
 
  603     if (c_val[0] > c_val[1])
 
  605         (*v).PD1() = v1global;
 
  606         (*v).PD2() = v2global;
 
  607         (*v).K1()  = c_val[0];
 
  608         (*v).K2()  = c_val[1];
 
  612         (*v).PD1() = v2global;
 
  613         (*v).PD2() = v1global;
 
  614         (*v).K1()  = c_val[1];
 
  615         (*v).K2()  = c_val[0];
 
  622     static void updateCurvatureLocal (MeshType & mesh, 
float radiusSphere, vcg::CallBackPos * cb = NULL)
 
  625     bool projectionPlaneCheck = 
true;
 
  626     int vertexesPerFit = 0;
 
  630     for(vi = mesh.vert.begin(); vi != mesh.vert.end(); ++vi, i++)
 
  632         std::vector<VertexType*> vv;
 
  633         std::vector<VertexType*> vvtmp;
 
  634         if (cb && ((i%1024)==00)) {
 
  635             (*cb)(int(100.0f * (
float)i / (
float)mesh.vn),
"Vertices Analysis");
 
  637         expandSphereLocal (mesh, &*vi, radiusSphere, 5, &vv);
 
  639         assert (vv.size() >= 5);
 
  642         getAverageNormal (&*vi, vv, &ppn);
 
  644         if (projectionPlaneCheck)
 
  646         vvtmp.reserve (vv.size ());
 
  647         applyProjOnPlane (ppn, vv, &vvtmp);
 
  648         if (vvtmp.size() >= 5)
 
  653         assert (vv.size() >= 5);
 
  655         std::vector<CoordType> ref;
 
  656         computeReferenceFramesLocal (&*vi, ppn, &ref);
 
  658         vertexesPerFit += vv.size();
 
  661         fitQuadricLocal (&*vi, ref, vv, &q);
 
  663         finalEigenStuff (&*vi, ref, q);
 
  668         printf (
"average vertex num in each fit: %f\n", ((
float) vertexesPerFit) / mesh.vn);
 
static void CompactVertexVector(MeshType &m, PointerUpdater< VertexPointer > &pu)
Compact vector of vertices removing deleted elements. Deleted elements are put to the end of the vect...
Definition: allocate.h:1084
 
Definition: curvature_fitting.h:315
 
Definition: curvature_fitting.h:78
 
Computation of per-vertex directions and values of curvature.
Definition: curvature_fitting.h:62
 
Management, updating and computation of per-vertex and per-face flags (like border flags).
Definition: flag.h:44
 
static void NormalizePerVertex(ComputeMeshType &m)
Normalize the length of the vertex normals.
Definition: normal.h:239
 
static void PerVertexAngleWeighted(ComputeMeshType &m)
Calculates the vertex normal as an angle weighted average. It does not need or exploit current face n...
Definition: normal.h:124
 
static void VertexFace(MeshType &m)
Update the Vertex-Face topological relation.
Definition: topology.h:467
 
Definition: namespaces.dox:6