curve_on_manifold.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 #ifndef __VCGLIB_CURVE_ON_SURF_H
00024 #define __VCGLIB_CURVE_ON_SURF_H
00025 
00026 #include<vcg/complex/complex.h>
00027 #include<vcg/simplex/face/topology.h>
00028 #include<vcg/complex/algorithms/update/topology.h>
00029 #include<vcg/complex/algorithms/update/color.h>
00030 #include<vcg/complex/algorithms/update/normal.h>
00031 #include<vcg/complex/algorithms/update/quality.h>
00032 #include<vcg/complex/algorithms/clean.h>
00033 #include<vcg/complex/algorithms/refine.h>
00034 #include<vcg/complex/algorithms/create/platonic.h>
00035 #include <vcg/space/index/grid_static_ptr.h>
00036 #include <vcg/space/index/kdtree/kdtree.h>
00037 #include <vcg/math/histogram.h>
00038 #include<vcg/space/distance3.h>
00039 #include<eigenlib/Eigen/Core>
00040 #include <vcg/complex/algorithms/attribute_seam.h>
00041 #include <wrap/io_trimesh/export_ply.h>
00042 
00043 namespace vcg {
00044 namespace tri {
00047 
00052 template <class MeshType>
00053 class CoM
00054 {
00055 public:
00056   typedef typename MeshType::ScalarType     ScalarType;
00057   typedef typename MeshType::CoordType     CoordType;
00058   typedef typename MeshType::VertexType     VertexType;
00059   typedef typename MeshType::VertexPointer  VertexPointer;
00060   typedef typename MeshType::VertexIterator VertexIterator;
00061   typedef typename MeshType::EdgeIterator   EdgeIterator;
00062   typedef typename MeshType::EdgeType       EdgeType;
00063   typedef typename MeshType::FaceType       FaceType;
00064   typedef typename MeshType::FacePointer    FacePointer;
00065   typedef typename MeshType::FaceIterator   FaceIterator;
00066   typedef Box3  <ScalarType>               Box3Type;
00067   typedef typename vcg::GridStaticPtr<FaceType, ScalarType> MeshGrid;  
00068   typedef typename vcg::GridStaticPtr<EdgeType, ScalarType> EdgeGrid;
00069   typedef typename face::Pos<FaceType> PosType;
00070   
00071   class Param 
00072   {
00073   public:
00074     
00075     ScalarType surfDistThr; // Distance between surface and curve; used in simplify and refine
00076     ScalarType polyDistThr; // Distance between the 
00077     ScalarType minRefEdgeLen;  // Minimal admitted Edge Lenght (used in refine: never make edge shorther than this value) 
00078     ScalarType maxSimpEdgeLen; // Minimal admitted Edge Lenght (used in simplify: never make edges longer than this value) 
00079     ScalarType maxSmoothDelta; // The maximum movement that is admitted during smoothing.
00080     ScalarType maxSnapThr;     // The maximum distance allowed when snapping a vertex of the polyline onto a mesh vertex
00081     ScalarType gridBailout;    // The maximum distance bailout used in grid sampling
00082     
00083     Param(MeshType &m) { Default(m);}
00084     
00085     void Default(MeshType &m)
00086     {
00087       surfDistThr   = m.bbox.Diag()/1000.0;
00088       polyDistThr   = m.bbox.Diag()/5000.0;
00089       minRefEdgeLen    = m.bbox.Diag()/16000.0;
00090       maxSimpEdgeLen    = m.bbox.Diag()/1000.0;
00091       maxSmoothDelta =   m.bbox.Diag()/100.0;
00092       maxSnapThr =       m.bbox.Diag()/10000.0;
00093       gridBailout =      m.bbox.Diag()/20.0;
00094     }
00095     void Dump() const
00096     {
00097       printf("surfDistThr    = %6.4f\n",surfDistThr   );
00098       printf("polyDistThr    = %6.4f\n",polyDistThr   );
00099       printf("minRefEdgeLen  = %6.4f\n",minRefEdgeLen    );
00100       printf("maxSimpEdgeLen = %6.4f\n",maxSimpEdgeLen    );
00101       printf("maxSmoothDelta = %6.4f\n",maxSmoothDelta);
00102     }
00103   };
00104   
00105   
00106   
00107   // The Data Members
00108   
00109   MeshType &base; 
00110   MeshGrid uniformGrid;
00111   
00112   Param par; 
00113   CoM(MeshType &_m) :base(_m),par(_m){}
00114  
00115   
00116   //******** CUT TREE GENERATION 
00117 
00118   int countNonVisitedEdges(VertexType * vp, EdgeType * &ep)
00119   {
00120     std::vector<EdgeType *> starVec;
00121     edge::VEStarVE(&*vp,starVec);
00122   
00123     int cnt =0;
00124     for(size_t i=0;i<starVec.size();++i)
00125     {
00126       if(!starVec[i]->IsV())
00127       {
00128         cnt++;
00129         ep = starVec[i];
00130       }
00131     }
00132   
00133     return cnt;
00134   }
00135   
00136   // Given two points return true if on the base mesh there exist an edge with that two coords
00137   // if return true the pos indicate the found edge. 
00138   bool ExistEdge(KdTree<ScalarType> &kdtree, CoordType &p0, CoordType &p1, PosType &fpos)
00139   {
00140     ScalarType locEps = SquaredDistance(p0,p1)/100000.0;
00141     
00142     VertexType *v0=0,*v1=0;
00143     unsigned int veInd;
00144     ScalarType sqdist;
00145     kdtree.doQueryClosest(p0,veInd,sqdist);
00146     if(sqdist<locEps) 
00147       v0 = &base.vert[veInd];
00148     kdtree.doQueryClosest(p1,veInd,sqdist);
00149     if(sqdist<locEps) 
00150       v1 = &base.vert[veInd];
00151     if(v0 && v1)
00152     {
00153       face::VFIterator<FaceType> vfi(v0);
00154       while(!vfi.End())
00155       { 
00156         if(vfi.V1()==v1)
00157         {
00158           fpos = PosType(vfi.F(),vfi.I(), v0);
00159           return true;
00160         }
00161         if(vfi.V2()==v1)
00162         {
00163           fpos = PosType(vfi.F(),(vfi.I()+1)%3, v1);
00164           return true;
00165         }
00166         ++vfi;
00167       }      
00168     }
00169     return false;
00170   }
00171   
00172   bool OptimizeTree(MeshType &t)
00173   {
00174     tri::Allocator<MeshType>::CompactEveryVector(t);
00175     tri::UpdateTopology<MeshType>::VertexEdge(t);
00176     tri::UpdateTopology<MeshType>::VertexFace(base);
00177     VertexConstDataWrapper<MeshType > vdw(base);
00178     KdTree<ScalarType> kdtree(vdw);
00179     
00180     // First simple loop that search for 2->1 moves. 
00181     for(VertexIterator vi=t.vert.begin();vi!=t.vert.end();++vi)
00182     {
00183       std::vector<VertexType *> starVec;
00184       edge::VVStarVE(&*vi,starVec);
00185       if(starVec.size()==2)
00186       {
00187         PosType pos;
00188         if(ExistEdge(kdtree,starVec[0]->P(),starVec[1]->P(),pos))
00189           edge::VEEdgeCollapse(t,&*vi);
00190       }
00191     }
00192     return (t.en < t.edge.size());
00193   }
00194   
00195   void Retract(MeshType &t)
00196   {
00197     tri::Clean<MeshType>::RemoveDuplicateVertex(t);
00198     printf("Retracting a tree of %i edges and %i vertices\n",t.en,t.vn);
00199     tri::UpdateTopology<MeshType>::VertexEdge(t);
00200   
00201     std::stack<VertexType *> vertStack;
00202   
00203     // Put on the stack all the vertex with just a single incident edge. 
00204     for(VertexIterator vi=t.vert.begin();vi!=t.vert.end();++vi)
00205     {
00206       std::vector<EdgeType *> starVec;
00207       edge::VEStarVE(&*vi,starVec);
00208       if(starVec.size()==1)
00209         vertStack.push(&*vi);
00210     }
00211   
00212     tri::UpdateFlags<MeshType>::EdgeClearV(t);
00213     tri::UpdateFlags<MeshType>::VertexClearV(t);
00214     
00215     int unvisitedEdgeNum = t.en;
00216     while((!vertStack.empty()) && (unvisitedEdgeNum > 2) )
00217     {
00218       VertexType *vp = vertStack.top();
00219       vertStack.pop();
00220       vp->C()=Color4b::Blue;
00221       EdgeType *ep=0;
00222   
00223       int eCnt =  countNonVisitedEdges(vp,ep);
00224       if(eCnt==1) // We have only one non visited edge over vp
00225       {
00226         assert(!ep->IsV());
00227         ep->SetV();
00228         --unvisitedEdgeNum;
00229         VertexType *otherVertP;
00230         if(ep->V(0)==vp) otherVertP = ep->V(1);
00231         else otherVertP = ep->V(0);
00232         vertStack.push(otherVertP);
00233       }
00234     }
00235     assert(unvisitedEdgeNum >0);
00236     
00237     for(size_t i =0; i<t.edge.size();++i)
00238       if(t.edge[i].IsV()) tri::Allocator<MeshType>::DeleteEdge(t,t.edge[i]);
00239     assert(t.en >0);
00240     tri::Clean<MeshType>::RemoveUnreferencedVertex(t);
00241     tri::Allocator<MeshType>::CompactEveryVector(t);
00242   
00243   }
00244   
00245   void CleanSpuriousDanglingEdges(MeshType &poly)
00246   {    
00247     EdgeGrid edgeGrid;
00248     edgeGrid.Set(poly.edge.begin(), poly.edge.end());    
00249     std::vector< std::pair<VertexType *, VertexType *> > mergeVec;
00250     UpdateFlags<MeshType>::FaceClearV(base);
00251     UpdateTopology<MeshType>::FaceFace(base);
00252     for(int i=0;i<base.fn;++i)
00253     {
00254       FaceType *fp=&base.face[i];
00255       if(!fp->IsV())
00256       {
00257         for(int j=0;j<3;++j)
00258           if(face::IsBorder(*fp,j))
00259           {
00260             face::Pos<FaceType> startPos(fp,int(j));
00261             assert(startPos.IsBorder());
00262             face::Pos<FaceType> curPos=startPos;
00263             face::Pos<FaceType> prevPos=startPos;
00264             int edgeCnt=0;
00265             do
00266             {
00267               prevPos=curPos;
00268               curPos.F()->SetV();
00269               curPos.NextB();
00270               edgeCnt++;
00271               if(Distance(curPos.V()->P(),prevPos.VFlip()->P())<0.000000001f)
00272               {
00273                 Point3f endp = curPos.VFlip()->P();
00274                 float minDist=par.gridBailout;
00275                 Point3f closestP;
00276                 EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,endp,par.gridBailout,minDist,closestP);        
00277                 if(minDist > par.polyDistThr){
00278                   mergeVec.push_back(std::make_pair(curPos.V(),prevPos.VFlip()));
00279                   printf("Vertex %i and %i should be merged\n",tri::Index(base,curPos.V()),tri::Index(base,prevPos.VFlip()));
00280                 }
00281               }
00282               
00283             } while(curPos!=startPos);
00284             printf("walked along a border of %i edges\n",edgeCnt);
00285             break;
00286           }
00287       }
00288     }
00289     printf("Found %i vertex pairs to be merged\n",mergeVec.size());
00290     for(int k=0;k<mergeVec.size();++k)
00291     {
00292       VertexType *vdel=mergeVec[k].first;
00293       VertexType *vmerge=mergeVec[k].second;
00294       for(int i=0;i<base.fn;++i)
00295       {
00296         FaceType *fp=&base.face[i];
00297         for(int j=0;j<3;++j)
00298           if(fp->V(j)==vdel) fp->V(j)=vmerge;        
00299       }
00300       Allocator<MeshType>::DeleteVertex(base,*vdel);
00301     }
00302     Allocator<MeshType>::CompactEveryVector(base);
00303     
00304    
00305       for(int i=0;i<base.fn;++i)
00306       {
00307         FaceType *fp=&base.face[i];
00308         for(int j=0;j<3;++j)
00309           if(fp->V0(j)==fp->V1(j)) 
00310         {
00311             Allocator<MeshType>::DeleteFace(base,*fp);
00312             printf("Deleted face %i\n",tri::Index(base,fp));
00313         }
00314         
00315       }
00316       Allocator<MeshType>::CompactEveryVector(base);
00317   }  
00318   
00319   
00320   // \brief This function build a cut tree. 
00321   //
00322   // First we make a bread first FF face visit. 
00323   // Each time that we encounter a visited face we cut add to the tree the edge 
00324   // that brings to the already visited face.
00325   // this structure build a dense graph and we retract this graph retracting each 
00326   // leaf until we remains with just the loops that cuts the object. 
00327   
00328   void BuildVisitTree(MeshType &dualMesh)
00329   {
00330     tri::UpdateTopology<MeshType>::FaceFace(base);
00331     tri::UpdateFlags<MeshType>::FaceClearV(base);
00332     
00333     std::vector<face::Pos<FaceType> > visitStack; // the stack contain the pos on the 'starting' face. 
00334     
00335     
00336     MeshType treeMesh; // this mesh will contain the set of the non traversed edge 
00337     
00338     base.face[0].SetV();
00339     for(int i=0;i<3;++i)
00340       visitStack.push_back(PosType(&(base.face[0]),i,base.face[0].V(i)));
00341   
00342     int cnt=1;
00343     
00344     while(!visitStack.empty())
00345     {
00346       std::swap(visitStack.back(),visitStack[rand()%visitStack.size()]);
00347       PosType c = visitStack.back();
00348       visitStack.pop_back();
00349       assert(c.F()->IsV());
00350       c.F()->C() = Color4b::ColorRamp(0,base.fn,cnt);
00351       c.FlipF();
00352       if(!c.F()->IsV())
00353       {
00354         tri::Allocator<MeshType>::AddEdge(treeMesh,Barycenter(*(c.FFlip())),Barycenter(*(c.F())));
00355         ++cnt;
00356         c.F()->SetV();
00357         c.FlipE();c.FlipV();
00358         visitStack.push_back(c);
00359         c.FlipE();c.FlipV();
00360         visitStack.push_back(c);
00361       }
00362       else
00363       {
00364         tri::Allocator<MeshType>::AddEdge(dualMesh,c.V()->P(),c.VFlip()->P());
00365       }
00366     }
00367     assert(cnt==base.fn);
00368     
00369     Retract(dualMesh);
00370 } 
00371   
00372   /*
00373    * Given a mesh <m> and a polyline <e> whose edges are a subset of edges of m
00374    * This function marks the edges of m as non-faux when they coincide with the polyline ones. 
00375    * 
00376    * Use this function toghether with the CutMeshAlongCrease function to actually cut the mesh. 
00377    */
00378   
00379   void MarkFauxEdgeWithPolyLine(MeshType &m, MeshType &e)
00380   {
00381     tri::UpdateFlags<MeshType>::FaceSetF(m);
00382     tri::UpdateTopology<MeshType>::VertexEdge(e);
00383     VertexConstDataWrapper<MeshType > vdw(e);
00384     KdTree<ScalarType> edgeTree(vdw);
00385     
00386     for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00387     {
00388       for(int i=0;i<3;++i)
00389       {
00390         ScalarType locEps = SquaredDistance(fi->P0(i), fi->P1(i))/100000.0;
00391         unsigned int veInd;
00392         ScalarType sqdist;
00393         edgeTree.doQueryClosest(fi->P(i),veInd,sqdist);
00394         if(sqdist<locEps)
00395         {
00396           std::vector<VertexPointer> starVecVp;
00397           edge::VVStarVE(&(e.vert[veInd]),starVecVp);      
00398           for(size_t j=0;j<starVecVp.size();++j)
00399           {
00400             if(SquaredDistance(starVecVp[j]->P(),fi->P1(i))< locEps)
00401               fi->ClearF(i);
00402           }
00403         }        
00404       }
00405     }
00406     
00407   }
00408   
00409   
00410   
00411   
00412   void SnapPolyline(MeshType &t)
00413   {
00414     printf("Selected vert num %i\n",tri::UpdateSelection<MeshType>::VertexCount(t));
00415     
00416     tri::UpdateFlags<MeshType>::VertexClearS(base);
00417     tri::UpdateFlags<MeshType>::VertexClearS(t);
00418     tri::Allocator<MeshType>::CompactEveryVector(t);
00419     VertexConstDataWrapper<MeshType > vdw(base);
00420     KdTree<ScalarType> kdtree(vdw);
00421 
00422     for(VertexIterator vi=t.vert.begin();vi!=t.vert.end();++vi)
00423     {
00424       unsigned int veInd;
00425       ScalarType sqdist;
00426       kdtree.doQueryClosest(vi->P(),veInd,sqdist);
00427       VertexPointer vp = &base.vert[veInd];
00428       if(!vp->IsS())
00429       {
00430         ScalarType dist = sqrt(sqdist);
00431         std::vector<VertexPointer> starVecVp;        
00432         face::VVStarVF<FaceType>(vp,starVecVp);
00433         ScalarType minEdgeLen = std::numeric_limits<ScalarType>::max();
00434         for(int i=0;i<starVecVp.size();++i)
00435           minEdgeLen = std::min(Distance(vp->P(),starVecVp[i]->P()),minEdgeLen);
00436         if(dist < minEdgeLen/3.0)
00437         {
00438           vi->P() = vp->P();
00439           vi->SetS();
00440           vp->SetS();
00441         }
00442       }
00443     }
00444     printf("Selected vert num %i\n",tri::UpdateSelection<MeshType>::VertexCount(t));    
00445   }
00446   
00447   
00448   
00449   
00450   float MinDistOnEdge(Point3f samplePnt, EdgeGrid &edgeGrid, MeshType &poly, Point3f &closestPoint)
00451   {
00452       float polyDist;
00453       EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,par.gridBailout,polyDist,closestPoint);        
00454       return polyDist;    
00455   }
00456   
00457   // Given an edge of a mesh, supposedly intersecting the polyline, 
00458   // we search on it the closest point to the polyline
00459   static float MinDistOnEdge(VertexType *v0,VertexType *v1, EdgeGrid &edgeGrid, MeshType &poly, Point3f &closestPoint)
00460   {
00461     float minPolyDist = std::numeric_limits<ScalarType>::max();
00462     const float sampleNum = 50;
00463     const float maxDist = poly.bbox.Diag()/10.0;
00464     for(float k = 0;k<sampleNum+1;++k)
00465     {
00466       float polyDist;
00467       Point3f closestPPoly;
00468       Point3f samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;          
00469       
00470       EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,maxDist,polyDist,closestPPoly);        
00471       
00472       if(polyDist < minPolyDist)
00473       {
00474         minPolyDist = polyDist;
00475         closestPoint = samplePnt;
00476 //        closestPoint = closestPPoly;
00477       }
00478     }
00479     return minPolyDist;    
00480   }
00481   
00482   
00489   static inline void ExtractVertex(const MeshType & srcMesh, const FaceType & f, int whichWedge, const MeshType & dstMesh, VertexType & v)
00490   {
00491       (void)srcMesh;
00492       (void)dstMesh;
00493       // This is done to preserve every single perVertex property
00494       // perVextex Texture Coordinate is instead obtained from perWedge one.
00495       v.ImportData(*f.cV(whichWedge));
00496       v.C() = f.cC();
00497   }
00498   
00499   static inline bool CompareVertex(const MeshType & m, const VertexType & vA, const VertexType & vB)
00500   {
00501       (void)m;
00502       
00503       if(vA.C() == Color4b(Color4b::Red) && vB.C() == Color4b(Color4b::Blue) ) return false;
00504       if(vA.C() == Color4b(Color4b::Blue) && vB.C() == Color4b(Color4b::Red) ) return false;
00505       return true;      
00506   }
00507   
00508   
00509   
00510   static Point3f QLerp(VertexType *v0, VertexType *v1)
00511   {
00512     
00513     float qSum = fabs(v0->Q())+fabs(v1->Q());      
00514     float w0 = (qSum - fabs(v0->Q()))/qSum;
00515     float w1 = (qSum - fabs(v1->Q()))/qSum;      
00516     return v0->P()*w0 + v1->P()*w1;      
00517   }
00518   
00519   class QualitySign
00520   {
00521   public:
00522       EdgeGrid &edgeGrid;
00523       MeshType &poly;
00524       CoM &com;
00525       QualitySign(EdgeGrid &_e,MeshType &_poly, CoM &_com):edgeGrid(_e),poly(_poly),com(_com) {};
00526       bool operator()(face::Pos<FaceType> ep) const
00527       {
00528         VertexType *v0 = ep.V();
00529         VertexType *v1 = ep.VFlip();
00530         if(v0->Q() * v1->Q() < 0)
00531         { 
00532           Point3f pp = QLerp(v0,v1);
00533           Point3f closestP;
00534           if(com.MinDistOnEdge(pp,edgeGrid,poly,closestP)<com.par.polyDistThr) return true;
00535           float minDist = com.MinDistOnEdge(v0,v1,edgeGrid,poly,closestP);
00536           if(minDist < com.par.polyDistThr) return true;
00537         }
00538         return false;
00539       }
00540   };
00541   
00542   struct QualitySignSplit : public std::unary_function<face::Pos<FaceType> ,  Point3f>
00543   {
00544     EdgeGrid &edgeGrid;
00545     MeshType &poly;
00546     CoM &com;
00547     vector<int> &newVertVec; 
00548     
00549     QualitySignSplit(EdgeGrid &_e,MeshType &_p, CoM &_com, vector<int> &_vec):edgeGrid(_e),poly(_p),com(_com),newVertVec(_vec) {};
00550       void operator()(VertexType &nv, face::Pos<FaceType> ep)
00551       {
00552         VertexType *v0 = ep.V();
00553         VertexType *v1 = ep.VFlip();
00554         Point3f pp = QLerp(v0,v1);
00555         Point3f closestP;
00556         com.MinDistOnEdge(pp,edgeGrid,poly,closestP);
00557         
00558 //        float minDist = MinDistOnEdge(v0,v1,edgeGrid,poly,closestP);
00559         nv.P()=closestP;        
00560         nv.Q()=0;
00561         newVertVec.push_back(tri::Index(com.base,&nv));
00562 //        nv.P() = CoS::QLerp(v0,v1);        
00563       }
00564       Color4b WedgeInterp(Color4b &c0, Color4b &c1)
00565       {
00566           Color4b cc;
00567           cc.lerp(c0,c1,0.5f);
00568           return Color4b::Red;
00569       }
00570       TexCoord2f WedgeInterp(TexCoord2f &t0, TexCoord2f &t1)
00571       {
00572           TexCoord2f tmp;
00573           assert(t0.n()== t1.n());
00574           tmp.n()=t0.n();
00575           tmp.t()=(t0.t()+t1.t())/2.0;
00576           return tmp;
00577       }
00578   };
00579   
00580   class EdgePointPred
00581   {
00582   public:
00583       CoM &com;
00584       KdTree<ScalarType> &kdtree;
00585       
00586       EdgePointPred(CoM &_com, KdTree<ScalarType> &_kdtree):com(_com),kdtree(_kdtree) {};
00587       bool operator()(face::Pos<FaceType> ep) const
00588       {
00589         CoordType p0 = ep.V()->P();
00590         CoordType p1 = ep.VFlip()->P();
00591         float stepNum=100.0;
00592         float locEps = Distance(p0,p1)/stepNum;
00593         for(float j=0;j<stepNum;++j)
00594         {
00595           CoordType qp = (p0*j+p1*(stepNum-j))/stepNum;
00596           unsigned int veInd;
00597           ScalarType sqdist;
00598           kdtree.doQueryClosest(qp,veInd,sqdist);
00599           if(sqrt(sqdist)<locEps) return true;
00600         }
00601         return false;
00602       }
00603   };
00604   
00605   struct EdgePointSplit : public std::unary_function<face::Pos<FaceType> ,  Point3f>
00606   {
00607     CoM &com;
00608     KdTree<ScalarType> &kdtree;
00609     MeshType &poly;
00610     
00611     EdgePointSplit(CoM &_com, KdTree<ScalarType> &_kdtree, MeshType &_poly):com(_com),kdtree(_kdtree),poly(_poly) {};
00612       void operator()(VertexType &nv, face::Pos<FaceType> ep)
00613       {
00614         CoordType p0 = ep.V()->P();
00615         CoordType p1 = ep.VFlip()->P();
00616         float stepNum=100.0;
00617         float locEps = Distance(p0,p1)/stepNum;
00618         for(float j=0;j<stepNum;++j)
00619         {
00620           CoordType qp = (p0*j+p1*(stepNum-j))/stepNum;
00621           unsigned int veInd;
00622           ScalarType sqdist;
00623           kdtree.doQueryClosest(qp,veInd,sqdist);
00624           if(sqrt(sqdist)<locEps) 
00625             nv.P() = poly.vert[veInd].P();           
00626         }
00627         return;
00628       }
00629       Color4b WedgeInterp(Color4b &c0, Color4b &c1)
00630       {
00631           Color4b cc;
00632           cc.lerp(c0,c1,0.5f);
00633           return Color4b::Red;
00634       }
00635       TexCoord2f WedgeInterp(TexCoord2f &t0, TexCoord2f &t1)
00636       {
00637           TexCoord2f tmp;
00638           assert(t0.n()== t1.n());
00639           tmp.n()=t0.n();
00640           tmp.t()=(t0.t()+t1.t())/2.0;
00641           return tmp;
00642       }
00643   };
00644   
00645   
00646   
00647   
00648   void DumpPlaneMesh(MeshType &poly, std::vector<Plane3f> &planeVec, int i =0)
00649   {
00650     MeshType full;
00651     for(int i=0;i<planeVec.size();++i)
00652     {
00653       float radius=edge::Length(poly.edge[i])/2.0;
00654       MeshType t;
00655       OrientedDisk(t,16,edge::Center(poly.edge[i]),planeVec[i].Direction(),radius);
00656       tri::Append<MeshType,MeshType>::Mesh(full,t);
00657     }
00658     char buf[100];
00659     sprintf(buf,"planes%03i.ply",i);
00660     tri::io::ExporterPLY<MeshType>::Save(full,buf);  
00661   }
00662 
00663   Plane3f ComputeEdgePlane(VertexType *v0, VertexType *v1)
00664   {
00665     Plane3f pl;
00666     Point3f mid = (v0->P()+v1->P())/2.0;
00667     Point3f delta = (v1->P()-v0->P()).Normalize();
00668     Point3f n0 =  (v0->N() ^ delta).Normalize();
00669     Point3f n1 =  (v1->N() ^ delta).Normalize();
00670     Point3f n = (n0+n1)/2.0;
00671     pl.Init(mid,n);
00672     return pl;
00673   }
00674 
00675 
00676   void ComputePlaneField(MeshType &poly, EdgeGrid &edgeGrid, int ind)
00677   {
00678     // First Compute per-edge planes
00679     std::vector<Plane3f> planeVec(poly.en);
00680     for(int i=0;i<poly.en;++i)
00681     {
00682       planeVec[i] = ComputeEdgePlane(poly.edge[i].V(0), poly.edge[i].V(1));
00683     }
00684     
00685     DumpPlaneMesh(poly,planeVec,ind);
00686     edgeGrid.Set(poly.edge.begin(), poly.edge.end());    
00687     
00688     for(VertexIterator vi=base.vert.begin();vi!=base.vert.end();++vi)
00689     {
00690       Point3<ScalarType> p = vi->P();
00691       
00692       float minDist=par.gridBailout;
00693       Point3f closestP;
00694       EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,p,par.gridBailout,minDist,closestP);        
00695       if(cep)
00696       {
00697         int ind = tri::Index(poly,cep);        
00698         vi->Q() = SignedDistancePlanePoint(planeVec[ind],p);
00699         Point3f proj = planeVec[ind].Projection(p);
00700         
00701 //        if(Distance(proj,closestP)>edge::Length(*cep))
00702 //        {
00703 //          vi->Q() =1;
00704 //          vi->SetS();
00705 //        }
00706       }
00707       else {
00708         vi->Q() =1;
00709       }
00710     } 
00711   }
00712 
00713   
00714   void CutAlongPolyLineUsingField(MeshType &poly,EdgeGrid &edgeGrid,std::vector<int> &newVertVec)
00715 {
00716   QualitySign qsPred(edgeGrid,poly,*this);
00717   QualitySignSplit qsSplit(edgeGrid,poly,*this,newVertVec);
00718   tri::UpdateTopology<MeshType>::FaceFace(base);
00719   tri::RefineE(base,qsSplit,qsPred);    
00720   tri::UpdateTopology<MeshType>::FaceFace(base);
00721     
00722   
00723   for(int i=0;i<base.fn;++i)
00724   {
00725     FaceType *fp = &base.face[i];
00726     if(!fp->IsD())
00727     {
00728     for(int j=0;j<3;++j)
00729     {
00730       if(Distance(fp->P0(j),fp->P1(j)) < par.polyDistThr)
00731       {
00732         if(face::FFLinkCondition(*fp,j))
00733         {
00734 //            if(fp->V0(j)->Q()==0) fp->V1(j)->Q()=0;
00735 //            face::FFEdgeCollapse(base,*fp,j);        
00736             break;
00737         }
00738       }
00739     }
00740     }
00741   }
00742   tri::Allocator<MeshType>::CompactEveryVector(base);
00743   
00744   for(int i=0;i<base.fn;++i)
00745   {
00746     FaceType *fp = &base.face[i];
00747     if( (fp->V(0)->Q()==0) &&
00748         (fp->V(1)->Q()==0) &&
00749         (fp->V(2)->Q()==0) )
00750     {
00751       ScalarType maxDist = 0;
00752       int maxInd = -1;
00753       for(int j=0;j<3;++j)
00754       {
00755         Point3f closestPt;
00756         ScalarType d = MinDistOnEdge(fp->P(j),edgeGrid,poly,closestPt);
00757         if(d>maxDist)
00758         { 
00759           maxDist= d;
00760           maxInd=j;
00761         }
00762       }        
00763 //      assert(maxInd!=-1);
00764 //      if(maxInd>=0 && maxDist > par.surfDistThr)
00765 //        fp->V(maxInd)->Q() = maxDist;
00766     }
00767   }  
00768   
00769     for(int i=0;i<base.fn;++i)
00770     {
00771       FaceType *fp = &base.face[i];
00772       if( (fp->V(0)->Q()>=0) &&
00773           (fp->V(1)->Q()>=0) &&
00774           (fp->V(2)->Q()>=0) )
00775         fp->C() = Color4b::Blue;
00776       if( (fp->V(0)->Q()<=0) &&
00777           (fp->V(1)->Q()<=0) &&
00778           (fp->V(2)->Q()<=0) )
00779         fp->C() = Color4b::Red;
00780       if( (fp->V(0)->Q()==0) &&
00781           (fp->V(1)->Q()==0) &&
00782           (fp->V(2)->Q()==0) )
00783         fp->C() = Color4b::Green;
00784       
00785       if( (fp->V(0)->Q()>0) &&
00786           (fp->V(1)->Q()>0) &&
00787           (fp->V(2)->Q()>0) )
00788         fp->C() = Color4b::White;
00789       if( (fp->V(0)->Q()<0) &&
00790           (fp->V(1)->Q()<0) &&
00791           (fp->V(2)->Q()<0) )
00792         fp->C() = Color4b::White;
00793   }
00794     tri::AttributeSeam::SplitVertex(base, ExtractVertex, CompareVertex);
00795     
00796  }
00797   
00798   void WalkAlongPolyLine(MeshType &poly, std::vector<VertexType *> &ptVec)
00799   {
00800     // Search a starting vertex
00801     VertexType *startVert;
00802     for(int i=0;i<base.vn;++i)
00803     {
00804       if(Distance(base.vert[i].P(),ptVec[0]->P()) < par.polyDistThr)
00805       {
00806         startVert = &base.vert[i];
00807         break;
00808       }
00809     }
00810     tri::UpdateTopology<MeshType>::VertexFace(base);
00811     tri::UpdateTopology<MeshType>::FaceFace(base);
00812     
00813     
00814     
00815   }
00816   
00817     
00818     
00819     
00820 //  }
00821 // } 
00822   
00828   void CutWithPolyLine(MeshType &poly)
00829   {    
00830     std::vector<int> newVertVec;
00831     SnapPolyline(poly, &newVertVec);
00832     tri::io::ExporterPLY<MeshType>::Save(poly,"poly_snapped.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);    
00833     
00834     DecomposeNonManifoldPolyline(poly);
00835     tri::io::ExporterPLY<MeshType>::Save(poly,"poly_manif.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);    
00836     std::vector< std::vector< int> > ccVec;
00837     BuildConnectedComponentVectors(poly,ccVec);
00838     printf("PolyLine of %i edges decomposed into %i manifold components\n",poly.en,ccVec.size());
00839     Reorient(poly,ccVec);
00840     char buf[1024];
00841     for(int i=0;i<ccVec.size();++i)
00842 //      for(int i=0;i<10;++i)
00843       {
00844         MeshType subPoly;
00845         ExtractSubMesh(poly,ccVec[i],subPoly);
00846         std::vector< VertexType *> ptVec;
00847         FindTerminalPoints(subPoly,ptVec);
00848         printf("Component %i (%i edges) has %i terminal points\n",i,subPoly.en, ptVec.size());fflush(stdout);
00849         SplitMeshWithPoints(base,ptVec,newVertVec);
00850 //        sprintf(buf,"CuttingPoly%02i.ply",i);
00851 //        tri::io::ExporterPLY<MeshType>::Save(subPoly, buf,tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);        
00852         EdgeGrid edgeGrid;
00853         ComputePlaneField(subPoly, edgeGrid,i);
00854         sprintf(buf,"PlaneField%02i.ply",i);
00855         tri::io::ExporterPLY<MeshType>::Save(base,buf,tri::io::Mask::IOM_VERTCOLOR + tri::io::Mask::IOM_VERTQUALITY );
00856         CutAlongPolyLineUsingField(subPoly,edgeGrid,newVertVec);
00857         sprintf(buf,"PlaneCut%02i.ply",i);
00858         tri::io::ExporterPLY<MeshType>::Save(base,buf,tri::io::Mask::IOM_FACECOLOR + tri::io::Mask::IOM_VERTQUALITY );  
00859       }
00860     
00861 //    printf("Added %i vertices\n",newVertVec.size());
00862 //    for(int i=0;i<newVertVec.size();++i)
00863 //        base.vert[newVertVec[i]].C()=Color4b::Red;
00864     tri::io::ExporterPLY<MeshType>::Save(base,"base_cut.ply",tri::io::Mask::IOM_VERTCOLOR + tri::io::Mask::IOM_VERTQUALITY );  
00865     CleanSpuriousDanglingEdges(poly);
00866     tri::io::ExporterPLY<MeshType>::Save(base,"base_cut_clean.ply",tri::io::Mask::IOM_VERTCOLOR + tri::io::Mask::IOM_VERTQUALITY );  
00867     
00868   }
00869 
00870   
00871   
00872   
00873   void SnapPolyline(MeshType &poly, std::vector<int> *newVertVec)
00874   {
00875     const float maxDist = base.bbox.Diag()/100.0;
00876     const ScalarType interpEps = 0.0001;
00877     int vertSnapCnt=0;
00878     int edgeSnapCnt=0;
00879     for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
00880     {
00881       float closestDist;
00882       Point3f closestP,closestN,ip;
00883       FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,vi->P(),maxDist, closestDist, closestP, closestN,ip);
00884       assert(f);
00885       VertexType *closestVp=0;
00886       int indIp = -1;
00887       ScalarType minDist = std::numeric_limits<ScalarType>::max();
00888       ScalarType minIp = minDist;
00889       for(int i=0;i<3;++i)
00890       {
00891         if(Distance(vi->P(),f->P(i))<minDist)
00892         {
00893           minDist = Distance(vi->P(),f->P(i));
00894           closestVp = f->V(i);
00895         }
00896         if(minIp > ip[i]) 
00897         {
00898           indIp = i;
00899           minIp=ip[i];
00900         }          
00901       }
00902       assert(closestVp && (indIp!=-1));
00903       
00904       
00905       if(minDist < par.maxSnapThr) {  // First Case: Snap to vertex;
00906         vi->P() = closestVp->P();
00907         vertSnapCnt++;
00908         if(newVertVec)
00909         newVertVec->push_back(tri::Index(base,closestVp));
00910       } else {
00911         if(minIp < interpEps) {       // Second Case: Snap to edge;
00912           ScalarType T1 = ip[(indIp+1)%3];
00913           ScalarType T2 = ip[(indIp+2)%3];
00914           vi->P() = (f->V1(indIp)->P() * T1 + f->V2(indIp)->P() * T2)/(T1+T2);
00915           edgeSnapCnt++;
00916         }
00917       }
00918     }
00919     printf("Snapped %i onto vert and %i onto edges\n",vertSnapCnt, edgeSnapCnt);
00920   }
00921  
00922 
00923   
00924   /*
00925    * Make an edge mesh 1-manifold by splitting all the
00926    * vertexes that have more than two incident edges
00927    * 
00928    * It performs the split in three steps. 
00929    * - First it collects and counts the vertices to be splitten. 
00930    * - Then it adds the vertices to the mesh and 
00931    * - lastly it updates the poly with the newly added vertices. 
00932    * 
00933    * singSplitFlag allows to ubersplit each singularity in a number of vertex of the same order of its degree. 
00934    * This is not really necessary but helps the management of sharp turns in the poly mesh.
00935    * \todo add corner detection and split.
00936    */
00937   
00938   void DecomposeNonManifoldPolyline(MeshType &poly, bool singSplitFlag = true)
00939   {
00940     tri::Allocator<MeshType>::CompactEveryVector(poly);
00941     std::vector<int> degreeVec(poly.vn, 0);
00942     tri::UpdateTopology<MeshType>::VertexEdge(poly);
00943     int neededVert=0;
00944     int delta;
00945     if(singSplitFlag) delta = 1;
00946                  else delta = 2;
00947       
00948     for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
00949     {
00950       std::vector<EdgeType *> starVec;
00951       edge::VEStarVE(&*vi,starVec);
00952       degreeVec[tri::Index(poly, *vi)] = starVec.size();
00953       if(starVec.size()>2)
00954         neededVert += starVec.size()-delta;
00955     }
00956     printf("DecomposeNonManifold Adding %i vert to a polyline of %i vert\n",neededVert,poly.vn);
00957     VertexIterator firstVi = tri::Allocator<MeshType>::AddVertices(poly,neededVert);
00958     
00959     for(size_t i=0;i<degreeVec.size();++i)
00960     {
00961       if(degreeVec[i]>2)
00962       {
00963         std::vector<EdgeType *> edgeStarVec;
00964         edge::VEStarVE(&(poly.vert[i]),edgeStarVec);
00965         assert(edgeStarVec.size() == degreeVec[i]);
00966         for(size_t j=delta;j<edgeStarVec.size();++j)
00967         {
00968           EdgeType *ep = edgeStarVec[j];
00969           int ind; // index of the vertex to be changed
00970           if(tri::Index(poly,ep->V(0)) == i) ind = 0;
00971               else ind = 1;
00972   
00973           ep->V(ind) = &*firstVi;
00974           ep->V(ind)->P() = poly.vert[i].P();
00975           ep->V(ind)->N() = poly.vert[i].N();
00976           ++firstVi;
00977         }
00978       }
00979     }
00980     assert(firstVi == poly.vert.end());
00981   }
00982   
00983   /*
00984    * Given a manifold edgemesh it returns the boundary/terminal endpoints.
00985    */
00986   static void FindTerminalPoints(MeshType &poly, std::vector<VertexType *> &vec)
00987   {
00988     tri::UpdateTopology<MeshType>::VertexEdge(poly);
00989     for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
00990     {
00991       if(edge::VEDegree<EdgeType>(&*vi)==1)
00992          vec.push_back(&*vi);
00993     }
00994   }
00995   
00996   // This function will decompose the input edge mesh into a set of 
00997   // connected components.
00998   // the vector will contain, for each connected component, a vector with all the edge indexes. 
00999   void BuildConnectedComponentVectors(MeshType &poly, std::vector< std::vector< int> > &ccVec)
01000   {
01001     UpdateTopology<MeshType>::VertexEdge(poly);
01002     for(size_t i=0;i<poly.vn;++i)
01003     {
01004       assert(edge::VEDegree<EdgeType>(&(poly.vert[i])) <=2);
01005     }
01006     
01007     tri::UpdateTopology<MeshType>::EdgeEdge(poly);
01008     tri::UpdateFlags<MeshType>::EdgeClearV(poly);
01009 
01010     int visitedEdgeNum=0 ;
01011     int ccCnt=0;
01012     EdgeIterator eIt = poly.edge.begin();  
01013     
01014     while(visitedEdgeNum < poly.en)
01015     {
01016       ccVec.resize(ccVec.size()+1);
01017       while(eIt->IsV()) ++eIt;
01018 //      printf("Starting component from edge %i\n",tri::Index(poly,&*eIt));
01019       assert(eIt != poly.edge.end());
01020       edge::Pos<EdgeType> startPos(&*eIt,0);
01021       edge::Pos<EdgeType> curPos(&*eIt,0);
01022       do
01023       {
01024 //        printf("(%i %i %i)-",tri::Index(poly,curPos.VFlip()), tri::Index(poly,curPos.E()) ,tri::Index(poly,curPos.V()));
01025         curPos.NextE();
01026       } 
01027       while(curPos!=startPos && !curPos.IsBorder()) ;
01028       
01029       curPos.FlipV();
01030       assert(!curPos.IsBorder());
01031       do
01032       {
01033 //         printf("<%i %i %i>-",tri::Index(poly,curPos.VFlip()), tri::Index(poly,curPos.E()) ,tri::Index(poly,curPos.V()));
01034         curPos.E()->SetV();
01035         visitedEdgeNum++;
01036         ccVec[ccCnt].push_back(tri::Index(poly,curPos.E()));        
01037         curPos.NextE();      
01038       } while(!curPos.E()->IsV());
01039       printf("Completed component %i of %i edges\n",ccCnt, ccVec[ccCnt].size());
01040       ccCnt++;      
01041     }    
01042   }
01043   
01044   // This function will decompose the input edge mesh into a set of 
01045   // connected components.
01046   // the vector will contain, for each connected component, a vector with all the edge indexes. 
01047   void BuildConnectedComponentVectorsOld(MeshType &poly, std::vector< std::vector< int> > &ccVec)
01048   {
01049     tri::UpdateTopology<MeshType>::EdgeEdge(poly);
01050     tri::UpdateTopology<MeshType>::VertexEdge(poly);
01051     tri::UpdateFlags<MeshType>::EdgeClearV(poly);
01052     
01053     int visitedEdgeNum=0 ;
01054     int ccCnt=0;
01055     
01056     EdgeIterator eIt = poly.edge.begin();  
01057     while(visitedEdgeNum < poly.en)
01058     {
01059       ccVec.resize(ccVec.size()+1);
01060       while((eIt != poly.edge.end()) && eIt->IsV()) ++eIt;
01061       EdgeType *startE = &*eIt;
01062       
01063       EdgeType *curEp = &*eIt;
01064       int     curEi = 0;
01065       printf("Starting Visit of connected Component %i from edge %i\n",ccCnt,tri::Index(poly,*eIt));
01066       while( (curEp->EEp(curEi) != startE) &&
01067              (curEp->EEp(curEi) != curEp) )
01068       {
01069         EdgeType *nextEp = curEp->EEp(curEi);
01070         int nextEi =  (curEp->EEi(curEi)+1)%2;
01071         curEp = nextEp;
01072         curEi = nextEi;
01073       }   
01074   
01075       curEp->SetV();
01076       curEi = (curEi +1)%2; // Flip the visit direction!
01077       visitedEdgeNum++;
01078       ccVec[ccCnt].push_back(tri::Index(poly,curEp));        
01079       while(! curEp->EEp(curEi)->IsV())
01080       {
01081         EdgeType *nextEp = curEp->EEp(curEi);
01082         int nextEi =  (curEp->EEi(curEi)+1)%2;
01083         curEp->SetV();
01084         curEp = nextEp;
01085         curEi = nextEi;
01086         curEp->V(curEi)->C() = Color4b::Scatter(30,ccCnt%30);
01087         if(!curEp->IsV()) {
01088           ccVec[ccCnt].push_back(tri::Index(poly,curEp));      
01089           visitedEdgeNum++;      
01090         }          
01091       }
01092       printf("Completed visit of component of size %i\n",ccVec[ccCnt].size());
01093       ccCnt++;    
01094     }
01095     printf("en %i - VisitedEdgeNum = %i\n",poly.en, visitedEdgeNum);
01096     
01097   }
01098   
01099   void ExtractSubMesh(MeshType &poly, std::vector<int> &ind, MeshType &subPoly)
01100   {
01101     subPoly.Clear();
01102     std::vector<int> remap(poly.vert.size(),-1);
01103     for(size_t i=0;i<ind.size();++i)
01104     {
01105       int v0 = tri::Index(poly,poly.edge[ind[i]].V(0));
01106       int v1 = tri::Index(poly,poly.edge[ind[i]].V(1));
01107       if(remap[v0]==-1) 
01108       {
01109         remap[v0]=subPoly.vn;
01110         tri::Allocator<MeshType>::AddVertex(subPoly,poly.vert[v0].P(),poly.vert[v0].N());      
01111       }
01112       if(remap[v1]==-1) 
01113       {
01114         remap[v1]=subPoly.vn;
01115         tri::Allocator<MeshType>::AddVertex(subPoly,poly.vert[v1].P(),poly.vert[v1].N());      
01116       }
01117       tri::Allocator<MeshType>::AddEdge(subPoly, &subPoly.vert[remap[v0]], &subPoly.vert[remap[v1]]);   
01118     }  
01119   }
01120   
01121   // It takes a vector of vector of connected components and cohorently reorient each one of them.
01122   // it usese the EE adjacency and requires that the input edgemesh is 1manifold. 
01123   
01124   void Reorient(MeshType &poly, std::vector< std::vector< int> > &ccVec)
01125   {
01126     UpdateTopology<MeshType>::VertexEdge(poly);
01127     for(size_t i=0;i<poly.vn;++i)
01128     {
01129       assert(edge::VEDegree<EdgeType>(&(poly.vert[i])) <=2);
01130     }
01131         UpdateTopology<MeshType>::EdgeEdge(poly);
01132     
01133     for(size_t i=0;i<ccVec.size();++i)
01134     {
01135       std::vector<bool> toFlipVec(ccVec[i].size(),false);
01136       
01137       for(int j=0;j<ccVec[i].size();++j)
01138       {
01139         EdgeType *cur  = & poly.edge[ccVec[i][j]];
01140         EdgeType *prev;
01141         if(j==0) 
01142         {
01143           if(cur->EEp(0) == cur) 
01144             prev = cur; // boundary
01145           else 
01146             prev = & poly.edge[ccVec[i].back()]; // cc is a loop
01147         }
01148         else prev = & poly.edge[ccVec[i][j-1]];
01149         
01150         if(cur->EEp(0) != prev)
01151         {
01152           toFlipVec[j] = true;
01153           assert(cur->EEp(1) == prev || j==0);
01154         }      
01155       }
01156       for(int j=0;j<ccVec[i].size();++j)
01157         if(toFlipVec[j]) 
01158           std::swap(poly.edge[ccVec[i][j]].V(0), poly.edge[ccVec[i][j]].V(1));    
01159     }
01160   }
01161   
01162   
01163   /*
01164    * Given a mesh and vector of vertex pointers it splits the mesh with the given points.
01165    * To avoid degeneracies it snaps the splitting points that came nearest than a given
01166    * threshold to the edge or the vertex of the closest triangle. When an input vertex
01167    * is snapped the passed vertex position is modiried accordingly
01168    * (this is the reason for having a vector of vertex pointers instead just a vector of points)
01169    *
01170    */
01171   void SplitMeshWithPoints(MeshType &m, std::vector<VertexType *> &vec, std::vector<int> &newVertVec)
01172   {
01173     int faceToAdd=0;
01174     int vertToAdd=0;
01175     
01176     // For each splitting point we save the index of the face to be splitten and the "kind" of split to do:
01177     // 3 -> means classical 1 to 3 face split
01178     // 2 -> means edge split.
01179     // 0 -> means no need of a split (e.g. the point is coincident with a vertex)
01180     
01181     std::vector< std::pair<int,int> > toSplitVec(vec.size(), std::make_pair(0,0));
01182     MeshGrid uniformGrid;
01183     uniformGrid.Set(m.face.begin(), m.face.end());
01184    
01185     for(size_t i =0; i<vec.size();++i)
01186     {
01187       Point3f newP = vec[i]->P();
01188       float closestDist;
01189       Point3f closestP;
01190       FaceType *f = vcg::tri::GetClosestFaceBase(m,uniformGrid,newP,par.gridBailout, closestDist, closestP);
01191       assert(f);
01192       VertexType *closestVp=0;
01193       ScalarType minDist = std::numeric_limits<ScalarType>::max();
01194       for(int i=0;i<3;++i) {
01195         if(Distance(newP,f->P(i))<minDist)
01196         {
01197           minDist = Distance(newP,f->P(i));
01198           closestVp = f->V(i);
01199         }
01200       }
01201       assert(closestVp);
01202       if(minDist < par.maxSnapThr)  {
01203            vec[i]->P() = closestVp->P();
01204       }
01205         else
01206       {
01207         toSplitVec[i].first = tri::Index(m,f);
01208         toSplitVec[i].second = 3;
01209         faceToAdd += 2;
01210         vertToAdd += 1;
01211       }
01212     }
01213 //    printf("Splitting with %i points: adding %i faces and %i vertices\n",vec.size(), faceToAdd,vertToAdd);
01214     FaceIterator newFi = tri::Allocator<MeshType>::AddFaces(m,faceToAdd);
01215     VertexIterator newVi = tri::Allocator<MeshType>::AddVertices(m,vertToAdd);
01216     
01217     tri::UpdateColor<MeshType>::PerFaceConstant(m,Color4b::White);
01218     
01219     for(size_t i =0; i<vec.size();++i)
01220     {
01221       if(toSplitVec[i].second==3)
01222       {        
01223         FaceType *fp0 = &m.face[toSplitVec[i].first];
01224         FaceType *fp1 = &*newFi; newFi++;
01225         FaceType *fp2 = &*newFi; newFi++;
01226         VertexType *vp = &*(newVi++);
01227         newVertVec.push_back(tri::Index(base,vp));
01228         vp->P() = vec[i]->P();
01229         VertexType *vp0 = fp0->V(0);
01230         VertexType *vp1 = fp0->V(1);
01231         VertexType *vp2 = fp0->V(2);
01232         
01233         fp0->V(0) = vp0; fp0->V(1) = vp1; fp0->V(2) = vp;
01234         fp1->V(0) = vp1; fp1->V(1) = vp2; fp1->V(2) = vp;
01235         fp2->V(0) = vp2; fp2->V(1) = vp0; fp2->V(2) = vp;
01236         
01237         fp0->C() = Color4b::Green;
01238         fp1->C() = Color4b::Green;
01239         fp2->C() = Color4b::Green;
01240       }
01241     }
01242   }
01243   
01244   
01245   void Init()
01246   {
01247     // Construction of the uniform grid
01248     uniformGrid.Set(base.face.begin(), base.face.end());
01249     UpdateNormal<MeshType>::PerFaceNormalized(base);
01250     UpdateTopology<MeshType>::FaceFace(base);    
01251     uniformGrid.Set(base.face.begin(), base.face.end());    
01252   }
01253   
01254   
01255   void Simplify( MeshType &poly)
01256   {
01257     int startEn = poly.en;
01258     Distribution<ScalarType> hist;
01259     for(int i =0; i<poly.en;++i) 
01260       hist.Add(edge::Length(poly.edge[i]));
01261         
01262     UpdateTopology<MeshType>::VertexEdge(poly);
01263     
01264     for(int i =0; i<poly.vn;++i)
01265     {
01266       std::vector<VertexPointer> starVecVp;
01267       edge::VVStarVE(&(poly.vert[i]),starVecVp);      
01268       if( (starVecVp.size()==2) && (!poly.vert[i].IsS()))
01269       {      
01270         float newSegLen = Distance(starVecVp[0]->P(), starVecVp[1]->P());
01271         Segment3f seg(starVecVp[0]->P(),starVecVp[1]->P());
01272         float segDist;
01273         Point3f closestPSeg;
01274         SegmentPointDistance(seg,poly.vert[i].cP(),closestPSeg,segDist);
01275         Point3f fp,fn;
01276         float maxSurfDist = MaxSegDist(starVecVp[0], starVecVp[1],fp,fn);
01277         
01278         if(maxSurfDist < par.surfDistThr && (newSegLen < par.maxSimpEdgeLen) )
01279         {
01280           edge::VEEdgeCollapse(poly,&(poly.vert[i]));
01281           
01282         }
01283       }
01284     }
01285     tri::UpdateTopology<MeshType>::TestVertexEdge(poly);
01286     tri::Allocator<MeshType>::CompactEveryVector(poly);
01287     tri::UpdateTopology<MeshType>::TestVertexEdge(poly);
01288     printf("Simplify %5i -> %5i (total len %5.2f)\n",startEn,poly.en,hist.Sum());
01289   }
01290   
01291   void EvaluateHausdorffDistance(MeshType &poly, Distribution<ScalarType> &dist)
01292   {
01293     dist.Clear();
01294     tri::UpdateTopology<MeshType>::VertexEdge(poly);
01295     tri::UpdateQuality<MeshType>::VertexConstant(poly,0);
01296     for(int i =0; i<poly.edge.size();++i)
01297     {      
01298       Point3f farthestP, farthestN;      
01299       float maxDist = MaxSegDist(poly.edge[i].V(0),poly.edge[i].V(1), farthestP, farthestN, &dist);      
01300       poly.edge[i].V(0)->Q()+= maxDist;
01301       poly.edge[i].V(1)->Q()+= maxDist;
01302     }
01303     for(int i=0;i<poly.vn;++i)
01304     {
01305       ScalarType deg = edge::VEDegree<EdgeType>(&poly.vert[i]);
01306       poly.vert[i].Q()/=deg;
01307     }
01308     tri::UpdateColor<MeshType>::PerVertexQualityRamp(poly,0,dist.Max());    
01309   }
01310   
01311   
01312   
01313   // Given a segment find the maximum distance from it to the original surface. 
01314   float MaxSegDist(VertexType *v0, VertexType *v1, Point3f &farthestPointOnSurf, Point3f &farthestN, Distribution<ScalarType> *dist=0)
01315   {
01316     float maxSurfDist = 0;
01317     const float sampleNum = 10;
01318     const float maxDist = base.bbox.Diag()/10.0;
01319     for(float k = 1;k<sampleNum;++k)
01320     {
01321       float surfDist;
01322       Point3f closestPSurf;
01323       Point3f samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;          
01324       FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,samplePnt,maxDist, surfDist, closestPSurf);        
01325       if(dist)
01326         dist->Add(surfDist);
01327       assert(f);
01328       if(surfDist > maxSurfDist)
01329       {
01330         maxSurfDist = surfDist;
01331         farthestPointOnSurf = closestPSurf;
01332         farthestN = f->N();
01333       }
01334     }
01335     return maxSurfDist;
01336   }
01337   
01338   void Refine(MeshType &poly, bool uniformFlag = false)
01339   {
01340     tri::Allocator<MeshType>::CompactEveryVector(poly);    
01341     int startEdgeSize = poly.en;
01342     for(int i =0; i<startEdgeSize;++i)
01343     {
01344       EdgeType &ei = poly.edge[i];
01345       if(edge::Length(ei)>par.minRefEdgeLen)  
01346       {      
01347         Point3f farthestP, farthestN;
01348         float maxDist = MaxSegDist(ei.V(0),ei.V(1),farthestP, farthestN);
01349         if(maxDist > par.surfDistThr)  
01350         {
01351           edge::VEEdgeSplit(poly, &ei, farthestP, farthestN); 
01352         }
01353         else if(uniformFlag)
01354         {
01355          edge::VEEdgeSplit(poly,&ei,(ei.P(0)+ei.P(1))/2.0,(ei.V(0)->N()+ei.V(1)->N())/2.0); 
01356         }
01357       }
01358     }
01359 //    tri::Allocator<MeshType>::CompactEveryVector(poly);
01360     printf("Refine %i -> %i\n",startEdgeSize,poly.en);fflush(stdout);
01361   }
01362   
01363   // Take a poly and find the position of edge -edge crossing.
01364   void RefineBaseMesh(MeshType &poly)
01365   {
01366     std::vector<CoordType> newPtVec;
01367     for(int i=0;i<poly.edge.size();++i)
01368     {
01369       {
01370         Point3f p0 = poly.edge[i].P(0);
01371         Point3f p1 = poly.edge[i].P(1);
01372         float stepNum = 10;
01373         FaceType *lastFace=0; 
01374         Point3f lastqp;
01375         Segment3f seg(p0, p1);        
01376         for(float j=1;j<stepNum;++j) 
01377         {
01378           Point3f qp = (p0*j + p1*(stepNum-j))/stepNum;
01379           const float maxDist = base.bbox.Diag()/20.0;
01380           float surfDist;
01381           Point3f closestPSurf, normSur, ip;
01382           FaceType *fp = vcg::tri::GetClosestFaceBase(base,uniformGrid,qp,maxDist, surfDist, closestPSurf, normSur, ip);                  
01383           if((fp != lastFace) && (lastFace!=0)  && (fp!=0)  )
01384           {
01385             for(int ei =0 ; ei<3;++ei)
01386             {
01387               if(fp->FFp(ei) == lastFace)
01388               {
01389                 Point3f ps0,ps1;
01390                 float segDist;
01391                 bool par;
01392                 Segment3f faceSeg(fp->P0(ei),fp->P1(ei));
01393                 float angDeg = fabs(math::ToDeg(Angle(faceSeg.Direction(),seg.Direction())));
01394                 
01395                 SegmentSegmentDistance(seg,faceSeg,segDist,par,ps0,ps1);
01396                 if(!par && (angDeg > 5 && angDeg<175)) newPtVec.push_back(ps1);             
01397               }
01398             }
01399           }
01400           lastFace=fp;        
01401           lastqp = qp;
01402         }
01403       }      
01404     }  
01405     MeshType meshPt; tri::BuildMeshFromCoordVector(meshPt,newPtVec);
01406     tri::io::ExporterPLY<MeshType>::Save(meshPt,"newPoints.ply");  
01407 
01408     VertexConstDataWrapper<MeshType > vdw(meshPt);
01409     KdTree<ScalarType> kdtree(vdw);
01410     
01411     EdgePointPred epPred(*this,kdtree);
01412     EdgePointSplit epSplit(*this,kdtree,meshPt);
01413     tri::UpdateTopology<MeshType>::FaceFace(base);
01414     tri::RefineE(base,epSplit,epPred);    
01415     tri::UpdateTopology<MeshType>::FaceFace(base);
01416     tri::io::ExporterPLY<MeshType>::Save(base,"newbase.ply");  
01417   }
01418   
01419   
01434   void SmoothProject(MeshType &poly, int iterNum, ScalarType smoothWeight, ScalarType projectWeight)
01435   {
01436     tri::RequireCompactness(poly);
01437     tri::UpdateTopology<MeshType>::VertexEdge(poly);
01438     printf("SmoothProject: Selected vert num %i\n",tri::UpdateSelection<MeshType>::VertexCount(poly));
01439     assert(poly.en>0 && base.fn>0);
01440     for(int k=0;k<iterNum;++k)
01441     {
01442       std::vector<Point3f> posVec(poly.vn,Point3f(0,0,0));
01443       std::vector<int>     cntVec(poly.vn,0);
01444   
01445       for(int i =0; i<poly.en;++i)
01446       {
01447         for(int j=0;j<2;++j)
01448         {
01449           int vertInd = tri::Index(poly,poly.edge[i].V(j));
01450           posVec[vertInd] += poly.edge[i].V1(j)->P();
01451           cntVec[vertInd] += 1;
01452         }
01453       }
01454       
01455       const float maxDist = base.bbox.Diag()/10.0;
01456       for(int i=0; i<poly.vn; ++i)
01457         if(!poly.vert[i].IsS())
01458         {
01459           Point3f smoothPos = (poly.vert[i].P() + posVec[i])/float(cntVec[i]+1);
01460           
01461           Point3f newP = poly.vert[i].P()*(1.0-smoothWeight) + smoothPos *smoothWeight;
01462           
01463           Point3f delta =  newP - poly.vert[i].P();
01464           if(delta.Norm() > par.maxSmoothDelta) 
01465           {
01466             newP =  poly.vert[i].P() + ( delta / delta.Norm()) * maxDist*0.5;
01467           }
01468           
01469           float minDist;
01470           Point3f closestP;
01471           FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,newP,maxDist, minDist, closestP);
01472           assert(f);
01473           poly.vert[i].P() = newP*(1.0-projectWeight) +closestP*projectWeight;
01474           poly.vert[i].N() = f->N();
01475         }
01476       
01477 //      Refine(poly);      
01478       tri::UpdateTopology<MeshType>::TestVertexEdge(poly);
01479     Refine(poly);      
01480       tri::UpdateTopology<MeshType>::TestVertexEdge(poly);
01481     Simplify(poly);
01482       tri::UpdateTopology<MeshType>::TestVertexEdge(poly);
01483       int dupVertNum = Clean<MeshType>::RemoveDuplicateVertex(poly);
01484       if(dupVertNum) {
01485         printf("****REMOVED %i Duplicated\n",dupVertNum);
01486         tri::Allocator<MeshType>::CompactEveryVector(poly);
01487         tri::UpdateTopology<MeshType>::VertexEdge(poly);
01488       }
01489     }
01490   }  
01491    
01492   
01493 };
01494 } // end namespace tri
01495 } // end namespace vcg
01496 
01497 #endif // __VCGLIB_CURVE_ON_SURF_H


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