00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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;
00076 ScalarType polyDistThr;
00077 ScalarType minRefEdgeLen;
00078 ScalarType maxSimpEdgeLen;
00079 ScalarType maxSmoothDelta;
00080 ScalarType maxSnapThr;
00081 ScalarType gridBailout;
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
00108
00109 MeshType &base;
00110 MeshGrid uniformGrid;
00111
00112 Param par;
00113 CoM(MeshType &_m) :base(_m),par(_m){}
00114
00115
00116
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
00137
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
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
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)
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
00321
00322
00323
00324
00325
00326
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;
00334
00335
00336 MeshType treeMesh;
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
00374
00375
00376
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
00458
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
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
00494
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
00559 nv.P()=closestP;
00560 nv.Q()=0;
00561 newVertVec.push_back(tri::Index(com.base,&nv));
00562
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
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
00702
00703
00704
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
00735
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
00764
00765
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
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
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
00851
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
00862
00863
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) {
00906 vi->P() = closestVp->P();
00907 vertSnapCnt++;
00908 if(newVertVec)
00909 newVertVec->push_back(tri::Index(base,closestVp));
00910 } else {
00911 if(minIp < interpEps) {
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
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
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;
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
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
00997
00998
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
01019 assert(eIt != poly.edge.end());
01020 edge::Pos<EdgeType> startPos(&*eIt,0);
01021 edge::Pos<EdgeType> curPos(&*eIt,0);
01022 do
01023 {
01024
01025 curPos.NextE();
01026 }
01027 while(curPos!=startPos && !curPos.IsBorder()) ;
01028
01029 curPos.FlipV();
01030 assert(!curPos.IsBorder());
01031 do
01032 {
01033
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
01045
01046
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;
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
01122
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;
01145 else
01146 prev = & poly.edge[ccVec[i].back()];
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
01165
01166
01167
01168
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
01177
01178
01179
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
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
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
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
01360 printf("Refine %i -> %i\n",startEdgeSize,poly.en);fflush(stdout);
01361 }
01362
01363
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
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 }
01495 }
01496
01497 #endif // __VCGLIB_CURVE_ON_SURF_H