From 51424a7896a76ea89f3de40d1eaf58f0c8bd5235 Mon Sep 17 00:00:00 2001 From: cignoni Date: Mon, 25 Nov 2013 12:46:30 +0000 Subject: [PATCH] committed a small change to the Geodesic::Visit Now it can start from a set of seeds that are not at zero distance. --- vcg/complex/algorithms/geodesic.h | 90 ++++++++++++++++++------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/vcg/complex/algorithms/geodesic.h b/vcg/complex/algorithms/geodesic.h index 45fe5c66..bb87c847 100644 --- a/vcg/complex/algorithms/geodesic.h +++ b/vcg/complex/algorithms/geodesic.h @@ -217,15 +217,27 @@ public: {return (v0.d > v1.d);} }; - struct pred_addr: public std::binary_function{ - pred_addr(){} - bool operator()(const VertDist& v0, const VertDist& v1) const - {return (v0.v > v1.v);} - }; + /* + * + curr: vertex for which distance should be estimated + d_pw1: distance of pw1 from the source + d_curr: distance of curr from the source - //************** calcolo della distanza di pw in base alle distanze note di pw1 e curr - //************** sapendo che (curr,pw,pw1) e'una faccia della mesh - //************** (vedi figura in file distance.gif) +The function estimates the distance of pw from the source +in the assumption the mesh is developable (and without holes) +along the path, so that (source,pw1,curr) from a triangle. +All the math is to comput the angles at pw1 and curr with the Erone formula. + +The if cases take care of the cases where the angles are obtuse. + + curr + d_pw1 + + | +pw +source+ | + d_curr + + pw1 + + */ template static ScalarType Distance(DistanceFunctor &distFunc, const VertexPointer &pw, @@ -271,6 +283,9 @@ public: return (curr_d); } + + + /* This is the low level version of the geodesic computation framework. Starting from the seeds, it assign a distance value to each vertex. The distance of a vertex is its @@ -278,20 +293,19 @@ approximated geodesic distance to the closest seeds. This is function is not meant to be called (although is not prevented). Instead, it is invoked by wrapping function. */ + template static VertexPointer Visit( MeshType & m, - std::vector & seedVec, // the set of seed to start from + std::vector & seedVec, // the set of seeds to start from DistanceFunctor &distFunc, -// bool farthestOnBorder = false, ScalarType distance_threshold = std::numeric_limits::max(), // cut off distance (do no compute anything farther than this value) typename MeshType::template PerVertexAttributeHandle * vertSource = NULL, // if present we put in this attribute the closest source for each vertex typename MeshType::template PerVertexAttributeHandle * vertParent = NULL, // if present we put in this attribute the parent in the path that goes from the vertex to the closest source std::vector *InInterval=NULL) { - std::vector frontier; - VertexPointer farthest=0,pw,pw1; - + VertexPointer farthest=0; +// int t0=clock(); //Requirements if(!HasVFAdjacency(m)) throw vcg::MissingComponentException("VFAdjacency"); if(!HasPerVertexQuality(m)) throw vcg::MissingComponentException("VertexQuality"); @@ -299,31 +313,31 @@ wrapping function. TempDataType TD(m.vert, std::numeric_limits::max()); + // initialize Heap + std::vector frontierHeap; typename std::vector ::iterator ifr; for(ifr = seedVec.begin(); ifr != seedVec.end(); ++ifr){ - (*ifr).d = 0.0; - TD[(*ifr).v].d = 0.0; + TD[(*ifr).v].d = (*ifr).d; TD[(*ifr).v].source = (*ifr).v; TD[(*ifr).v].parent = (*ifr).v; - frontier.push_back(VertDist((*ifr).v,0.0)); + frontierHeap.push_back(*ifr); } - // initialize Heap - make_heap(frontier.begin(),frontier.end(),pred()); + make_heap(frontierHeap.begin(),frontierHeap.end(),pred()); ScalarType curr_d,d_curr = 0.0,d_heap; ScalarType max_distance=0.0; - - while(!frontier.empty() && max_distance < distance_threshold) +// int t1=clock(); + while(!frontierHeap.empty() && max_distance < distance_threshold) { - pop_heap(frontier.begin(),frontier.end(),pred()); - VertexPointer curr = (frontier.back()).v; + pop_heap(frontierHeap.begin(),frontierHeap.end(),pred()); + VertexPointer curr = (frontierHeap.back()).v; if (InInterval!=NULL) InInterval->push_back(curr); if(vertSource!=NULL) (*vertSource)[curr] = TD[curr].source; if(vertParent!=NULL) (*vertParent)[curr] = TD[curr].parent; - d_heap = (frontier.back()).d; - frontier.pop_back(); + d_heap = (frontierHeap.back()).d; + frontierHeap.pop_back(); assert(TD[curr].d <= d_heap); if(TD[curr].d < d_heap ) // a vertex whose distance has been improved after it was inserted in the queue @@ -332,20 +346,18 @@ wrapping function. d_curr = TD[curr].d; -// bool isLeaf = (!farthestOnBorder || curr->IsB()); - - face::VFIterator x;int k; - - for( x.f = curr->VFp(), x.z = curr->VFi(); x.f!=0; ++x ) - for(k=0;k<2;++k) + for(face::VFIterator vfi(curr) ; vfi.f!=0; ++vfi ) + { + for(int k=0;k<2;++k) { + VertexPointer pw,pw1; if(k==0) { - pw = x.f->V1(x.z); - pw1=x.f->V2(x.z); + pw = vfi.f->V1(vfi.z); + pw1= vfi.f->V2(vfi.z); } else { - pw = x.f->V2(x.z); - pw1=x.f->V1(x.z); + pw = vfi.f->V2(vfi.z); + pw1= vfi.f->V1(vfi.z); } const ScalarType & d_pw1 = TD[pw1].d; @@ -367,8 +379,8 @@ wrapping function. TD[pw].d = curr_d; TD[pw].source = TD[curr].source; TD[pw].parent = curr; - frontier.push_back(VertDist(pw,curr_d)); - push_heap(frontier.begin(),frontier.end(),pred()); + frontierHeap.push_back(VertDist(pw,curr_d)); + push_heap(frontierHeap.begin(),frontierHeap.end(),pred()); } // if(isLeaf){ if(d_curr > max_distance){ @@ -377,7 +389,9 @@ wrapping function. } // } } + } // end for VFIterator }// end while +// int t2=clock(); // Copy found distance onto the Quality (\todo parametric!) if (InInterval==NULL) @@ -391,11 +405,11 @@ wrapping function. for(size_t i=0;isize();i++) (*InInterval)[i]->Q() = TD[(*InInterval)[i]].d; } - +// int t3=clock(); +// printf("Init %6.3f\nVisit %6.3f\nFinal %6.3f\n",float(t1-t0)/CLOCKS_PER_SEC,float(t2-t1)/CLOCKS_PER_SEC,float(t3-t2)/CLOCKS_PER_SEC); return farthest; } - public: /*! \brief Given a set of source vertices compute the approximate geodesic distance to all the other vertices