23 #include <vcg/simplex/face/pos.h>
24 #include <vcg/simplex/face/topology.h>
25 #include <vcg/complex/algorithms/update/quality.h>
28 #ifndef __VCGLIB_GEODESIC
29 #define __VCGLIB_GEODESIC
34 template <
class MeshType>
36 typedef typename MeshType::VertexType VertexType;
37 typedef typename MeshType::ScalarType ScalarType;
38 typedef typename MeshType::FacePointer FacePointer;
42 ScalarType operator()(
const VertexType * v0,
const VertexType * v1)
const
43 {
return vcg::Distance(v0->cP(),v1->cP());}
45 ScalarType operator()(
const FacePointer f0,
const FacePointer f1)
const
46 {
return vcg::Distance(Barycenter(*f0),Barycenter(*f1));}
50 template <
class MeshType>
54 typename MeshType::template PerVertexAttributeHandle<float> wH;
56 typedef typename MeshType::VertexType VertexType;
57 typedef typename MeshType::ScalarType ScalarType;
58 typedef typename MeshType::FacePointer FacePointer;
70 float qmin = 1.0f/variance;
71 float qmax = variance;
72 float qrange = qmax-qmin;
73 std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
74 float range = minmax.second-minmax.first;
75 for(
size_t i=0;i<m.vert.size();++i)
76 wH[i]=qmin+((m.vert[i].Q()-minmax.first)/range)*qrange;
81 ScalarType operator()( VertexType * v0, VertexType * v1)
83 float scale = (wH[v0]+wH[v1])/2.0f;
84 return (1.0f/scale)*vcg::Distance(v0->cP(),v1->cP());
89 template <
class MeshType>
93 typedef typename MeshType::VertexType VertexType;
95 typename MeshType::CoordType D1(VertexType &v) {
return v.PD1(); }
96 typename MeshType::CoordType D2(VertexType &v) {
return v.PD2(); }
107 template <
class MeshType>
109 typedef typename MeshType::VertexType VertexType;
110 typedef typename MeshType::ScalarType ScalarType;
111 typedef typename MeshType::CoordType CoordType;
112 typedef typename MeshType::VertexIterator VertexIterator;
114 typename MeshType::template PerVertexAttributeHandle<CoordType> wxH,wyH;
121 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
128 ScalarType operator()( VertexType * v0, VertexType * v1)
130 CoordType dd = v0->cP()-v1->cP();
131 float x = (fabs(dd * wxH[v0])+fabs(dd *wxH[v1]))/2.0f;
132 float y = (fabs(dd * wyH[v0])+fabs(dd *wyH[v1]))/2.0f;
134 return sqrt(x*x+y*y);
147 template <
class MeshType>
152 typedef typename MeshType::VertexType VertexType;
153 typedef typename MeshType::VertexIterator VertexIterator;
154 typedef typename MeshType::VertexPointer VertexPointer;
155 typedef typename MeshType::FacePointer FacePointer;
156 typedef typename MeshType::FaceType FaceType;
157 typedef typename MeshType::CoordType CoordType;
158 typedef typename MeshType::ScalarType ScalarType;
165 VertDist(VertexPointer _v, ScalarType _d):v(_v),d(_d){}
173 DIJKDist(VertexPointer _v):v(_v), q(_v->Q()){}
177 bool operator < (
const DIJKDist &o)
const
189 bool operator < (
const FaceDist &o)
const
191 if( f->Q() != o.f->Q())
192 return f->Q() > o.f->Q();
200 TempData(
const ScalarType & _d):d(_d),source(0),parent(0){}
203 VertexPointer source;
204 VertexPointer parent;
207 typedef SimpleTempData<std::vector<VertexType>,
TempData > TempDataType;
213 return (v0.d > v1.d);
238 template <
class DistanceFunctor>
239 static ScalarType Distance(DistanceFunctor &distFunc,
240 const VertexPointer &pw,
241 const VertexPointer &pw1,
242 const VertexPointer &curr,
243 const ScalarType &d_pw1,
244 const ScalarType &d_curr)
248 ScalarType ew_c = distFunc(pw,curr);
249 ScalarType ew_w1 = distFunc(pw,pw1);
250 ScalarType ec_w1 = distFunc(pw1,curr);
251 CoordType w_c = (pw->cP()-curr->cP()).Normalize() * ew_c;
252 CoordType w_w1 = (pw->cP() - pw1->cP()).Normalize() * ew_w1;
253 CoordType w1_c = (pw1->cP() - curr->cP()).Normalize() * ec_w1;
255 ScalarType alpha,alpha_, beta,beta_,theta,h,delta,s,a,b;
257 alpha = acos((w_c.dot(w1_c))/(ew_c*ec_w1));
258 s = (d_curr + d_pw1+ec_w1)/2;
261 alpha_ = 2*acos ( std::min<ScalarType>(1.0,sqrt( (b- a* d_pw1)/d_curr)));
263 if ( alpha+alpha_ > M_PI){
264 curr_d = d_curr + ew_c;
267 beta_ = 2*acos ( std::min<ScalarType>(1.0,sqrt( (b- a* d_curr)/d_pw1)));
268 beta = acos((w_w1).dot(-w1_c)/(ew_w1*ec_w1));
270 if ( beta+beta_ > M_PI)
271 curr_d = d_pw1 + ew_w1;
274 theta = ScalarType(M_PI)-alpha-alpha_;
275 delta = cos(theta)* ew_c;
276 h = sin(theta)* ew_c;
277 curr_d = sqrt( pow(h,2)+ pow(d_curr + delta,2));
294 template <
class DistanceFunctor>
295 static VertexPointer Visit(
297 std::vector<VertDist> & seedVec,
298 DistanceFunctor &distFunc,
299 ScalarType distance_threshold = std::numeric_limits<ScalarType>::max(),
300 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * vertSource = NULL,
301 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * vertParent = NULL,
302 std::vector<VertexPointer> *InInterval=NULL)
304 VertexPointer farthest=0;
307 tri::RequireVFAdjacency(m);
308 tri::RequirePerVertexQuality(m);
310 assert(!seedVec.empty());
312 TempDataType TD(m.vert, std::numeric_limits<ScalarType>::max());
315 std::vector<VertDist> frontierHeap;
316 typename std::vector <VertDist >::iterator ifr;
317 for(ifr = seedVec.begin(); ifr != seedVec.end(); ++ifr){
318 TD[(*ifr).v].d = (*ifr).d;
319 TD[(*ifr).v].source = (*ifr).v;
320 TD[(*ifr).v].parent = (*ifr).v;
321 frontierHeap.push_back(*ifr);
323 make_heap(frontierHeap.begin(),frontierHeap.end(),pred());
325 ScalarType curr_d,d_curr = 0.0,d_heap;
326 ScalarType max_distance=0.0;
328 while(!frontierHeap.empty() && max_distance < distance_threshold)
330 pop_heap(frontierHeap.begin(),frontierHeap.end(),pred());
331 VertexPointer curr = (frontierHeap.back()).v;
332 if (InInterval!=NULL) InInterval->push_back(curr);
334 if(vertSource!=NULL) (*vertSource)[curr] = TD[curr].source;
335 if(vertParent!=NULL) (*vertParent)[curr] = TD[curr].parent;
337 d_heap = (frontierHeap.back()).d;
338 frontierHeap.pop_back();
340 assert(TD[curr].d <= d_heap);
341 if(TD[curr].d < d_heap )
343 assert(TD[curr].d == d_heap);
347 for(face::VFIterator<FaceType> vfi(curr) ; vfi.f!=0; ++vfi )
351 VertexPointer pw,pw1;
353 pw = vfi.f->V1(vfi.z);
354 pw1= vfi.f->V2(vfi.z);
357 pw = vfi.f->V2(vfi.z);
358 pw1= vfi.f->V1(vfi.z);
361 const ScalarType & d_pw1 = TD[pw1].d;
363 const ScalarType inter = distFunc(curr,pw1);
364 const ScalarType tol = (inter + d_curr + d_pw1)*.0001f;
366 if ( (TD[pw1].source != TD[curr].source)||
367 (inter + d_curr < d_pw1 +tol ) ||
368 (inter + d_pw1 < d_curr +tol ) ||
369 (d_curr + d_pw1 < inter +tol )
371 curr_d = d_curr + distFunc(pw,curr);
373 curr_d = Distance(distFunc,pw,pw1,curr,d_pw1,d_curr);
376 if(TD[pw].d > curr_d){
378 TD[pw].source = TD[curr].source;
379 TD[pw].parent = curr;
380 frontierHeap.push_back(VertDist(pw,curr_d));
381 push_heap(frontierHeap.begin(),frontierHeap.end(),pred());
384 if(d_curr > max_distance){
385 max_distance = d_curr;
395 if (InInterval==NULL)
397 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if(!(*vi).IsD())
398 (*vi).Q() = TD[&(*vi)].d;
402 assert(InInterval->size()>0);
403 for(
size_t i=0;i<InInterval->size();i++)
404 (*InInterval)[i]->Q() = TD[(*InInterval)[i]].d;
444 const std::vector<VertexPointer> & seedVec)
450 template <
class DistanceFunctor>
451 static bool Compute( MeshType & m,
452 const std::vector<VertexPointer> & seedVec,
453 DistanceFunctor &distFunc,
454 ScalarType maxDistanceThr = std::numeric_limits<ScalarType>::max(),
455 std::vector<VertexPointer> *withinDistanceVec=NULL,
456 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * sourceSeed = NULL,
457 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * parentSeed = NULL
460 if(seedVec.empty())
return false;
461 std::vector<VertDist> vdSeedVec;
462 typename std::vector<VertexPointer>::const_iterator fi;
463 for( fi = seedVec.begin(); fi != seedVec.end() ; ++fi)
464 vdSeedVec.push_back(VertDist(*fi,0.0));
465 Visit(m, vdSeedVec, distFunc, maxDistanceThr, sourceSeed, parentSeed, withinDistanceVec);
476 static bool DistanceFromBorder( MeshType & m,
typename MeshType::template PerVertexAttributeHandle<VertexPointer> * sources = NULL)
478 std::vector<VertexPointer> fro;
479 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
481 fro.push_back(&(*vi));
482 if(fro.empty())
return false;
483 EuclideanDistance<MeshType> dd;
485 return Compute(m,fro,dd,std::numeric_limits<ScalarType>::max(),0,sources);
489 static bool ConvertPerVertexSeedToPerFaceSeed(MeshType &m,
const std::vector<VertexPointer> &vertexSeedVec,
490 std::vector<FacePointer> &faceSeedVec)
492 tri::RequireVFAdjacency(m);
493 tri::RequirePerFaceMark(m);
497 for(
size_t i=0;i<vertexSeedVec.size();++i)
499 for(face::VFIterator<FaceType> vfi(vertexSeedVec[i]);!vfi.End();++vfi)
501 if(tri::IsMarked(m,vfi.F()))
return false;
502 faceSeedVec.push_back(vfi.F());
503 tri::Mark(m,vfi.F());
509 static inline std::string sourcesAttributeName(
void) {
return "sources"; }
510 static inline std::string parentsAttributeName(
void) {
return "parent"; }
512 template <
class DistanceFunctor>
513 static void PerFaceDijkstraCompute(MeshType &m,
const std::vector<FacePointer> &seedVec,
514 DistanceFunctor &distFunc,
515 ScalarType maxDistanceThr = std::numeric_limits<ScalarType>::max(),
516 std::vector<FacePointer> *InInterval=NULL,
517 FacePointer FaceTarget=NULL,
518 bool avoid_selected=
false)
520 tri::RequireFFAdjacency(m);
521 tri::RequirePerFaceMark(m);
522 tri::RequirePerFaceQuality(m);
524 typename MeshType::template PerFaceAttributeHandle<FacePointer> sourceHandle
525 = tri::Allocator<MeshType>::template GetPerFaceAttribute<FacePointer>(m, sourcesAttributeName());
527 typename MeshType::template PerFaceAttributeHandle<FacePointer> parentHandle
528 = tri::Allocator<MeshType>::template GetPerFaceAttribute<FacePointer>(m, parentsAttributeName());
530 std::vector<FaceDist> Heap;
532 for(
size_t i=0;i<seedVec.size();++i)
534 tri::Mark(m,seedVec[i]);
536 sourceHandle[seedVec[i]]=seedVec[i];
537 parentHandle[seedVec[i]]=seedVec[i];
538 Heap.push_back(FaceDist(seedVec[i]));
539 if (InInterval!=NULL) InInterval->push_back(seedVec[i]);
542 std::make_heap(Heap.begin(),Heap.end());
545 pop_heap(Heap.begin(),Heap.end());
546 FacePointer curr = (Heap.back()).f;
547 if ((FaceTarget!=NULL)&&(curr==FaceTarget))
return;
554 FacePointer nextF = curr->FFp(i);
555 ScalarType nextDist = curr->Q() + distFunc(curr,nextF);
556 if( (nextDist < maxDistanceThr) &&
557 (!tri::IsMarked(m,nextF) || nextDist < nextF->Q()) )
559 nextF->Q() = nextDist;
560 if ((avoid_selected)&&(nextF->IsS()))
continue;
562 Heap.push_back(FaceDist(nextF));
563 push_heap(Heap.begin(),Heap.end());
564 if (InInterval!=NULL) InInterval->push_back(nextF);
565 sourceHandle[nextF] = sourceHandle[curr];
566 parentHandle[nextF] = curr;
577 template <
class DistanceFunctor>
578 static void PerVertexDijkstraCompute(MeshType &m,
const std::vector<VertexPointer> &seedVec,
579 DistanceFunctor &distFunc,
580 ScalarType maxDistanceThr = std::numeric_limits<ScalarType>::max(),
581 std::vector<VertexPointer> *InInterval=NULL,
582 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * sourceHandle= NULL,
583 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * parentHandle=NULL,
584 bool avoid_selected=
false,
585 VertexPointer target=NULL)
587 tri::RequireVFAdjacency(m);
588 tri::RequirePerVertexMark(m);
589 tri::RequirePerVertexQuality(m);
591 std::vector<DIJKDist> Heap;
594 for(
size_t i=0;i<seedVec.size();++i)
596 assert(!tri::IsMarked(m,seedVec[i]));
597 tri::Mark(m,seedVec[i]);
599 if (sourceHandle!=NULL)
600 (*sourceHandle)[seedVec[i]]=seedVec[i];
601 if (parentHandle!=NULL)
602 (*parentHandle)[seedVec[i]]=seedVec[i];
603 Heap.push_back(DIJKDist(seedVec[i]));
604 if (InInterval!=NULL) InInterval->push_back(seedVec[i]);
607 std::make_heap(Heap.begin(),Heap.end());
610 pop_heap(Heap.begin(),Heap.end());
611 VertexPointer curr = (Heap.back()).v;
612 if ((target!=NULL)&&(target==curr))
return;
614 std::vector<VertexPointer> vertVec;
615 face::VVStarVF<FaceType>(curr,vertVec);
616 for(
size_t i=0;i<vertVec.size();++i)
618 VertexPointer nextV = vertVec[i];
619 if ((avoid_selected)&&(nextV->IsS()))
continue;
620 ScalarType nextDist = curr->Q() + distFunc(curr,nextV);
621 if( (nextDist < maxDistanceThr) &&
622 (!tri::IsMarked(m,nextV) || nextDist < nextV->Q()) )
624 nextV->Q() = nextDist;
626 Heap.push_back(DIJKDist(nextV));
627 push_heap(Heap.begin(),Heap.end());
628 if (InInterval!=NULL) InInterval->push_back(nextV);
629 if (sourceHandle!=NULL)
630 (*sourceHandle)[nextV] = (*sourceHandle)[curr];
631 if (parentHandle!=NULL)
632 (*parentHandle)[nextV] = curr;
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
Definition: geodesic.h:108
class for computing approximate geodesic distances on a mesh
Definition: geodesic.h:148
static bool Compute(MeshType &m, const std::vector< VertexPointer > &seedVec)
Given a set of source vertices compute the approximate geodesic distance to all the other vertices.
Definition: geodesic.h:443
Definition: geodesic.h:51
IsotropicDistance(MeshType &m, float variance)
Definition: geodesic.h:66
static void VertexConstant(MeshType &m, VertexQualityType q)
Definition: quality.h:67
bool IsBorder(FaceType const &f, const int j)
Definition: topology.h:55
Definition: namespaces.dox:6
Definition: geodesic.h:91
Definition: geodesic.h:35
Definition: geodesic.h:172
Definition: geodesic.h:186
Definition: geodesic.h:198
Definition: geodesic.h:163
Definition: geodesic.h:210