VCG Library
Loading...
Searching...
No Matches
geodesic.h
1/****************************************************************************
2* VCGLib o o *
3* Visual and Computer Graphics Library o o *
4* _ O _ *
5* Copyright(C) 2004-2016 \/)\/ *
6* Visual Computing Lab /\/| *
7* ISTI - Italian National Research Council | *
8* \ *
9* All rights reserved. *
10* *
11* This program is free software; you can redistribute it and/or modify *
12* it under the terms of the GNU General Public License as published by *
13* the Free Software Foundation; either version 2 of the License, or *
14* (at your option) any later version. *
15* *
16* This program is distributed in the hope that it will be useful, *
17* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20* for more details. *
21* *
22****************************************************************************/
23#include <vcg/simplex/face/pos.h>
24#include <vcg/simplex/face/topology.h>
25#include <vcg/complex/algorithms/update/quality.h>
26#include <deque>
27#include <functional>
28#ifndef __VCGLIB_GEODESIC
29#define __VCGLIB_GEODESIC
30
31namespace vcg{
32namespace tri{
33
34// Distance Functors
35// Geodesic distance can be compute according different distances functors on the mesh in order
36// to bias the distance computation for the edges of the mesh.
37//
38// EuclideanDistance: the distance is just the euclidean distance between the two vertexes
39// IsotropicDistance: the distance is the euclidean distance scaled by the quality of the vertexes
40// AnisotropicDistance: the distance is the euclidean distance scaled by a given tangential cross field
41
42
43template <class MeshType>
45 typedef typename MeshType::VertexType VertexType;
46 typedef typename MeshType::ScalarType ScalarType;
47 typedef typename MeshType::FacePointer FacePointer;
48
50
51 ScalarType operator()(const VertexType * v0, const VertexType * v1) const
52 {return vcg::Distance(v0->cP(),v1->cP());}
53
54 ScalarType operator()(const FacePointer f0, const FacePointer f1) const
55 {return vcg::Distance(Barycenter(*f0),Barycenter(*f1));}
56};
57
58
59template <class MeshType>
61private:
62 // The only member of this class. The attribute handle used to
63 typename MeshType::template PerVertexAttributeHandle<float> wH;
64public:
65 typedef typename MeshType::VertexType VertexType;
66 typedef typename MeshType::ScalarType ScalarType;
67 typedef typename MeshType::FacePointer FacePointer;
68
74
75 IsotropicDistance(MeshType &m, float variance)
76 {
77 // the wH attribute store the scaling factor to be applied to the distance
78 wH = tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (m,"distW");
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;
86
87// qDebug("Range %f %f %f",minmax.first,minmax.second,range);
88 }
89
90 ScalarType operator()( VertexType * v0, VertexType * v1)
91 {
92 float scale = (wH[v0]+wH[v1])/2.0f;
93 return (1.0f/scale)*vcg::Distance(v0->cP(),v1->cP());
94 }
95};
96
97
98template <class MeshType>
100{
101 BasicCrossFunctor(MeshType &m) { tri::RequirePerVertexCurvatureDir(m); }
102 typedef typename MeshType::VertexType VertexType;
103
104 typename MeshType::CoordType D1(VertexType &v) { return v.PD1(); }
105 typename MeshType::CoordType D2(VertexType &v) { return v.PD2(); }
106};
107
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;
122
123 typename MeshType::template PerVertexAttributeHandle<CoordType> wxH,wyH;
124public:
125 template <class CrossFunctor > AnisotropicDistance(MeshType &m, CrossFunctor &cf)
126 {
127 wxH = tri::Allocator<MeshType>:: template GetPerVertexAttribute<CoordType> (m,"distDirX");
128 wyH = tri::Allocator<MeshType>:: template GetPerVertexAttribute<CoordType> (m,"distDirY");
129
130 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
131 {
132 wxH[vi]=cf.D1(*vi);
133 wyH[vi]=cf.D2(*vi);
134 }
135 }
136
137 ScalarType operator()( VertexType * v0, VertexType * v1)
138 {
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;
142
143 return sqrt(x*x+y*y);
144 }
145};
146
147
148
149
174template <class MeshType>
176
177public:
178
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;
186
187
188
189/* Auxiliary class for keeping the heap of vertices to visit and their estimated distance */
190 struct VertDist{
191 VertDist(){}
192 VertDist(VertexPointer _v, ScalarType _d):v(_v),d(_d){}
193
194 VertexPointer v;
195 ScalarType d;
196 };
197
198
199 struct DIJKDist{
200 DIJKDist(VertexPointer _v):v(_v), q(_v->Q()){}
201 VertexPointer v;
202 ScalarType q;
203
204 bool operator < (const DIJKDist &o) const
205 {
206 if( q != o.q)
207 return q > o.q;
208 return v<o.v;
209 }
210 };
211
212 /* Auxiliary class for keeping the heap of vertices to visit and their estimated distance */
213 struct FaceDist{
214 FaceDist(FacePointer _f):f(_f){}
215 FacePointer f;
216 bool operator < (const FaceDist &o) const
217 {
218 if( f->Q() != o.f->Q())
219 return f->Q() > o.f->Q();
220 return f<o.f;
221 }
222 };
223
224 /* Temporary Geodesic Data to associate to all the vertices
225 * it uses a mailbox marking strategy (constant unmarking time)
226 * to allow quick restart of multiple geodesic visits over a mesh
227 */
228 class GeodData{
229 private:
230 ScalarType _d;
231 int _local_mark=0;
232
233 static int &_global_mark()
234 {
235 static int _global=1;
236 return _global;
237 }
238
239 public:
240 GeodData(){}
241 GeodData(const ScalarType & __d):_d(__d),source(0),parent(0){}
242
243 const ScalarType d() const {
244 if(isMarked())
245 return _d;
246 else
247 return std::numeric_limits<ScalarType>::max();
248 }
249
250 void set_d(const ScalarType &d){
251 mark();
252 _d=d;
253 }
254
255 VertexPointer source; // Pointer to the vertex that is the closest source
256 VertexPointer parent; // Pointer to the next one in the chain going to the closest.
257
258 // Constant time unmarking;
259 static void reset() { _global_mark()++;}
260
261 // A vertex is marked only if its local copy of the mark value is equal to the global one
262 bool isMarked() const {return _local_mark==_global_mark();}
263
264 // A vertex is marked only if its local copy of the mark value is equal to the global one
265 void mark() { _local_mark=_global_mark();}
266 };
267
268
269 struct pred {
270 pred() {};
271 bool operator()(const VertDist& v0, const VertDist& v1) const {
272 return (v0.d > v1.d);
273 }
274 };
275
276 /*
277 *
278 curr: vertex for which distance should be estimated
279 d_pw1: distance of pw1 from the source
280 d_curr: distance of curr from the source
281
282The function estimates the distance of pw from the source
283in the assumption the mesh is developable (and without holes)
284along the path, so that (source,pw1,curr) from a triangle.
285All the math is to compute the angles at pw1 and curr with the Erone formula.
286
287The if cases take care of the cases where the angles are obtuse.
288
289 curr
290 d_pw1 +
291 | +pw
292source+ |
293 d_curr +
294 pw1
295
296 */
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)
304 {
305 ScalarType curr_d=0;
306
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;
313
314 ScalarType alpha,alpha_, beta,beta_,theta,h,delta,s,a,b;
315
316 alpha = acos((w_c.dot(w1_c))/(ew_c*ec_w1));
317 s = (d_curr + d_pw1+ec_w1)/2;
318 a = s/ec_w1;
319 b = a*s;
320 alpha_ = 2*acos ( std::min<ScalarType>(1.0,sqrt( (b- a* d_pw1)/d_curr)));
321
322 if ( alpha+alpha_ > M_PI){
323 curr_d = d_curr + ew_c;
324 }else
325 {
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));
328
329 if ( beta+beta_ > M_PI)
330 curr_d = d_pw1 + ew_w1;
331 else
332 {
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));
337 }
338 }
339 return (curr_d);
340 }
341
342
343
344
374 template <class DistanceFunctor>
375 static VertexPointer Visit(
376 MeshType & m,
377 std::vector<VertDist> & seedVec, // the set of seeds to start from
378 DistanceFunctor &distFunc,
379 ScalarType distance_threshold = std::numeric_limits<ScalarType>::max(), // cut off distance (do no compute anything farther than this value)
380 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * vertSource = NULL, // if present we put in this attribute the closest source for each vertex
381 typename MeshType::template PerVertexAttributeHandle<VertexPointer> * vertParent = NULL, // if present we put in this attribute the parent in the path that goes from the vertex to the closest source
382 std::vector<VertexPointer> *InInterval=NULL)
383 {
384 VertexPointer farthest=0;
385 //Requirements
386 tri::RequireVFAdjacency(m);
387 tri::RequirePerVertexQuality(m);
388
389 assert(!seedVec.empty());
390
391 auto TD = tri::Allocator<MeshType>::template GetPerVertexAttribute<GeodData>(m,"geod");
392 GeodData::reset();
393
394 // initialize Heap
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);
402 }
403 make_heap(frontierHeap.begin(),frontierHeap.end(),pred());
404
405 ScalarType curr_d,d_curr = 0.0,d_heap;
406 ScalarType max_distance=0.0;
407
408 while(!frontierHeap.empty() && max_distance < distance_threshold)
409 {
410 pop_heap(frontierHeap.begin(),frontierHeap.end(),pred());
411 VertexPointer curr = (frontierHeap.back()).v;
412 if (InInterval!=NULL) InInterval->push_back(curr);
413
414 if(vertSource!=NULL) (*vertSource)[curr] = TD[curr].source;
415 if(vertParent!=NULL) (*vertParent)[curr] = TD[curr].parent;
416
417 d_heap = (frontierHeap.back()).d;
418 frontierHeap.pop_back();
419
420 assert(TD[curr].d() <= d_heap);
421 if(TD[curr].d() < d_heap ) // a vertex whose distance has been improved after it was inserted in the queue
422 continue;
423 assert(TD[curr].d() == d_heap);
424
425 d_curr = TD[curr].d();
426
427 for(face::VFIterator<FaceType> vfi(curr) ; vfi.f!=0; ++vfi )
428 {
429 for(int k=0;k<2;++k)
430 {
431 VertexPointer pw,pw1;
432 if(k==0) {
433 pw = vfi.f->V1(vfi.z);
434 pw1= vfi.f->V2(vfi.z);
435 }
436 else {
437 pw = vfi.f->V2(vfi.z);
438 pw1= vfi.f->V1(vfi.z);
439 }
440
441 const ScalarType & d_pw1 = TD[pw1].d();
442 {
443 const ScalarType inter = distFunc(curr,pw1);//(curr->P() - pw1->P()).Norm();
444 const ScalarType tol = (inter + d_curr + d_pw1)*.0001f;
445
446 if ( (TD[pw1].source != TD[curr].source)||// not the same source
447 (inter + d_curr < d_pw1 +tol ) ||
448 (inter + d_pw1 < d_curr +tol ) ||
449 (d_curr + d_pw1 < inter +tol ) // triangular inequality
450 )
451 curr_d = d_curr + distFunc(pw,curr);//(pw->P()-curr->P()).Norm();
452 else
453 curr_d = GeoDistance(distFunc,pw,pw1,curr,d_pw1,d_curr);
454 }
455
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());
462 }
463// if(isLeaf){
464 if(d_curr > max_distance){
465 max_distance = d_curr;
466 farthest = curr;
467 }
468// }
469 }
470 } // end for VFIterator
471 }// end while
472
473 // Copy found distance onto the Quality (\todo parametric!)
474 if (InInterval==NULL)
475 {
476 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD())
477 (*vi).Q() = TD[&(*vi)].d();
478 }
479 else
480 {
481 assert(InInterval->size()>0);
482 for(size_t i=0;i<InInterval->size();i++)
483 (*InInterval)[i]->Q() = TD[(*InInterval)[i]].d();
484 }
485
486 return farthest;
487 }
488
489public:
527 static bool Compute( MeshType & m,
528 const std::vector<VertexPointer> & seedVec)
529 {
531 return Compute(m,seedVec,dd);
532 }
533
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
542 )
543 {
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);
550 return true;
551 }
552
553 /* \brief Assigns to each vertex of the mesh its distance to the closest vertex on the boundary
554
555It is just a simple wrapper of the basic Compute()
556
557 Note: update the field Q() of the vertices
558 Note: it needs the border bit set.
559 */
560 static bool DistanceFromBorder( MeshType & m, typename MeshType::template PerVertexAttributeHandle<VertexPointer> * sources = NULL)
561 {
562 std::vector<VertexPointer> fro;
563 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
564 if( (*vi).IsB())
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);
570 }
571
572
573 static bool ConvertPerVertexSeedToPerFaceSeed(MeshType &m, const std::vector<VertexPointer> &vertexSeedVec,
574 std::vector<FacePointer> &faceSeedVec)
575 {
576 tri::RequireVFAdjacency(m);
577 tri::RequirePerFaceMark(m);
578
579 faceSeedVec.clear();
580 tri::UnMarkAll(m);
581 for(size_t i=0;i<vertexSeedVec.size();++i)
582 {
583 for(face::VFIterator<FaceType> vfi(vertexSeedVec[i]);!vfi.End();++vfi)
584 {
585 if(tri::IsMarked(m,vfi.F())) return false;
586 faceSeedVec.push_back(vfi.F());
587 tri::Mark(m,vfi.F());
588 }
589 }
590 return true;
591 }
592
593 static inline std::string sourcesAttributeName(void) { return "sources"; }
594 static inline std::string parentsAttributeName(void) { return "parent"; }
595
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)
603 {
604 tri::RequireFFAdjacency(m);
605 tri::RequirePerFaceMark(m);
606 tri::RequirePerFaceQuality(m);
607
608 typename MeshType::template PerFaceAttributeHandle<FacePointer> sourceHandle
609 = tri::Allocator<MeshType>::template GetPerFaceAttribute<FacePointer>(m, sourcesAttributeName());
610
611 typename MeshType::template PerFaceAttributeHandle<FacePointer> parentHandle
612 = tri::Allocator<MeshType>::template GetPerFaceAttribute<FacePointer>(m, parentsAttributeName());
613
614 std::vector<FaceDist> Heap;
615 tri::UnMarkAll(m);
616 for(size_t i=0;i<seedVec.size();++i)
617 {
618 tri::Mark(m,seedVec[i]);
619 seedVec[i]->Q()=0;
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]);
624 }
625
626 std::make_heap(Heap.begin(),Heap.end());
627 while(!Heap.empty())
628 {
629 pop_heap(Heap.begin(),Heap.end());
630 FacePointer curr = (Heap.back()).f;
631 if ((FaceTarget!=NULL)&&(curr==FaceTarget))return;
632 Heap.pop_back();
633
634 for(int i=0;i<3;++i)
635 {
636 if(!face::IsBorder(*curr,i) )
637 {
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()) )
642 {
643 nextF->Q() = nextDist;
644 if ((avoid_selected)&&(nextF->IsS()))continue;
645 tri::Mark(m,nextF);
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;
651// printf("Heapsize %i nextDist = %f curr face %i next face %i \n",Heap.size(), nextDist, tri::Index(m,curr), tri::Index(m,nextF));
652 }
653 }
654 }
655 }
656 }
657
658
659
660
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)
670 {
671 tri::RequireVFAdjacency(m);
672 tri::RequirePerVertexMark(m);
673 tri::RequirePerVertexQuality(m);
674
675 std::vector<DIJKDist> Heap;
676 tri::UnMarkAll(m);
677
678 for(size_t i=0;i<seedVec.size();++i)
679 {
680 assert(!tri::IsMarked(m,seedVec[i]));
681 tri::Mark(m,seedVec[i]);
682 seedVec[i]->Q()=0;
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]);
689 }
690
691 std::make_heap(Heap.begin(),Heap.end());
692 while(!Heap.empty())
693 {
694 pop_heap(Heap.begin(),Heap.end());
695 VertexPointer curr = (Heap.back()).v;
696 if ((target!=NULL)&&(target==curr))return;
697 Heap.pop_back();
698 std::vector<VertexPointer> vertVec;
699 face::VVStarVF<FaceType>(curr,vertVec);
700 for(size_t i=0;i<vertVec.size();++i)
701 {
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()) )
707 {
708 nextV->Q() = nextDist;
709 tri::Mark(m,nextV);
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;
717// printf("Heapsize %i nextDist = %f curr vert %i next vert %i \n",Heap.size(), nextDist, tri::Index(m,curr), tri::Index(m,nextV));
718 }
719 }
720 }
721 }
722
723
724};// end class
725}// end namespace tri
726}// end namespace vcg
727#endif
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: color4.h:30
Definition: geodesic.h:100
Definition: geodesic.h:44
Definition: geodesic.h:199
Definition: geodesic.h:213
Definition: geodesic.h:190
Definition: geodesic.h:269