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
43template <
class MeshType>
45 typedef typename MeshType::VertexType VertexType;
46 typedef typename MeshType::ScalarType ScalarType;
47 typedef typename MeshType::FacePointer FacePointer;
51 ScalarType operator()(
const VertexType * v0,
const VertexType * v1)
const
52 {
return vcg::Distance(v0->cP(),v1->cP());}
54 ScalarType operator()(
const FacePointer f0,
const FacePointer f1)
const
55 {
return vcg::Distance(Barycenter(*f0),Barycenter(*f1));}
59template <
class MeshType>
63 typename MeshType::template PerVertexAttributeHandle<float> wH;
65 typedef typename MeshType::VertexType VertexType;
66 typedef typename MeshType::ScalarType ScalarType;
67 typedef typename MeshType::FacePointer FacePointer;
79 float qmin = 1.0f/variance;
80 float qmax = variance;
81 float qrange = qmax-qmin;
82 std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
83 float range = minmax.second-minmax.first;
84 for(
size_t i=0;i<m.vert.size();++i)
85 wH[i]=qmin+((m.vert[i].Q()-minmax.first)/range)*qrange;
90 ScalarType operator()( VertexType * v0, VertexType * v1)
92 float scale = (wH[v0]+wH[v1])/2.0f;
93 return (1.0f/scale)*vcg::Distance(v0->cP(),v1->cP());
98template <
class MeshType>
102 typedef typename MeshType::VertexType VertexType;
104 typename MeshType::CoordType D1(VertexType &v) {
return v.PD1(); }
105 typename MeshType::CoordType D2(VertexType &v) {
return v.PD2(); }
116template <
class MeshType>
118 typedef typename MeshType::VertexType VertexType;
119 typedef typename MeshType::ScalarType ScalarType;
120 typedef typename MeshType::CoordType CoordType;
121 typedef typename MeshType::VertexIterator VertexIterator;
123 typename MeshType::template PerVertexAttributeHandle<CoordType> wxH,wyH;
130 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
137 ScalarType operator()( VertexType * v0, VertexType * v1)
139 CoordType dd = v0->cP()-v1->cP();
140 float x = (fabs(dd * wxH[v0])+fabs(dd *wxH[v1]))/2.0f;
141 float y = (fabs(dd * wyH[v0])+fabs(dd *wyH[v1]))/2.0f;
143 return sqrt(x*x+y*y);
174template <
class MeshType>
179 typedef typename MeshType::VertexType VertexType;
180 typedef typename MeshType::VertexIterator VertexIterator;
181 typedef typename MeshType::VertexPointer VertexPointer;
182 typedef typename MeshType::FacePointer FacePointer;
183 typedef typename MeshType::FaceType FaceType;
184 typedef typename MeshType::CoordType CoordType;
185 typedef typename MeshType::ScalarType ScalarType;
192 VertDist(VertexPointer _v, ScalarType _d):v(_v),d(_d){}
200 DIJKDist(VertexPointer _v):v(_v), q(_v->Q()){}
204 bool operator < (
const DIJKDist &o)
const
216 bool operator < (
const FaceDist &o)
const
218 if( f->Q() != o.f->Q())
219 return f->Q() > o.f->Q();
233 static int &_global_mark()
235 static int _global=1;
241 GeodData(
const ScalarType & __d):_d(__d),source(0),parent(0){}
243 const ScalarType d()
const {
247 return std::numeric_limits<ScalarType>::max();
250 void set_d(
const ScalarType &d){
255 VertexPointer source;
256 VertexPointer parent;
259 static void reset() { _global_mark()++;}
262 bool isMarked()
const {
return _local_mark==_global_mark();}
265 void mark() { _local_mark=_global_mark();}
272 return (v0.d > v1.d);
297 template <
class DistanceFunctor>
298 static ScalarType GeoDistance(DistanceFunctor &distFunc,
299 const VertexPointer &pw,
300 const VertexPointer &pw1,
301 const VertexPointer &curr,
302 const ScalarType &d_pw1,
303 const ScalarType &d_curr)
307 ScalarType ew_c = distFunc(pw,curr);
308 ScalarType ew_w1 = distFunc(pw,pw1);
309 ScalarType ec_w1 = distFunc(pw1,curr);
310 CoordType w_c = (pw->cP()-curr->cP()).Normalize() * ew_c;
311 CoordType w_w1 = (pw->cP() - pw1->cP()).Normalize() * ew_w1;
312 CoordType w1_c = (pw1->cP() - curr->cP()).Normalize() * ec_w1;
314 ScalarType alpha,alpha_, beta,beta_,theta,h,delta,s,a,b;
316 alpha = acos((w_c.dot(w1_c))/(ew_c*ec_w1));
317 s = (d_curr + d_pw1+ec_w1)/2;
320 alpha_ = 2*acos ( std::min<ScalarType>(1.0,sqrt( (b- a* d_pw1)/d_curr)));
322 if ( alpha+alpha_ > M_PI){
323 curr_d = d_curr + ew_c;
326 beta_ = 2*acos ( std::min<ScalarType>(1.0,sqrt( (b- a* d_curr)/d_pw1)));
327 beta = acos((w_w1).dot(-w1_c)/(ew_w1*ec_w1));
329 if ( beta+beta_ > M_PI)
330 curr_d = d_pw1 + ew_w1;
333 theta = ScalarType(M_PI)-alpha-alpha_;
334 delta = cos(theta)* ew_c;
335 h = sin(theta)* ew_c;
336 curr_d = sqrt( pow(h,2)+ pow(d_curr + delta,2));
374 template <
class DistanceFunctor>
377 std::vector<VertDist> & seedVec,
378 DistanceFunctor &distFunc,
379 ScalarType distance_threshold = std::numeric_limits<ScalarType>::max(),
380 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * vertSource = NULL,
381 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * vertParent = NULL,
382 std::vector<VertexPointer> *InInterval=NULL)
384 VertexPointer farthest=0;
386 tri::RequireVFAdjacency(m);
387 tri::RequirePerVertexQuality(m);
389 assert(!seedVec.empty());
395 std::vector<VertDist> frontierHeap;
396 typename std::vector <VertDist >::iterator ifr;
397 for(ifr = seedVec.begin(); ifr != seedVec.end(); ++ifr){
398 TD[(*ifr).v].set_d( (*ifr).d );
399 TD[(*ifr).v].source = (*ifr).v;
400 TD[(*ifr).v].parent = (*ifr).v;
401 frontierHeap.push_back(*ifr);
403 make_heap(frontierHeap.begin(),frontierHeap.end(),
pred());
405 ScalarType curr_d,d_curr = 0.0,d_heap;
406 ScalarType max_distance=0.0;
408 while(!frontierHeap.empty() && max_distance < distance_threshold)
410 pop_heap(frontierHeap.begin(),frontierHeap.end(),
pred());
411 VertexPointer curr = (frontierHeap.back()).v;
412 if (InInterval!=NULL) InInterval->push_back(curr);
414 if(vertSource!=NULL) (*vertSource)[curr] = TD[curr].source;
415 if(vertParent!=NULL) (*vertParent)[curr] = TD[curr].parent;
417 d_heap = (frontierHeap.back()).d;
418 frontierHeap.pop_back();
420 assert(TD[curr].d() <= d_heap);
421 if(TD[curr].d() < d_heap )
423 assert(TD[curr].d() == d_heap);
425 d_curr = TD[curr].d();
427 for(face::VFIterator<FaceType> vfi(curr) ; vfi.f!=0; ++vfi )
431 VertexPointer pw,pw1;
433 pw = vfi.f->V1(vfi.z);
434 pw1= vfi.f->V2(vfi.z);
437 pw = vfi.f->V2(vfi.z);
438 pw1= vfi.f->V1(vfi.z);
441 const ScalarType & d_pw1 = TD[pw1].d();
443 const ScalarType inter = distFunc(curr,pw1);
444 const ScalarType tol = (inter + d_curr + d_pw1)*.0001f;
446 if ( (TD[pw1].source != TD[curr].source)||
447 (inter + d_curr < d_pw1 +tol ) ||
448 (inter + d_pw1 < d_curr +tol ) ||
449 (d_curr + d_pw1 < inter +tol )
451 curr_d = d_curr + distFunc(pw,curr);
453 curr_d = GeoDistance(distFunc,pw,pw1,curr,d_pw1,d_curr);
456 if(TD[pw].d() > curr_d){
457 TD[pw].set_d( curr_d );
458 TD[pw].source = TD[curr].source;
459 TD[pw].parent = curr;
460 frontierHeap.push_back(
VertDist(pw,curr_d));
461 push_heap(frontierHeap.begin(),frontierHeap.end(),
pred());
464 if(d_curr > max_distance){
465 max_distance = d_curr;
474 if (InInterval==NULL)
476 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if(!(*vi).IsD())
477 (*vi).Q() = TD[&(*vi)].d();
481 assert(InInterval->size()>0);
482 for(
size_t i=0;i<InInterval->size();i++)
483 (*InInterval)[i]->Q() = TD[(*InInterval)[i]].d();
528 const std::vector<VertexPointer> & seedVec)
534 template <
class DistanceFunctor>
535 static bool Compute( MeshType & m,
536 const std::vector<VertexPointer> & seedVec,
537 DistanceFunctor &distFunc,
538 ScalarType maxDistanceThr = std::numeric_limits<ScalarType>::max(),
539 std::vector<VertexPointer> *withinDistanceVec=NULL,
540 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * sourceSeed = NULL,
541 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * parentSeed = NULL
544 if(seedVec.empty())
return false;
545 std::vector<VertDist> vdSeedVec;
546 typename std::vector<VertexPointer>::const_iterator fi;
547 for( fi = seedVec.begin(); fi != seedVec.end() ; ++fi)
548 vdSeedVec.push_back(VertDist(*fi,0.0));
549 Visit(m, vdSeedVec, distFunc, maxDistanceThr, sourceSeed, parentSeed, withinDistanceVec);
560 static bool DistanceFromBorder( MeshType & m,
typename MeshType::template PerVertexAttributeHandle<VertexPointer> * sources = NULL)
562 std::vector<VertexPointer> fro;
563 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
565 fro.push_back(&(*vi));
566 if(fro.empty())
return false;
567 EuclideanDistance<MeshType> dd;
569 return Compute(m,fro,dd,std::numeric_limits<ScalarType>::max(),0,sources);
573 static bool ConvertPerVertexSeedToPerFaceSeed(MeshType &m,
const std::vector<VertexPointer> &vertexSeedVec,
574 std::vector<FacePointer> &faceSeedVec)
576 tri::RequireVFAdjacency(m);
577 tri::RequirePerFaceMark(m);
581 for(
size_t i=0;i<vertexSeedVec.size();++i)
583 for(face::VFIterator<FaceType> vfi(vertexSeedVec[i]);!vfi.End();++vfi)
585 if(tri::IsMarked(m,vfi.F()))
return false;
586 faceSeedVec.push_back(vfi.F());
587 tri::Mark(m,vfi.F());
593 static inline std::string sourcesAttributeName(
void) {
return "sources"; }
594 static inline std::string parentsAttributeName(
void) {
return "parent"; }
596 template <
class DistanceFunctor>
597 static void PerFaceDijkstraCompute(MeshType &m,
const std::vector<FacePointer> &seedVec,
598 DistanceFunctor &distFunc,
599 ScalarType maxDistanceThr = std::numeric_limits<ScalarType>::max(),
600 std::vector<FacePointer> *InInterval=NULL,
601 FacePointer FaceTarget=NULL,
602 bool avoid_selected=
false)
604 tri::RequireFFAdjacency(m);
605 tri::RequirePerFaceMark(m);
606 tri::RequirePerFaceQuality(m);
608 typename MeshType::template PerFaceAttributeHandle<FacePointer> sourceHandle
609 = tri::Allocator<MeshType>::template GetPerFaceAttribute<FacePointer>(m, sourcesAttributeName());
611 typename MeshType::template PerFaceAttributeHandle<FacePointer> parentHandle
612 = tri::Allocator<MeshType>::template GetPerFaceAttribute<FacePointer>(m, parentsAttributeName());
614 std::vector<FaceDist> Heap;
616 for(
size_t i=0;i<seedVec.size();++i)
618 tri::Mark(m,seedVec[i]);
620 sourceHandle[seedVec[i]]=seedVec[i];
621 parentHandle[seedVec[i]]=seedVec[i];
622 Heap.push_back(FaceDist(seedVec[i]));
623 if (InInterval!=NULL) InInterval->push_back(seedVec[i]);
626 std::make_heap(Heap.begin(),Heap.end());
629 pop_heap(Heap.begin(),Heap.end());
630 FacePointer curr = (Heap.back()).f;
631 if ((FaceTarget!=NULL)&&(curr==FaceTarget))
return;
638 FacePointer nextF = curr->FFp(i);
639 ScalarType nextDist = curr->Q() + distFunc(curr,nextF);
640 if( (nextDist < maxDistanceThr) &&
641 (!tri::IsMarked(m,nextF) || nextDist < nextF->Q()) )
643 nextF->Q() = nextDist;
644 if ((avoid_selected)&&(nextF->IsS()))
continue;
646 Heap.push_back(FaceDist(nextF));
647 push_heap(Heap.begin(),Heap.end());
648 if (InInterval!=NULL) InInterval->push_back(nextF);
649 sourceHandle[nextF] = sourceHandle[curr];
650 parentHandle[nextF] = curr;
661 template <
class DistanceFunctor>
662 static void PerVertexDijkstraCompute(MeshType &m,
const std::vector<VertexPointer> &seedVec,
663 DistanceFunctor &distFunc,
664 ScalarType maxDistanceThr = std::numeric_limits<ScalarType>::max(),
665 std::vector<VertexPointer> *InInterval=NULL,
666 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * sourceHandle= NULL,
667 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * parentHandle=NULL,
668 bool avoid_selected=
false,
669 VertexPointer target=NULL)
671 tri::RequireVFAdjacency(m);
672 tri::RequirePerVertexMark(m);
673 tri::RequirePerVertexQuality(m);
675 std::vector<DIJKDist> Heap;
678 for(
size_t i=0;i<seedVec.size();++i)
680 assert(!tri::IsMarked(m,seedVec[i]));
681 tri::Mark(m,seedVec[i]);
683 if (sourceHandle!=NULL)
684 (*sourceHandle)[seedVec[i]]=seedVec[i];
685 if (parentHandle!=NULL)
686 (*parentHandle)[seedVec[i]]=seedVec[i];
687 Heap.push_back(DIJKDist(seedVec[i]));
688 if (InInterval!=NULL) InInterval->push_back(seedVec[i]);
691 std::make_heap(Heap.begin(),Heap.end());
694 pop_heap(Heap.begin(),Heap.end());
695 VertexPointer curr = (Heap.back()).v;
696 if ((target!=NULL)&&(target==curr))
return;
698 std::vector<VertexPointer> vertVec;
699 face::VVStarVF<FaceType>(curr,vertVec);
700 for(
size_t i=0;i<vertVec.size();++i)
702 VertexPointer nextV = vertVec[i];
703 if ((avoid_selected)&&(nextV->IsS()))
continue;
704 ScalarType nextDist = curr->Q() + distFunc(curr,nextV);
705 if( (nextDist < maxDistanceThr) &&
706 (!tri::IsMarked(m,nextV) || nextDist < nextV->Q()) )
708 nextV->Q() = nextDist;
710 Heap.push_back(DIJKDist(nextV));
711 push_heap(Heap.begin(),Heap.end());
712 if (InInterval!=NULL) InInterval->push_back(nextV);
713 if (sourceHandle!=NULL)
714 (*sourceHandle)[nextV] = (*sourceHandle)[curr];
715 if (parentHandle!=NULL)
716 (*parentHandle)[nextV] = curr;
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
Definition: geodesic.h:117
Definition: geodesic.h:228
Class for computing approximate geodesic distances on a mesh.
Definition: geodesic.h:175
static bool Compute(MeshType &m, const std::vector< VertexPointer > &seedVec)
High-level wrapper: compute approximate geodesic distances from seeds.
Definition: geodesic.h:527
static VertexPointer Visit(MeshType &m, std::vector< VertDist > &seedVec, DistanceFunctor &distFunc, ScalarType distance_threshold=std::numeric_limits< ScalarType >::max(), typename MeshType::template PerVertexAttributeHandle< VertexPointer > *vertSource=NULL, typename MeshType::template PerVertexAttributeHandle< VertexPointer > *vertParent=NULL, std::vector< VertexPointer > *InInterval=NULL)
Definition: geodesic.h:375
Definition: geodesic.h:60
IsotropicDistance(MeshType &m, float variance)
Definition: geodesic.h:75
static void VertexConstant(MeshType &m, VertexQualityType q)
Definition: quality.h:67
bool IsBorder(FaceType const &f, const int j)
Definition: topology.h:55
Definition: geodesic.h:100
Definition: geodesic.h:44
Definition: geodesic.h:199
Definition: geodesic.h:213
Definition: geodesic.h:190
Definition: geodesic.h:269