35#ifndef __VCGLIB_POINT_SAMPLING
36#define __VCGLIB_POINT_SAMPLING
40#include <vcg/math/random_generator.h>
41#include <vcg/complex/algorithms/closest.h>
42#include <vcg/space/index/spatial_hashing.h>
43#include <vcg/complex/algorithms/hole.h>
44#include <vcg/complex/algorithms/stat.h>
45#include <vcg/complex/algorithms/create/platonic.h>
46#include <vcg/complex/algorithms/update/normal.h>
47#include <vcg/complex/algorithms/update/bounding.h>
48#include <vcg/space/segment2.h>
49#include <vcg/space/index/grid_static_ptr.h>
70template <
class MeshType>
74 typedef typename MeshType::ScalarType ScalarType;
75 typedef typename MeshType::CoordType CoordType;
76 typedef typename MeshType::VertexType VertexType;
77 typedef typename MeshType::EdgeType EdgeType;
78 typedef typename MeshType::FaceType FaceType;
87 sampleVec =
new std::vector<CoordType>();
100 if(vectorOwner)
delete sampleVec;
104 std::vector<CoordType> *sampleVec;
108 std::vector<CoordType> &SampleVec()
113 void AddVert(
const VertexType &p)
115 sampleVec->push_back(p.cP());
117 void AddEdge(
const EdgeType& e, ScalarType u )
119 sampleVec->push_back(e.cV(0)->cP()*(1.0-u)+e.cV(1)->cP()*u);
122 void AddFace(
const FaceType &f,
const CoordType &p)
124 sampleVec->push_back(f.cP(0)*p[0] + f.cP(1)*p[1] +f.cP(2)*p[2] );
127 void AddTextureSample(
const FaceType &,
const CoordType &,
const Point2i &,
float )
135template <
class MeshType>
139 typedef typename MeshType::ScalarType ScalarType;
140 typedef typename MeshType::CoordType CoordType;
141 typedef typename MeshType::VertexType VertexType;
142 typedef typename MeshType::EdgeType EdgeType;
143 typedef typename MeshType::FaceType FaceType;
154 std::vector<VertexType *> sampleVec;
156 void AddVert(VertexType &p)
158 sampleVec.push_back(&p);
161 void AddEdge(
const EdgeType& e, ScalarType u )
164 sampleVec.push_back(e.cV(0));
166 sampleVec.push_back(e.cV(1));
170 void AddFace(
const FaceType &,
const CoordType &) { assert(0); }
171 void AddTextureSample(
const FaceType &,
const CoordType &,
const Point2i &,
float ) { assert(0); }
175template <
class MeshType>
179 typedef typename MeshType::VertexType VertexType;
180 typedef typename MeshType::FaceType FaceType;
181 typedef typename MeshType::EdgeType EdgeType;
182 typedef typename MeshType::CoordType CoordType;
183 typedef typename MeshType::ScalarType ScalarType;
186 perFaceNormal =
false;
197 void AddVert(
const VertexType &p)
200 m.vert.back().ImportData(p);
203 void AddEdge(
const EdgeType& e, ScalarType u )
206 m.vert.back().P() = e.cV(0)->cP()*(1.0-u)+e.cV(1)->cP()*u;
207 m.vert.back().N() = e.cV(0)->cN()*(1.0-u)+e.cV(1)->cN()*u;
210 void AddFace(
const FaceType &f, CoordType p)
213 m.vert.back().P() = f.cP(0)*p[0] + f.cP(1)*p[1] +f.cP(2)*p[2];
214 if(perFaceNormal) m.vert.back().N() = f.cN();
215 else m.vert.back().N() = f.cV(0)->N()*p[0] + f.cV(1)->N()*p[1] + f.cV(2)->N()*p[2];
216 if(tri::HasPerVertexQuality(m) )
217 m.vert.back().Q() = f.cV(0)->Q()*p[0] + f.cV(1)->Q()*p[1] + f.cV(2)->Q()*p[2];
228template <
class MeshType>
231 typedef typename MeshType::FaceType FaceType;
232 typedef typename MeshType::VertexType VertexType;
233 typedef typename MeshType::CoordType CoordType;
234 typedef typename MeshType::ScalarType ScalarType;
235 typedef GridStaticPtr<FaceType, ScalarType > MetroMeshFaceGrid;
236 typedef GridStaticPtr<VertexType, ScalarType > MetroMeshVertexGrid;
240 HausdorffSampler(MeshType* _m, MeshType* _sampleMesh=0, MeshType* _closestMesh=0 ) :markerFunctor(_m)
243 init(_sampleMesh,_closestMesh);
251 MetroMeshFaceGrid unifGridFace;
264 bool useVertexSampling;
265 ScalarType dist_upper_bound;
266 typedef typename tri::FaceTmark<MeshType> MarkerFace;
267 MarkerFace markerFunctor;
270 float getMeanDist()
const {
return mean_dist / n_total_samples; }
271 float getMinDist()
const {
return min_dist ; }
272 float getMaxDist()
const {
return max_dist ; }
273 float getRMSDist()
const {
return sqrt(RMS_dist / n_total_samples); }
275 void init(MeshType* _sampleMesh=0, MeshType* _closestMesh=0 )
282 if(m->fn==0) useVertexSampling =
true;
283 else useVertexSampling =
false;
285 if(useVertexSampling)
unifGridVert.Set(m->vert.begin(),m->vert.end());
286 else unifGridFace.Set(m->face.begin(),m->face.end());
287 markerFunctor.SetMesh(m);
288 hist.SetRange(0.0, m->bbox.Diag()/100.0, 100);
290 min_dist = std::numeric_limits<double>::max();
297 void AddFace(
const FaceType &f, CoordType interp)
299 CoordType startPt = f.cP(0)*interp[0] + f.cP(1)*interp[1] +f.cP(2)*interp[2];
300 CoordType startN = f.cV(0)->cN()*interp[0] + f.cV(1)->cN()*interp[1] +f.cV(2)->cN()*interp[2];
301 AddSample(startPt,startN);
304 void AddVert(VertexType &p)
306 p.Q()=AddSample(p.cP(),p.cN());
310 float AddSample(
const CoordType &startPt,
const CoordType &startN)
314 ScalarType dist = dist_upper_bound;
317 FaceType *nearestF=0;
318 VertexType *nearestV=0;
319 vcg::face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
320 dist=dist_upper_bound;
321 if(useVertexSampling)
322 nearestV = tri::GetClosestVertex<MeshType,MetroMeshVertexGrid>(*m,
unifGridVert,startPt,dist_upper_bound,dist);
324 nearestF = unifGridFace.GetClosest(PDistFunct,markerFunctor,startPt,dist_upper_bound,dist,closestPt);
327 if(dist == dist_upper_bound)
330 if(dist > max_dist) max_dist = dist;
331 if(dist < min_dist) min_dist = dist;
334 RMS_dist += dist*dist;
337 hist.Add((
float)fabs(dist));
361template <
class MeshType>
364 typedef typename MeshType::FaceType FaceType;
365 typedef typename MeshType::VertexType VertexType;
366 typedef typename MeshType::CoordType CoordType;
367 typedef typename MeshType::ScalarType ScalarType;
368 typedef GridStaticPtr<FaceType, ScalarType > MetroMeshGrid;
369 typedef GridStaticPtr<VertexType, ScalarType > VertexMeshGrid;
379 MetroMeshGrid unifGridFace;
380 VertexMeshGrid unifGridVert;
381 bool useVertexSampling;
384 typedef tri::FaceTmark<MeshType> MarkerFace;
385 MarkerFace markerFunctor;
392 bool storeDistanceAsQualityFlag;
393 float dist_upper_bound;
394 void init(MeshType *_m, CallBackPos *_cb=0,
int targetSz=0)
400 storeDistanceAsQualityFlag=
false;
403 if(m->fn==0) useVertexSampling =
true;
404 else useVertexSampling =
false;
406 if(useVertexSampling) unifGridVert.Set(m->vert.begin(),m->vert.end());
407 else unifGridFace.Set(m->face.begin(),m->face.end());
408 markerFunctor.SetMesh(m);
411 sampleNum = targetSz;
417 void AddVert(VertexType &p)
421 CoordType closestPt, normf, bestq, ip;
422 ScalarType dist = dist_upper_bound;
423 const CoordType &startPt= p.cP();
425 if(useVertexSampling)
427 VertexType *nearestV=0;
428 nearestV = tri::GetClosestVertex<MeshType,VertexMeshGrid>(*m,unifGridVert,startPt,dist_upper_bound,dist);
429 if(
cb)
cb(sampleCnt++*100/sampleNum,
"Resampling Vertex attributes");
430 if(storeDistanceAsQualityFlag) p.Q() = dist;
431 if(dist == dist_upper_bound) return ;
433 if(coordFlag) p.P()=nearestV->P();
434 if(colorFlag) p.C() = nearestV->C();
435 if(normalFlag) p.N() = nearestV->N();
436 if(qualityFlag) p.Q()= nearestV->Q();
437 if(selectionFlag)
if(nearestV->IsS()) p.SetS();
441 FaceType *nearestF=0;
442 vcg::face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
443 dist=dist_upper_bound;
444 if(
cb)
cb(sampleCnt++*100/sampleNum,
"Resampling Vertex attributes");
445 nearestF = unifGridFace.GetClosest(PDistFunct,markerFunctor,startPt,dist_upper_bound,dist,closestPt);
446 if(dist == dist_upper_bound) return ;
449 InterpolationParameters(*nearestF,(*nearestF).cN(),closestPt, interp);
450 interp[2]=1.0-interp[1]-interp[0];
452 if(coordFlag) p.P()=closestPt;
453 if(colorFlag) p.C().lerp(nearestF->V(0)->C(),nearestF->V(1)->C(),nearestF->V(2)->C(),interp);
454 if(normalFlag) p.N() = nearestF->V(0)->N()*interp[0] + nearestF->V(1)->N()*interp[1] + nearestF->V(2)->N()*interp[2];
455 if(qualityFlag) p.Q()= nearestF->V(0)->Q()*interp[0] + nearestF->V(1)->Q()*interp[1] + nearestF->V(2)->Q()*interp[2];
456 if(selectionFlag)
if(nearestF->IsS()) p.SetS();
474template <
class MeshType,
class VertexSampler = TrivialSampler< MeshType> >
477 typedef typename MeshType::CoordType CoordType;
478 typedef typename MeshType::BoxType BoxType;
479 typedef typename MeshType::ScalarType ScalarType;
480 typedef typename MeshType::VertexType VertexType;
481 typedef typename MeshType::VertexPointer VertexPointer;
482 typedef typename MeshType::VertexIterator VertexIterator;
483 typedef typename MeshType::EdgeType EdgeType;
484 typedef typename MeshType::EdgeIterator EdgeIterator;
485 typedef typename MeshType::FaceType FaceType;
486 typedef typename MeshType::FacePointer FacePointer;
487 typedef typename MeshType::FaceIterator FaceIterator;
488 typedef typename MeshType::FaceContainer FaceContainer;
490 typedef typename vcg::SpatialHashTable<FaceType, ScalarType> MeshSHT;
491 typedef typename vcg::SpatialHashTable<FaceType, ScalarType>::CellIterator MeshSHTIterator;
492 typedef typename vcg::SpatialHashTable<VertexType, ScalarType> MontecarloSHT;
493 typedef typename vcg::SpatialHashTable<VertexType, ScalarType>::CellIterator MontecarloSHTIterator;
494 typedef typename vcg::SpatialHashTable<VertexType, ScalarType> SampleSHT;
495 typedef typename vcg::SpatialHashTable<VertexType, ScalarType>::CellIterator SampleSHTIterator;
497 typedef typename MeshType::template PerVertexAttributeHandle<float> PerVertexFloatAttribute;
501static math::MarsenneTwisterRNG &SamplingRandomGenerator()
503 static math::MarsenneTwisterRNG rnd;
509static unsigned int RandomInt(
unsigned int i)
511 return (SamplingRandomGenerator().generate(i));
517 typedef unsigned int result_type;
519 static constexpr result_type min() {
return 0;}
520 static constexpr result_type max() {
return std::numeric_limits<result_type>::max();}
521 result_type operator()() {
return SamplingRandomGenerator().generate(_max);}
527static double RandomDouble01()
529 return SamplingRandomGenerator().generate01();
533static double LnFac(
int n) {
538 C0 = 0.918938533204672722,
544 static double fac_table[FAK_LEN];
545 static bool initialized =
false;
550 if (n < 0) assert(0);
555 double sum = fac_table[0] = 0.;
556 for (
int i=1; i<FAK_LEN; i++) {
557 sum += log(
double(i));
567 return (n1 + 0.5)*log(n1) - n1 + C0 + r*(C1 + r*r*C3);
570static int PoissonRatioUniforms(
double L) {
592 const double SHAT1 = 2.943035529371538573;
593 const double SHAT2 = 0.8989161620588987408;
599 double pois_a = L + 0.5;
601 double pois_g = log(L);
602 double pois_f0 = mode * pois_g - LnFac(mode);
603 double pois_h = sqrt(SHAT1 * (L+0.5)) + SHAT2;
604 double pois_bound = (int)(pois_a + 6.0 * pois_h);
607 u = RandomDouble01();
608 if (u == 0)
continue;
609 x = pois_a + pois_h * (RandomDouble01() - 0.5) / u;
610 if (x < 0 || x >= pois_bound)
continue;
612 lf = k * pois_g - LnFac(k) - pois_f0;
613 if (lf >= u * (4.0 - u) - 3.0)
break;
614 if (u * (u - lf) > 1.0)
continue;
615 if (2.0 * log(u) <= lf)
break;
634 if(lambda>50)
return PoissonRatioUniforms(lambda);
635 double L = exp(-lambda);
641 p = p*RandomDouble01();
648static void AllVertex(MeshType & m, VertexSampler &ps)
650 AllVertex(m, ps,
false);
653static void AllVertex(MeshType & m, VertexSampler &ps,
bool onlySelected)
656 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
658 if ((!onlySelected) || ((*vi).IsS()))
676 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
680 ScalarType samplePerUnit = sampleNum/qSum;
681 ScalarType floatSampleNum =0;
682 std::vector<VertexPointer> vertVec;
683 FillAndShuffleVertexPointerVector(m,vertVec);
685 std::vector<bool> vertUsed(m.vn,
false);
688 while(cnt < sampleNum)
692 floatSampleNum += vertVec[i]->Q() * samplePerUnit;
693 int vertSampleNum = (int) floatSampleNum;
694 floatSampleNum -= (float) vertSampleNum;
697 if(vertSampleNum > 1)
699 ps.AddVert(*vertVec[i]);
713 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
718 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
721 ScalarType areaThird = DoubleArea(*fi)/6.0;
722 (*fi).V(0)->Q()+=areaThird;
723 (*fi).V(1)->Q()+=areaThird;
724 (*fi).V(2)->Q()+=areaThird;
730static void FillAndShuffleFacePointerVector(MeshType & m, std::vector<FacePointer> &faceVec)
732 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
733 if(!(*fi).IsD()) faceVec.push_back(&*fi);
735 assert((
int)faceVec.size()==m.fn);
740 MarsenneTwisterURBG g(faceVec.size());
741 std::shuffle(faceVec.begin(),faceVec.end(), g);
743static void FillAndShuffleVertexPointerVector(MeshType & m, std::vector<VertexPointer> &vertVec)
745 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
746 if(!(*vi).IsD()) vertVec.push_back(&*vi);
748 assert((
int)vertVec.size()==m.vn);
753 MarsenneTwisterURBG g(vertVec.size());
754 std::shuffle(vertVec.begin(),vertVec.end(), g);
758static void VertexUniform(MeshType & m, VertexSampler &ps,
int sampleNum,
bool onlySelected)
760 if (sampleNum >= m.vn) {
761 AllVertex(m, ps, onlySelected);
765 std::vector<VertexPointer> vertVec;
766 FillAndShuffleVertexPointerVector(m, vertVec);
769 for (
int i = 0; ((i < m.vn) && (added < sampleNum)); ++i)
770 if (!(*vertVec[i]).IsD())
771 if ((!onlySelected) || (*vertVec[i]).IsS())
773 ps.AddVert(*vertVec[i]);
780static void VertexUniform(MeshType & m, VertexSampler &ps,
int sampleNum)
817 tri::RequireEEAdjacency(m);
818 tri::RequireCompactness(m);
819 tri::RequirePerEdgeFlags(m);
820 tri::RequirePerVertexFlags(m);
823 tri::MeshAssert<MeshType>::EEOneManifold(m);
825 for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
829 edge::Pos<EdgeType> ep(&*ei,0);
830 edge::Pos<EdgeType> startep = ep;
836 }
while (startep != ep);
840 assert(ep == startep);
844 edge::Pos<EdgeType> altEp = ep;
846 while (altEp != startep) {
847 if (altEp.V()->cP() < ep.V()->cP())
855 const auto dir0 = ep.VFlip()->cP() - ep.V()->cP();
857 const auto dir1 = ep.VFlip()->cP() - ep.V()->cP();
865 edge::Pos<EdgeType> altEp = ep;
868 }
while (!altEp.IsBorder());
870 if (altEp.V()->cP() < ep.V()->cP())
876 ScalarType totalLen = 0;
882 totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
884 }
while (!ep.E()->IsV() && !ep.IsBorder());
885 if (ep.IsBorder() && !ep.E()->IsV())
888 totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
891 VertexPointer startVertex = ep.V();
896 double div = double(totalLen) / radius;
898 case Round: sampleNum = int(round(div));
break;
899 case Ceil: sampleNum = int( ceil(div));
break;
900 default: sampleNum = int(floor(div));
break;
903 assert(sampleNum >= 0);
905 ScalarType sampleDist = totalLen / sampleNum;
909 ScalarType curLen = 0;
911 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
915 assert(ep.E()->IsV());
916 ScalarType edgeLen = Distance(ep.VFlip()->cP(), ep.V()->cP());
917 ScalarType d0 = curLen;
918 ScalarType d1 = d0 + edgeLen;
920 while (d1 > sampleCnt * sampleDist && sampleCnt < sampleNum)
922 ScalarType off = (sampleCnt * sampleDist - d0) / edgeLen;
924 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 1.0 - off : off);
928 }
while(!ep.IsBorder() && ep.V() != startVertex);
930 if(ep.V() != startVertex)
932 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
947 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
949 if(vi->IsS()) ps.AddVert(*vi);
972 std::vector< SimpleEdge > Edges;
973 typename std::vector< SimpleEdge >::iterator ei;
976 typename MeshType::template PerVertexAttributeHandle <int> hv =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<int> (m);
978 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
984 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
992static void FaceUniform(MeshType & m, VertexSampler &ps,
int sampleNum)
994 if(sampleNum>=m.fn) {
999 std::vector<FacePointer> faceVec;
1000 FillAndShuffleFacePointerVector(m,faceVec);
1002 for(
int i =0; i< sampleNum; ++i)
1003 ps.AddFace(*faceVec[i],Barycenter(*faceVec[i]));
1006static void AllFace(MeshType & m, VertexSampler &ps)
1009 for(fi=m.face.begin();fi!=m.face.end();++fi)
1012 ps.AddFace(*fi,Barycenter(*fi));
1017static void AllEdge(MeshType & m, VertexSampler &ps)
1020 typedef typename UpdateTopology<MeshType>::PEdge SimpleEdge;
1021 std::vector< SimpleEdge > Edges;
1022 typename std::vector< SimpleEdge >::iterator ei;
1023 UpdateTopology<MeshType>::FillUniqueEdgeVector(m,Edges);
1025 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1026 ps.AddFace(*(*ei).f,ei->EdgeBarycentricToFaceBarycentric(0.5));
1033static void EdgeUniform(MeshType & m, VertexSampler &ps,
int sampleNum,
bool sampleFauxEdge=
true)
1035 typedef typename UpdateTopology<MeshType>::PEdge SimpleEdge;
1037 std::vector< SimpleEdge > Edges;
1038 UpdateTopology<MeshType>::FillUniqueEdgeVector(m,Edges,sampleFauxEdge);
1041 typename std::vector< SimpleEdge >::iterator ei;
1042 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1043 edgeSum+=Distance((*ei).v[0]->P(),(*ei).v[1]->P());
1045 float sampleLen = edgeSum/sampleNum;
1047 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1049 float len = Distance((*ei).v[0]->P(),(*ei).v[1]->P());
1050 float samplePerEdge = floor((len+rest)/sampleLen);
1051 rest = (len+rest) - samplePerEdge * sampleLen;
1052 float step = 1.0/(samplePerEdge+1);
1053 for(
int i=0;i<samplePerEdge;++i)
1055 CoordType interp(0,0,0);
1056 interp[ (*ei).z ]=step*(i+1);
1057 interp[((*ei).z+1)%3]=1.0-step*(i+1);
1058 ps.AddFace(*(*ei).f,interp);
1066static CoordType RandomBarycentric()
1068 return math::GenerateBarycentricUniform<ScalarType>(SamplingRandomGenerator());
1072static CoordType RandomPointInTriangle(
const FaceType &f)
1074 CoordType u = RandomBarycentric();
1075 return f.cP(0)*u[0] + f.cP(1)*u[1] + f.cP(2)*u[2];
1078static void StratifiedMontecarlo(MeshType & m, VertexSampler &ps,
int sampleNum)
1080 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1081 ScalarType samplePerAreaUnit = sampleNum/area;
1083 double floatSampleNum = 0.0;
1086 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1090 floatSampleNum += 0.5*DoubleArea(*fi) * samplePerAreaUnit;
1091 int faceSampleNum = (int) floatSampleNum;
1094 for(
int i=0; i < faceSampleNum; i++)
1095 ps.AddFace(*fi,RandomBarycentric());
1096 floatSampleNum -= (double) faceSampleNum;
1116 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1117 ScalarType samplePerAreaUnit = sampleNum/area;
1120 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1123 float areaT=DoubleArea(*fi) * 0.5f;
1124 int faceSampleNum =
Poisson(areaT*samplePerAreaUnit);
1127 for(
int i=0; i < faceSampleNum; i++)
1128 ps.AddFace(*fi,RandomBarycentric());
1140static void EdgeMontecarlo(MeshType & m, VertexSampler &ps,
int sampleNum,
bool sampleAllEdges)
1143 std::vector< SimpleEdge > Edges;
1146 assert(!Edges.empty());
1148 typedef std::pair<ScalarType, SimpleEdge*> IntervalType;
1149 std::vector< IntervalType > intervals (Edges.size()+1);
1151 intervals[i]=std::make_pair(0,(SimpleEdge*)(0));
1153 typename std::vector< SimpleEdge >::iterator ei;
1154 for(ei=Edges.begin(); ei != Edges.end(); ei++)
1156 intervals[i+1]=std::make_pair(intervals[i].first+Distance((*ei).v[0]->P(),(*ei).v[1]->P()), &*ei);
1161 ScalarType edgeSum = intervals.back().first;
1162 for(i=0;i<sampleNum;++i)
1164 ScalarType val = edgeSum * RandomDouble01();
1167 typename std::vector<IntervalType>::iterator it = lower_bound(intervals.begin(),intervals.end(),std::make_pair(val,(SimpleEdge*)(0)) );
1168 assert(it != intervals.end() && it != intervals.begin());
1169 assert( ( (*(it-1)).first < val ) && ((*(it)).first >= val) );
1170 SimpleEdge * ep=(*it).second;
1171 ps.AddFace( *(ep->f), ep->EdgeBarycentricToFaceBarycentric(RandomDouble01()) );
1181static void Montecarlo(MeshType & m, VertexSampler &ps,
int sampleNum)
1183 typedef std::pair<ScalarType, FacePointer> IntervalType;
1184 std::vector< IntervalType > intervals (m.fn+1);
1187 intervals[i]=std::make_pair(0,FacePointer(0));
1189 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1192 intervals[i+1]=std::make_pair(intervals[i].first+0.5*DoubleArea(*fi), &*fi);
1195 ScalarType meshArea = intervals.back().first;
1196 for(i=0;i<sampleNum;++i)
1198 ScalarType val = meshArea * RandomDouble01();
1201 typename std::vector<IntervalType>::iterator it = lower_bound(intervals.begin(),intervals.end(),std::make_pair(val,FacePointer(0)) );
1202 assert(it != intervals.end());
1203 assert(it != intervals.begin());
1204 assert( (*(it-1)).first <val );
1205 assert( (*(it)).first >= val);
1206 ps.AddFace( *(*it).second, RandomBarycentric() );
1210static ScalarType WeightedArea(FaceType &f, PerVertexFloatAttribute &wH)
1212 ScalarType averageQ = ( wH[f.V(0)] + wH[f.V(1)] + wH[f.V(2)] )/3.0;
1213 return averageQ*averageQ*DoubleArea(f)/2.0;
1226 tri::RequirePerVertexQuality(m);
1227 tri::RequireCompactness(m);
1231 ScalarType weightedArea = 0;
1232 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1233 weightedArea += WeightedArea(*fi,rH);
1235 ScalarType samplePerAreaUnit = sampleNum/weightedArea;
1237 double floatSampleNum = 0.0;
1238 for(FaceIterator fi=m.face.begin(); fi != m.face.end(); fi++)
1241 floatSampleNum += WeightedArea(*fi,rH) * samplePerAreaUnit;
1242 int faceSampleNum = (int) floatSampleNum;
1245 for(
int i=0; i < faceSampleNum; i++)
1246 ps.AddFace(*fi,RandomBarycentric());
1248 floatSampleNum -= (double) faceSampleNum;
1256static int SingleFaceSubdivision(
int sampleNum,
const CoordType & v0,
const CoordType & v1,
const CoordType & v2, VertexSampler &ps, FacePointer fp,
bool randSample)
1262 CoordType SamplePoint;
1265 CoordType rb=RandomBarycentric();
1266 SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
1268 else SamplePoint=((v0+v1+v2)*(1.0f/3.0f));
1270 ps.AddFace(*fp,SamplePoint);
1274 int s0 = sampleNum /2;
1275 int s1 = sampleNum-s0;
1279 ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
1280 ScalarType w1 = 1.0-w0;
1282 ScalarType maxd01 = SquaredDistance(v0,v1);
1283 ScalarType maxd12 = SquaredDistance(v1,v2);
1284 ScalarType maxd20 = SquaredDistance(v2,v0);
1287 if(maxd01 > maxd20) res = 0;
1290 if(maxd12 > maxd20) res = 1;
1293 int faceSampleNum=0;
1298 case 0 : pp = v0*w0 + v1*w1;
1299 faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
1300 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1302 case 1 : pp = v1*w0 + v2*w1;
1303 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1304 faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
1306 case 2 : pp = v0*w0 + v2*w1;
1307 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1308 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1311 return faceSampleNum;
1316static void FaceSubdivision(MeshType & m, VertexSampler &ps,
int sampleNum,
bool randSample)
1319 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1320 ScalarType samplePerAreaUnit = sampleNum/area;
1321 std::vector<FacePointer> faceVec;
1322 FillAndShuffleFacePointerVector(m,faceVec);
1324 double floatSampleNum = 0.0;
1327 typename std::vector<FacePointer>::iterator fi;
1328 for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
1330 const CoordType b0(1.0, 0.0, 0.0);
1331 const CoordType b1(0.0, 1.0, 0.0);
1332 const CoordType b2(0.0, 0.0, 1.0);
1334 floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
1335 faceSampleNum = (int) floatSampleNum;
1337 faceSampleNum = SingleFaceSubdivision(faceSampleNum,b0,b1,b2,ps,*fi,randSample);
1338 floatSampleNum -= (double) faceSampleNum;
1345static int SingleFaceSubdivisionOld(
int sampleNum,
const CoordType & v0,
const CoordType & v1,
const CoordType & v2, VertexSampler &ps, FacePointer fp,
bool randSample)
1351 CoordType SamplePoint;
1354 CoordType rb=RandomBarycentric();
1355 SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
1357 else SamplePoint=((v0+v1+v2)*(1.0f/3.0f));
1359 CoordType SampleBary;
1360 InterpolationParameters(*fp,SamplePoint,SampleBary);
1361 ps.AddFace(*fp,SampleBary);
1365 int s0 = sampleNum /2;
1366 int s1 = sampleNum-s0;
1370 ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
1371 ScalarType w1 = 1.0-w0;
1373 ScalarType maxd01 = SquaredDistance(v0,v1);
1374 ScalarType maxd12 = SquaredDistance(v1,v2);
1375 ScalarType maxd20 = SquaredDistance(v2,v0);
1378 if(maxd01 > maxd20) res = 0;
1381 if(maxd12 > maxd20) res = 1;
1384 int faceSampleNum=0;
1389 case 0 : pp = v0*w0 + v1*w1;
1390 faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
1391 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1393 case 1 : pp = v1*w0 + v2*w1;
1394 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1395 faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
1397 case 2 : pp = v0*w0 + v2*w1;
1398 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1399 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1402 return faceSampleNum;
1410 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1411 ScalarType samplePerAreaUnit = sampleNum/area;
1412 std::vector<FacePointer> faceVec;
1413 FillAndShuffleFacePointerVector(m,faceVec);
1415 double floatSampleNum = 0.0;
1418 typename std::vector<FacePointer>::iterator fi;
1419 for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
1422 floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
1423 faceSampleNum = (int) floatSampleNum;
1425 faceSampleNum = SingleFaceSubdivision(faceSampleNum,(**fi).V(0)->cP(), (**fi).V(1)->cP(), (**fi).V(2)->cP(),ps,*fi,randSample);
1426 floatSampleNum -= (double) faceSampleNum;
1437static int SingleFaceSimilar(FacePointer fp, VertexSampler &ps,
int n_samples_per_edge)
1441 float segmentNum=n_samples_per_edge -1 ;
1442 float segmentLen = 1.0/segmentNum;
1444 for(i=1; i < n_samples_per_edge-1; i++)
1445 for(j=1; j < n_samples_per_edge-1-i; j++)
1448 CoordType sampleBary(i*segmentLen,j*segmentLen, 1.0 - (i*segmentLen+j*segmentLen) ) ;
1450 ps.AddFace(*fp,sampleBary);
1454static int SingleFaceSimilarDual(FacePointer fp, VertexSampler &ps,
int n_samples_per_edge,
bool randomFlag)
1458 float segmentNum=n_samples_per_edge -1 ;
1459 float segmentLen = 1.0/segmentNum;
1461 for(i=0; i < n_samples_per_edge-1; i++)
1462 for(j=0; j < n_samples_per_edge-1-i; j++)
1465 CoordType V0((i+0)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+0)*segmentLen) ) ;
1466 CoordType V1((i+1)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+1)*segmentLen+(j+0)*segmentLen) ) ;
1467 CoordType V2((i+0)*segmentLen,(j+1)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+1)*segmentLen) ) ;
1470 CoordType rb=RandomBarycentric();
1471 ps.AddFace(*fp, V0*rb[0]+V1*rb[1]+V2*rb[2]);
1472 }
else ps.AddFace(*fp,(V0+V1+V2)/3.0);
1474 if( j < n_samples_per_edge-i-2 )
1476 CoordType V3((i+1)*segmentLen,(j+1)*segmentLen, 1.0 - ((i+1)*segmentLen+(j+1)*segmentLen) ) ;
1479 CoordType rb=RandomBarycentric();
1480 ps.AddFace(*fp, V3*rb[0]+V1*rb[1]+V2*rb[2]);
1481 }
else ps.AddFace(*fp,(V3+V1+V2)/3.0);
1516static void FaceSimilar(MeshType & m, VertexSampler &ps,
int sampleNum,
bool dualFlag,
bool randomFlag)
1518 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1519 ScalarType samplePerAreaUnit = sampleNum/area;
1522 int n_samples_per_edge;
1523 double n_samples_decimal = 0.0;
1526 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1529 n_samples_decimal += 0.5*DoubleArea(*fi) * samplePerAreaUnit;
1530 int n_samples = (int) n_samples_decimal;
1536 n_samples_per_edge = (int)((sqrt(1.0+8.0*(
double)n_samples) +5.0)/2.0);
1537 n_samples = SingleFaceSimilar(&*fi,ps, n_samples_per_edge);
1539 n_samples_per_edge = (int)(sqrt((
double)n_samples) +1.0);
1540 n_samples = SingleFaceSimilarDual(&*fi,ps, n_samples_per_edge,randomFlag);
1543 n_samples_decimal -= (double) n_samples;
1557 static void SingleFaceRaster(
typename MeshType::FaceType &f, VertexSampler &ps,
1558 const Point2<typename MeshType::ScalarType> & v0,
1559 const Point2<typename MeshType::ScalarType> & v1,
1560 const Point2<typename MeshType::ScalarType> & v2,
1561 bool correctSafePointsBaryCoords=
true)
1563 typedef typename MeshType::ScalarType S;
1571 bbox.min[0] = floor(bboxf.min[0]);
1572 bbox.min[1] = floor(bboxf.min[1]);
1573 bbox.max[0] = ceil(bboxf.max[0]);
1574 bbox.max[1] = ceil(bboxf.max[1]);
1577 Point2<S> d10 = v1 - v0;
1578 Point2<S> d21 = v2 - v1;
1579 Point2<S> d02 = v0 - v2;
1582 S b0 = (bbox.min[0]-v0[0])*d10[1] - (bbox.min[1]-v0[1])*d10[0];
1583 S b1 = (bbox.min[0]-v1[0])*d21[1] - (bbox.min[1]-v1[1])*d21[0];
1584 S b2 = (bbox.min[0]-v2[0])*d02[1] - (bbox.min[1]-v2[1])*d02[0];
1595 bool flipped = !(d02 * vcg::Point2<S>(-d10[1], d10[0]) >= 0);
1598 Segment2<S> borderEdges[3];
1600 unsigned char edgeMask = 0;
1603 borderEdges[0] = Segment2<S>(v0, v1);
1604 edgeLength[0] = borderEdges[0].Length();
1608 borderEdges[1] = Segment2<S>(v1, v2);
1609 edgeLength[1] = borderEdges[1].Length();
1613 borderEdges[2] = Segment2<S>(v2, v0);
1614 edgeLength[2] = borderEdges[2].Length();
1619 double de = v0[0]*v1[1]-v0[0]*v2[1]-v1[0]*v0[1]+v1[0]*v2[1]-v2[0]*v1[1]+v2[0]*v0[1];
1621 for(
int x=bbox.min[0]-1;x<=bbox.max[0]+1;++x)
1624 S n[3] = { b0-db0-dn0, b1-db1-dn1, b2-db2-dn2};
1625 for(
int y=bbox.min[1]-1;y<=bbox.max[1]+1;++y)
1627 if( ((n[0]>=0 && n[1]>=0 && n[2]>=0) || (n[0]<=0 && n[1]<=0 && n[2]<=0)) && (de != 0))
1629 typename MeshType::CoordType baryCoord;
1630 baryCoord[0] = double(-y*v1[0]+v2[0]*y+v1[1]*x-v2[0]*v1[1]+v1[0]*v2[1]-x*v2[1])/de;
1631 baryCoord[1] = -double( x*v0[1]-x*v2[1]-v0[0]*y+v0[0]*v2[1]-v2[0]*v0[1]+v2[0]*y)/de;
1632 baryCoord[2] = 1-baryCoord[0]-baryCoord[1];
1634 ps.AddTextureSample(f, baryCoord, Point2i(x,y), 0);
1639 Point2<S> closePoint;
1644 for (
int i=0; i<3; ++i)
1646 if (edgeMask & (1 << i))
1650 if ( ((!flipped) && (n[i]<0)) ||
1651 ( flipped && (n[i]>0)) )
1653 dst = ((close = ClosestPoint(borderEdges[i], px)) - px).Norm();
1655 close.X() > px.X()-1 && close.X() < px.X()+1 &&
1656 close.Y() > px.Y()-1 && close.Y() < px.Y()+1)
1668 typename MeshType::CoordType baryCoord;
1669 if (correctSafePointsBaryCoords)
1672 baryCoord[closeEdge] = (closePoint - borderEdges[closeEdge].P1()).Norm()/edgeLength[closeEdge];
1673 baryCoord[(closeEdge+1)%3] = 1 - baryCoord[closeEdge];
1674 baryCoord[(closeEdge+2)%3] = 0;
1677 baryCoord[0] = double(-y*v1[0]+v2[0]*y+v1[1]*x-v2[0]*v1[1]+v1[0]*v2[1]-x*v2[1])/de;
1678 baryCoord[1] = -double( x*v0[1]-x*v2[1]-v0[0]*y+v0[0]*v2[1]-v2[0]*v0[1]+v2[0]*y)/de;
1679 baryCoord[2] = 1-baryCoord[0]-baryCoord[1];
1681 ps.AddTextureSample(f, baryCoord, Point2i(x,y), minDst);
1696static bool checkPoissonDisk(SampleSHT & sht,
const Point3<ScalarType> & p, ScalarType radius)
1699 std::vector<VertexType*> closests;
1700 typedef EmptyTMark<MeshType> MarkerVert;
1701 static MarkerVert mv;
1703 Box3f bb(p-Point3f(radius,radius,radius),p+Point3f(radius,radius,radius));
1704 GridGetInBox(sht, mv, bb, closests);
1706 ScalarType r2 = radius*radius;
1707 for(
int i=0; i<closests.size(); ++i)
1708 if(SquaredDistance(p,closests[i]->cP()) < r2)
1718 adaptiveRadiusFlag =
false;
1719 bestSampleChoiceFlag =
true;
1720 bestSamplePoolSize = 10;
1723 invertQuality =
false;
1726 geodesicDistanceFlag =
false;
1739 int montecarloSampleNum;
1742 bool geodesicDistanceFlag;
1743 bool bestSampleChoiceFlag;
1744 int bestSamplePoolSize;
1745 bool adaptiveRadiusFlag;
1746 float radiusVariance;
1750 MeshType *preGenMesh;
1761static VertexPointer getSampleFromCell(
Point3i &cell, MontecarloSHT & samplepool)
1763 MontecarloSHTIterator cellBegin, cellEnd;
1764 samplepool.Grid(cell, cellBegin, cellEnd);
1771static VertexPointer getBestPrecomputedMontecarloSample(
Point3i &cell, MontecarloSHT & samplepool, ScalarType diskRadius,
const PoissonDiskParam &pp)
1773 MontecarloSHTIterator cellBegin,cellEnd;
1774 samplepool.Grid(cell, cellBegin, cellEnd);
1775 VertexPointer bestSample=0;
1776 int minRemoveCnt = std::numeric_limits<int>::max();
1777 std::vector<typename MontecarloSHT::HashIterator> inSphVec;
1779 for(MontecarloSHTIterator ci=cellBegin; ci!=cellEnd && i<pp.bestSamplePoolSize; ++ci,i++)
1781 VertexPointer sp = *ci;
1782 if(pp.adaptiveRadiusFlag) diskRadius = sp->Q();
1783 int curRemoveCnt = samplepool.CountInSphere(sp->cP(),diskRadius,inSphVec);
1784 if(curRemoveCnt < minRemoveCnt)
1787 minRemoveCnt = curRemoveCnt;
1797 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
1802 meshArea = (origMesh.bbox.DimX()*origMesh.bbox.DimY() +
1803 origMesh.bbox.DimX()*origMesh.bbox.DimZ() +
1804 origMesh.bbox.DimY()*origMesh.bbox.DimZ());
1806 ScalarType diskRadius = sqrt(meshArea / (0.7 * M_PI * sampleNum));
1810static int ComputePoissonSampleNum(MeshType &origMesh, ScalarType diskRadius)
1812 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
1813 int sampleNum = meshArea / (diskRadius*diskRadius *M_PI *0.7) ;
1824static void InitRadiusHandleFromQuality(MeshType &sampleMesh, PerVertexFloatAttribute &rH, ScalarType diskRadius, ScalarType radiusVariance,
bool invert)
1826 std::pair<float,float> minmax = tri::Stat<MeshType>::ComputePerVertexQualityMinMax( sampleMesh);
1827 float minRad = diskRadius ;
1828 float maxRad = diskRadius * radiusVariance;
1829 float deltaQ = minmax.second-minmax.first;
1830 float deltaRad = maxRad-minRad;
1831 for (VertexIterator vi = sampleMesh.vert.begin(); vi != sampleMesh.vert.end(); vi++)
1833 rH[*vi] = minRad + deltaRad*((invert ? minmax.second - (*vi).Q() : (*vi).Q() - minmax.first )/deltaQ);
1842static void InitSpatialHashTable(MeshType &montecarloMesh, MontecarloSHT &montecarloSHT, ScalarType diskRadius,
1843 struct PoissonDiskParam pp=PoissonDiskParam())
1845 ScalarType cellsize = 2.0f* diskRadius / sqrt(3.0);
1846 float occupancyRatio=0;
1850 BoxType bb=montecarloMesh.bbox;
1851 assert(!bb.IsNull());
1852 bb.Offset(cellsize);
1854 int sizeX = std::max(1,
int(bb.DimX() / cellsize));
1855 int sizeY = std::max(1,
int(bb.DimY() / cellsize));
1856 int sizeZ = std::max(1,
int(bb.DimZ() / cellsize));
1857 Point3i gridsize(sizeX, sizeY, sizeZ);
1859 montecarloSHT.InitEmpty(bb, gridsize);
1861 for (VertexIterator vi = montecarloMesh.vert.begin(); vi != montecarloMesh.vert.end(); vi++)
1864 montecarloSHT.Add(&(*vi));
1867 montecarloSHT.UpdateAllocatedCells();
1868 pp.pds.gridSize = gridsize;
1869 pp.pds.gridCellNum = (int)montecarloSHT.AllocatedCells.size();
1871 occupancyRatio = float(montecarloMesh.vn) / float(montecarloSHT.AllocatedCells.size());
1874 while( occupancyRatio> 100);
1877static void PoissonDiskPruningByNumber(VertexSampler &ps, MeshType &m,
1878 size_t sampleNum, ScalarType &diskRadius,
1879 PoissonDiskParam &pp,
1880 float tolerance=0.04,
1884 size_t sampleNumMin = int(
float(sampleNum)*(1.0f-tolerance));
1885 size_t sampleNumMax = int(
float(sampleNum)*(1.0f+tolerance));
1886 float RangeMinRad = m.bbox.Diag()/50.0;
1887 float RangeMaxRad = m.bbox.Diag()/50.0;
1888 size_t RangeMinRadNum;
1889 size_t RangeMaxRadNum;
1896 RangeMinRadNum = pp.pds.sampleNum;
1898 }
while(RangeMinRadNum < sampleNum);
1904 RangeMaxRadNum = pp.pds.sampleNum;
1906 }
while(RangeMaxRadNum > sampleNum);
1909 float curRadius=RangeMaxRad;
1911 while(iterCnt<maxIter &&
1912 (pp.pds.sampleNum < sampleNumMin || pp.pds.sampleNum > sampleNumMax) )
1916 curRadius=(RangeMaxRad+RangeMinRad)/2.0f;
1919 if(pp.pds.sampleNum > sampleNum){
1920 RangeMinRad = curRadius;
1921 RangeMinRadNum = pp.pds.sampleNum;
1923 if(pp.pds.sampleNum < sampleNum){
1924 RangeMaxRad = curRadius;
1925 RangeMaxRadNum = pp.pds.sampleNum;
1928 diskRadius = curRadius;
1944 tri::RequireCompactness(montecarloMesh);
1945 if(pp.randomSeed) SamplingRandomGenerator().initialize(pp.randomSeed);
1946 if(pp.adaptiveRadiusFlag)
1947 tri::RequirePerVertexQuality(montecarloMesh);
1950 MontecarloSHT montecarloSHT;
1951 InitSpatialHashTable(montecarloMesh,montecarloSHT,diskRadius,pp);
1955 PerVertexFloatAttribute rH =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (montecarloMesh,
"radius");
1956 if(pp.adaptiveRadiusFlag)
1964 std::shuffle(montecarloSHT.AllocatedCells.begin(),montecarloSHT.AllocatedCells.end(), g);
1966 pp.pds.montecarloSampleNum = montecarloMesh.vn;
1967 pp.pds.sampleNum =0;
1972 if(pp.preGenMesh==0)
1974 typename MeshType::template PerVertexAttributeHandle<bool> fixed;
1976 for(VertexIterator vi=montecarloMesh.vert.begin();vi!=montecarloMesh.vert.end();++vi)
1980 removedCnt += montecarloSHT.RemoveInSphere(vi->cP(),diskRadius);
1985 for(VertexIterator vi =pp.preGenMesh->vert.begin(); vi!=pp.preGenMesh->vert.end();++vi)
1989 removedCnt += montecarloSHT.RemoveInSphere(vi->cP(),diskRadius);
1992 montecarloSHT.UpdateAllocatedCells();
1994 vertex::ApproximateGeodesicDistanceFunctor<VertexType> GDF;
1995 while(!montecarloSHT.AllocatedCells.empty())
1998 for (
size_t i = 0; i < montecarloSHT.AllocatedCells.size(); i++)
2000 if( montecarloSHT.EmptyCell(montecarloSHT.AllocatedCells[i]) )
continue;
2001 ScalarType currentRadius =diskRadius;
2003 if(pp.bestSampleChoiceFlag)
2004 sp = getBestPrecomputedMontecarloSample(montecarloSHT.AllocatedCells[i], montecarloSHT, diskRadius, pp);
2006 sp = getSampleFromCell(montecarloSHT.AllocatedCells[i], montecarloSHT);
2008 if(pp.adaptiveRadiusFlag)
2009 currentRadius = rH[sp];
2013 if(pp.geodesicDistanceFlag) removedCnt += montecarloSHT.RemoveInSphereNormal(sp->cP(),sp->cN(),GDF,currentRadius);
2014 else removedCnt += montecarloSHT.RemoveInSphere(sp->cP(),currentRadius);
2016 montecarloSHT.UpdateAllocatedCells();
2019 pp.pds.gridTime = t1-t0;
2020 pp.pds.pruneTime = t2-t1;
2037 MontecarloSHT montecarloSHTVec[5];
2044 ScalarType cellsize = 2.0f* diskRadius / sqrt(3.0);
2047 BoxType bb=origMesh.bbox;
2048 bb.Offset(cellsize);
2050 int sizeX = std::max(1.0f,bb.DimX() / cellsize);
2051 int sizeY = std::max(1.0f,bb.DimY() / cellsize);
2052 int sizeZ = std::max(1.0f,bb.DimZ() / cellsize);
2053 Point3i gridsize(sizeX, sizeY, sizeZ);
2057 checkSHT.InitEmpty(bb, gridsize);
2073 montecarloSHTVec[0].InitEmpty(bb, gridsize);
2075 for (VertexIterator vi = montecarloMesh.vert.begin(); vi != montecarloMesh.vert.end(); vi++)
2076 montecarloSHTVec[0].Add(&(*vi));
2077 montecarloSHTVec[0].UpdateAllocatedCells();
2080 PerVertexFloatAttribute rH =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (montecarloMesh,
"radius");
2081 if(pp.adaptiveRadiusFlag)
2086 MontecarloSHT &montecarloSHT = montecarloSHTVec[level];
2090 montecarloSHT.InitEmpty(bb, gridsize);
2092 for (
typename MontecarloSHT::HashIterator hi = montecarloSHTVec[level-1].hash_table.begin(); hi != montecarloSHTVec[level-1].hash_table.end(); hi++)
2093 montecarloSHT.Add((*hi).second);
2094 montecarloSHT.UpdateAllocatedCells();
2098 std::random_device rd;
2102 std::shuffle(montecarloSHT.AllocatedCells.begin(),montecarloSHT.AllocatedCells.end(), g);
2106 int removedCnt=montecarloSHT.hash_table.size();
2107 int addedCnt=checkSHT.hash_table.size();
2108 for (
int i = 0; i < montecarloSHT.AllocatedCells.size(); i++)
2110 for(
int j=0;j<4;j++)
2112 if( montecarloSHT.EmptyCell(montecarloSHT.AllocatedCells[i]) )
continue;
2115 typename MontecarloSHT::HashIterator hi = montecarloSHT.hash_table.find(montecarloSHT.AllocatedCells[i]);
2117 if(hi==montecarloSHT.hash_table.end()) {
break;}
2118 VertexPointer sp = (*hi).second;
2120 ScalarType sampleRadius = diskRadius;
2121 if(pp.adaptiveRadiusFlag) sampleRadius = rH[sp];
2122 if (checkPoissonDisk(checkSHT, sp->cP(), sampleRadius))
2125 montecarloSHT.RemoveCell(sp);
2130 montecarloSHT.RemovePunctual(sp);
2133 addedCnt = checkSHT.hash_table.size()-addedCnt;
2134 removedCnt = removedCnt-montecarloSHT.hash_table.size();
2158static void Texture(MeshType & m, VertexSampler &ps,
int textureWidth,
int textureHeight,
bool correctSafePointsBaryCoords=
true)
2160typedef Point2<ScalarType> Point2x;
2162 for(FaceIterator fi=m.face.begin(); fi != m.face.end(); fi++)
2166 for(
int i=0;i<3;++i)
2167 ti[i]=Point2x((*fi).WT(i).U() * textureWidth - 0.5, (*fi).WT(i).V() * textureHeight - 0.5);
2170 SingleFaceRaster(*fi, ps, ti[0],ti[1],ti[2], correctSafePointsBaryCoords);
2174typedef GridStaticPtr<FaceType, ScalarType > TriMeshGrid;
2181tri::FaceTmark<MeshType> markerFunctor;
2185static void RegularRecursiveOffset(MeshType & m, std::vector<CoordType> &pvec, ScalarType offset,
float minDiag)
2192 rrp.markerFunctor.SetMesh(&m);
2194 rrp.gM.Set(m.face.begin(),m.face.end(),bb);
2198 rrp.minDiag=minDiag;
2199 SubdivideAndSample(m, pvec, bb, rrp, bb.
Diag());
2202static void SubdivideAndSample(MeshType & m, std::vector<CoordType> &pvec,
const Box3<ScalarType> bb, RRParam &rrp,
float curDiag)
2204 CoordType startPt = bb.
Center();
2208 FaceType *nearestF=0;
2209 ScalarType dist_upper_bound = curDiag+rrp.offset;
2210 CoordType closestPt;
2211 vcg::face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
2212 dist=dist_upper_bound;
2213 nearestF = rrp.gM.GetClosest(PDistFunct,rrp.markerFunctor,startPt,dist_upper_bound,dist,closestPt);
2215 if(dist < dist_upper_bound)
2217 if(curDiag/3 < rrp.minDiag)
2220 pvec.push_back(closestPt);
2225 CoordType delta = startPt-closestPt;
2226 pvec.push_back(closestPt+delta*(rrp.offset/dist));
2230 if(curDiag < rrp.minDiag)
return;
2231 CoordType hs = (bb.
max-bb.
min)/2;
2232 for(
int i=0;i<2;i++)
2233 for(
int j=0;j<2;j++)
2234 for(
int k=0;k<2;k++)
2235 SubdivideAndSample(m, pvec,
2236 BoxType(CoordType( bb.
min[0]+i*hs[0], bb.
min[1]+j*hs[1], bb.
min[2]+k*hs[2]),
2237 CoordType(startPt[0]+i*hs[0], startPt[1]+j*hs[1], startPt[2]+k*hs[2]) ),
2245template <
class MeshType>
2246typename MeshType::ScalarType ComputePoissonDiskRadius(MeshType &origMesh,
int sampleNum)
2248 typedef typename MeshType::ScalarType ScalarType;
2249 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
2254 meshArea = (origMesh.bbox.DimX()*origMesh.bbox.DimY() +
2255 origMesh.bbox.DimX()*origMesh.bbox.DimZ() +
2256 origMesh.bbox.DimY()*origMesh.bbox.DimZ());
2258 ScalarType diskRadius = sqrt(meshArea / (0.7 * M_PI * sampleNum));
2264template <
class MeshType>
2265void MontecarloSampling(MeshType &m,
2269 typedef tri::MeshSampler<MeshType> BaseSampler;
2270 MeshSampler<MeshType> mcSampler(&mm);
2275template <
class MeshType>
2276void MontecarloSampling(MeshType &m,
2277 std::vector<Point3f> &montercarloSamples,
2280 typedef tri::TrivialSampler<MeshType> BaseSampler;
2281 BaseSampler mcSampler(montercarloSamples);
2287template <
class MeshType>
2288void PoissonSampling(MeshType &m,
2289 std::vector<typename MeshType::CoordType> &poissonSamples,
2291 typename MeshType::ScalarType &radius,
2292 typename MeshType::ScalarType radiusVariance=1,
2293 typename MeshType::ScalarType PruningByNumberTolerance=0.04f,
2294 unsigned int randSeed=0)
2297 typedef tri::TrivialSampler<MeshType> BaseSampler;
2298 typedef tri::MeshSampler<MeshType> MontecarloSampler;
2300 typename tri::SurfaceSampling<MeshType, BaseSampler>::PoissonDiskParam pp;
2304 if(radius>0 && sampleNum==0) sampleNum = tri::SurfaceSampling<MeshType,BaseSampler>::ComputePoissonSampleNum(m,radius);
2306 pp.pds.sampleNum = sampleNum;
2307 pp.randomSeed = randSeed;
2308 poissonSamples.clear();
2310 MeshType MontecarloMesh;
2313 MontecarloSampler mcSampler(MontecarloMesh);
2314 BaseSampler pdSampler(poissonSamples);
2316 if(randSeed) tri::SurfaceSampling<MeshType,MontecarloSampler>::SamplingRandomGenerator().initialize(randSeed);
2321 pp.pds.montecarloTime = t1-t0;
2323 if(radiusVariance !=1)
2325 pp.adaptiveRadiusFlag=
true;
2326 pp.radiusVariance=radiusVariance;
2329 else tri::SurfaceSampling<MeshType,BaseSampler>::PoissonDiskPruningByNumber(pdSampler, MontecarloMesh, sampleNum, radius,pp,PruningByNumberTolerance);
2331 pp.pds.totalTime = t2-t0;
2338template <
class MeshType>
2340 std::vector<typename MeshType::VertexPointer> &poissonSamples,
2341 float radius,
unsigned int randSeed=0)
2345 pp.randomSeed = randSeed;
2348 BaseSampler pdSampler;
2350 poissonSamples = pdSampler.sampleVec;
2359template <
class MeshType>
2361 std::vector<typename MeshType::CoordType> &poissonSamples,
2362 float radius,
unsigned int randSeed=0)
2364 std::vector<typename MeshType::VertexPointer> poissonSamplesVP;
2366 poissonSamples.resize(poissonSamplesVP.size());
2367 for(
size_t i=0;i<poissonSamplesVP.size();++i)
2368 poissonSamples[i]=poissonSamplesVP[i]->P();
2378template <
class MeshType>
2380 std::vector<typename MeshType::VertexPointer> &poissonSamples,
2381 typename MeshType::ScalarType & radius,
2383 float tolerance=0.04,
2385 unsigned int randSeed=0)
2387 size_t sampleNumMin = int(
float(sampleNum)*(1.0f-tolerance));
2388 size_t sampleNumMax = int(
float(sampleNum)*(1.0f+tolerance));
2389 float RangeMinRad = m.bbox.Diag()/10.0f;
2390 float RangeMaxRad = m.bbox.Diag()/10.0f;
2391 size_t RangeMinSampleNum;
2392 size_t RangeMaxSampleNum;
2393 std::vector<typename MeshType::VertexPointer> poissonSamplesTmp;
2399 RangeMinSampleNum = poissonSamplesTmp.size();
2400 }
while(RangeMinSampleNum < sampleNumMin);
2406 RangeMaxSampleNum = poissonSamplesTmp.size();
2407 }
while(RangeMaxSampleNum > sampleNumMax);
2411 while(iterCnt<maxIter &&
2412 (poissonSamplesTmp.size() < sampleNumMin || poissonSamplesTmp.size() > sampleNumMax) )
2414 curRadius=(RangeMaxRad+RangeMinRad)/2.0f;
2417 if(poissonSamplesTmp.size() >
size_t(sampleNum))
2418 RangeMinRad = curRadius;
2419 if(poissonSamplesTmp.size() <
size_t(sampleNum))
2420 RangeMaxRad = curRadius;
2423 swap(poissonSamples,poissonSamplesTmp);
Point3< BoxScalarType > max
max coordinate point
Definition: box3.h:51
Point3< BoxScalarType > Center() const
Return the center of the box.
Definition: box3.h:250
void Offset(const BoxScalarType s)
Definition: box3.h:75
Point3< BoxScalarType > min
min coordinate point
Definition: box3.h:49
BoxScalarType Diag() const
Return the lenght of the diagonal of the box .
Definition: box3.h:240
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater< VertexPointer > &pu)
Add n vertices to the mesh. Function to add n vertices to the mesh. The elements are added always to ...
Definition: allocate.h:189
Definition: point_sampling.h:230
double volume
from the wikipedia defintion RMS DIST is sqrt(Sum(distances^2)/n), here we store Sum(distances^2)
Definition: point_sampling.h:258
MeshType * closestPtMesh
the mesh containing the sample points
Definition: point_sampling.h:248
MeshType * samplePtMesh
the mesh for which we search the closest points.
Definition: point_sampling.h:247
MetroMeshVertexGrid unifGridVert
the mesh containing the corresponding closest points that have been found
Definition: point_sampling.h:250
Definition: point_sampling.h:177
Definition: point_sampling.h:363
CallBackPos * cb
the source mesh for which we search the closest points (e.g. the mesh from which we take colors etc).
Definition: point_sampling.h:376
Definition: point_sampling.h:515
Definition: point_sampling.h:2177
Main Class of the Sampling framework.
Definition: point_sampling.h:476
static void Montecarlo(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:1181
static void HierarchicalPoissonDisk(MeshType &origMesh, VertexSampler &ps, MeshType &montecarloMesh, ScalarType diskRadius, const struct PoissonDiskParam pp=PoissonDiskParam())
Definition: point_sampling.h:2033
static void VertexAreaUniform(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:710
static void VertexWeighted(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:672
static void VertexCrease(MeshType &m, VertexSampler &ps)
Definition: point_sampling.h:969
static void VertexUniform(MeshType &m, VertexSampler &ps, int sampleNum, bool onlySelected)
Sample the vertices in a uniform way. Each vertex has the same probabiltiy of being chosen.
Definition: point_sampling.h:758
static void FaceSubdivision(MeshType &m, VertexSampler &ps, int sampleNum, bool randSample)
Compute a sampling of the surface where the points are regularly scattered over the face surface usin...
Definition: point_sampling.h:1316
static void PoissonDiskPruning(VertexSampler &ps, MeshType &montecarloMesh, ScalarType diskRadius, PoissonDiskParam &pp)
Definition: point_sampling.h:1941
static ScalarType ComputePoissonDiskRadius(MeshType &origMesh, int sampleNum)
Estimate the radius r that you should give to get a certain number of samples in a Poissson Disk Dist...
Definition: point_sampling.h:1795
EdgeSamplingRoundingStrategy
The EdgeSamplingStrategy enum determines the sampling strategy for edge meshes. Given a sampling radi...
Definition: point_sampling.h:793
static void VertexBorder(MeshType &m, VertexSampler &ps)
Sample all the border vertices.
Definition: point_sampling.h:958
static void VertexBorderCorner(MeshType &m, VertexSampler &ps, ScalarType angleRad)
Sample all the border corner vertices.
Definition: point_sampling.h:944
static void EdgeMeshUniform(MeshType &m, VertexSampler &ps, float radius, EdgeSamplingRoundingStrategy strategy=Floor)
Definition: point_sampling.h:815
static void FaceSubdivisionOld(MeshType &m, VertexSampler &ps, int sampleNum, bool randSample)
Compute a sampling of the surface where the points are regularly scattered over the face surface usin...
Definition: point_sampling.h:1407
static int Poisson(double lambda)
Definition: point_sampling.h:632
static void MontecarloPoisson(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:1114
static void WeightedMontecarlo(MeshType &m, VertexSampler &ps, int sampleNum, float variance)
Definition: point_sampling.h:1224
static void InitRadiusHandleFromQuality(MeshType &sampleMesh, PerVertexFloatAttribute &rH, ScalarType diskRadius, ScalarType radiusVariance, bool invert)
Definition: point_sampling.h:1824
static void EdgeMontecarlo(MeshType &m, VertexSampler &ps, int sampleNum, bool sampleAllEdges)
Definition: point_sampling.h:1140
Definition: point_sampling.h:137
A basic sampler class that show the required interface used by the SurfaceSampling class.
Definition: point_sampling.h:72
static void Box(ComputeMeshType &m)
Calculates the bounding box of the given mesh m.
Definition: bounding.h:45
Management, updating and computation of per-vertex and per-face flags (like border flags).
Definition: flag.h:44
static void PerFaceNormalized(ComputeMeshType &m)
Equivalent to PerFace() and NormalizePerFace()
Definition: normal.h:276
static size_t VertexCornerBorder(MeshType &m, ScalarType angleRad, bool preserveSelection=false)
Select the border vertices that form a corner along the border with an angle that is below a certain ...
Definition: selection.h:656
Auxiliary data structure for computing face face adjacency information.
Definition: topology.h:149
Generation of per-vertex and per-face topological information.
Definition: topology.h:43
void PoissonPruningExact(MeshType &m, std::vector< typename MeshType::VertexPointer > &poissonSamples, typename MeshType::ScalarType &radius, int sampleNum, float tolerance=0.04, int maxIter=20, unsigned int randSeed=0)
Very simple wrapping for the Exact Poisson Disk Pruning.
Definition: point_sampling.h:2379
void PoissonPruning(MeshType &m, std::vector< typename MeshType::VertexPointer > &poissonSamples, float radius, unsigned int randSeed=0)
Low level wrapper for Poisson Disk Pruning.
Definition: point_sampling.h:2339
Definition: point_sampling.h:1731
Definition: point_sampling.h:1715