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>
70 template <
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 )
135 template <
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); }
175 template <
class MeshType>
179 typedef typename MeshType::VertexType VertexType;
180 typedef typename MeshType::FaceType FaceType;
181 typedef typename MeshType::CoordType CoordType;
184 perFaceNormal =
false;
195 void AddVert(
const VertexType &p)
198 m.vert.back().ImportData(p);
201 void AddFace(
const FaceType &f, CoordType p)
204 m.vert.back().P() = f.cP(0)*p[0] + f.cP(1)*p[1] +f.cP(2)*p[2];
205 if(perFaceNormal) m.vert.back().N() = f.cN();
206 else m.vert.back().N() = f.cV(0)->N()*p[0] + f.cV(1)->N()*p[1] + f.cV(2)->N()*p[2];
207 if(tri::HasPerVertexQuality(m) )
208 m.vert.back().Q() = f.cV(0)->Q()*p[0] + f.cV(1)->Q()*p[1] + f.cV(2)->Q()*p[2];
219 template <
class MeshType>
222 typedef typename MeshType::FaceType FaceType;
223 typedef typename MeshType::VertexType VertexType;
224 typedef typename MeshType::CoordType CoordType;
225 typedef typename MeshType::ScalarType ScalarType;
226 typedef GridStaticPtr<FaceType, ScalarType > MetroMeshFaceGrid;
227 typedef GridStaticPtr<VertexType, ScalarType > MetroMeshVertexGrid;
231 HausdorffSampler(MeshType* _m, MeshType* _sampleMesh=0, MeshType* _closestMesh=0 ) :markerFunctor(_m)
234 init(_sampleMesh,_closestMesh);
242 MetroMeshFaceGrid unifGridFace;
255 bool useVertexSampling;
256 ScalarType dist_upper_bound;
257 typedef typename tri::FaceTmark<MeshType> MarkerFace;
258 MarkerFace markerFunctor;
261 float getMeanDist()
const {
return mean_dist / n_total_samples; }
262 float getMinDist()
const {
return min_dist ; }
263 float getMaxDist()
const {
return max_dist ; }
264 float getRMSDist()
const {
return sqrt(RMS_dist / n_total_samples); }
266 void init(MeshType* _sampleMesh=0, MeshType* _closestMesh=0 )
273 if(m->fn==0) useVertexSampling =
true;
274 else useVertexSampling =
false;
276 if(useVertexSampling)
unifGridVert.Set(m->vert.begin(),m->vert.end());
277 else unifGridFace.Set(m->face.begin(),m->face.end());
278 markerFunctor.SetMesh(m);
279 hist.SetRange(0.0, m->bbox.Diag()/100.0, 100);
281 min_dist = std::numeric_limits<double>::max();
288 void AddFace(
const FaceType &f, CoordType interp)
290 CoordType startPt = f.cP(0)*interp[0] + f.cP(1)*interp[1] +f.cP(2)*interp[2];
291 CoordType startN = f.cV(0)->cN()*interp[0] + f.cV(1)->cN()*interp[1] +f.cV(2)->cN()*interp[2];
292 AddSample(startPt,startN);
295 void AddVert(VertexType &p)
297 p.Q()=AddSample(p.cP(),p.cN());
301 float AddSample(
const CoordType &startPt,
const CoordType &startN)
305 ScalarType dist = dist_upper_bound;
308 FaceType *nearestF=0;
309 VertexType *nearestV=0;
310 vcg::face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
311 dist=dist_upper_bound;
312 if(useVertexSampling)
313 nearestV = tri::GetClosestVertex<MeshType,MetroMeshVertexGrid>(*m,
unifGridVert,startPt,dist_upper_bound,dist);
315 nearestF = unifGridFace.GetClosest(PDistFunct,markerFunctor,startPt,dist_upper_bound,dist,closestPt);
318 if(dist == dist_upper_bound)
321 if(dist > max_dist) max_dist = dist;
322 if(dist < min_dist) min_dist = dist;
325 RMS_dist += dist*dist;
328 hist.Add((
float)fabs(dist));
352 template <
class MeshType>
355 typedef typename MeshType::FaceType FaceType;
356 typedef typename MeshType::VertexType VertexType;
357 typedef typename MeshType::CoordType CoordType;
358 typedef typename MeshType::ScalarType ScalarType;
359 typedef GridStaticPtr<FaceType, ScalarType > MetroMeshGrid;
360 typedef GridStaticPtr<VertexType, ScalarType > VertexMeshGrid;
370 MetroMeshGrid unifGridFace;
371 VertexMeshGrid unifGridVert;
372 bool useVertexSampling;
375 typedef tri::FaceTmark<MeshType> MarkerFace;
376 MarkerFace markerFunctor;
383 bool storeDistanceAsQualityFlag;
384 float dist_upper_bound;
385 void init(MeshType *_m, CallBackPos *_cb=0,
int targetSz=0)
391 storeDistanceAsQualityFlag=
false;
394 if(m->fn==0) useVertexSampling =
true;
395 else useVertexSampling =
false;
397 if(useVertexSampling) unifGridVert.Set(m->vert.begin(),m->vert.end());
398 else unifGridFace.Set(m->face.begin(),m->face.end());
399 markerFunctor.SetMesh(m);
402 sampleNum = targetSz;
408 void AddVert(VertexType &p)
412 CoordType closestPt, normf, bestq, ip;
413 ScalarType dist = dist_upper_bound;
414 const CoordType &startPt= p.cP();
416 if(useVertexSampling)
418 VertexType *nearestV=0;
419 nearestV = tri::GetClosestVertex<MeshType,VertexMeshGrid>(*m,unifGridVert,startPt,dist_upper_bound,dist);
420 if(
cb)
cb(sampleCnt++*100/sampleNum,
"Resampling Vertex attributes");
421 if(storeDistanceAsQualityFlag) p.Q() = dist;
422 if(dist == dist_upper_bound) return ;
424 if(coordFlag) p.P()=nearestV->P();
425 if(colorFlag) p.C() = nearestV->C();
426 if(normalFlag) p.N() = nearestV->N();
427 if(qualityFlag) p.Q()= nearestV->Q();
428 if(selectionFlag)
if(nearestV->IsS()) p.SetS();
432 FaceType *nearestF=0;
433 vcg::face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
434 dist=dist_upper_bound;
435 if(
cb)
cb(sampleCnt++*100/sampleNum,
"Resampling Vertex attributes");
436 nearestF = unifGridFace.GetClosest(PDistFunct,markerFunctor,startPt,dist_upper_bound,dist,closestPt);
437 if(dist == dist_upper_bound) return ;
440 InterpolationParameters(*nearestF,(*nearestF).cN(),closestPt, interp);
441 interp[2]=1.0-interp[1]-interp[0];
443 if(coordFlag) p.P()=closestPt;
444 if(colorFlag) p.C().lerp(nearestF->V(0)->C(),nearestF->V(1)->C(),nearestF->V(2)->C(),interp);
445 if(normalFlag) p.N() = nearestF->V(0)->N()*interp[0] + nearestF->V(1)->N()*interp[1] + nearestF->V(2)->N()*interp[2];
446 if(qualityFlag) p.Q()= nearestF->V(0)->Q()*interp[0] + nearestF->V(1)->Q()*interp[1] + nearestF->V(2)->Q()*interp[2];
447 if(selectionFlag)
if(nearestF->IsS()) p.SetS();
465 template <
class MeshType,
class VertexSampler = TrivialSampler< MeshType> >
468 typedef typename MeshType::CoordType CoordType;
469 typedef typename MeshType::BoxType BoxType;
470 typedef typename MeshType::ScalarType ScalarType;
471 typedef typename MeshType::VertexType VertexType;
472 typedef typename MeshType::VertexPointer VertexPointer;
473 typedef typename MeshType::VertexIterator VertexIterator;
474 typedef typename MeshType::EdgeType EdgeType;
475 typedef typename MeshType::EdgeIterator EdgeIterator;
476 typedef typename MeshType::FaceType FaceType;
477 typedef typename MeshType::FacePointer FacePointer;
478 typedef typename MeshType::FaceIterator FaceIterator;
479 typedef typename MeshType::FaceContainer FaceContainer;
481 typedef typename vcg::SpatialHashTable<FaceType, ScalarType> MeshSHT;
482 typedef typename vcg::SpatialHashTable<FaceType, ScalarType>::CellIterator MeshSHTIterator;
483 typedef typename vcg::SpatialHashTable<VertexType, ScalarType> MontecarloSHT;
484 typedef typename vcg::SpatialHashTable<VertexType, ScalarType>::CellIterator MontecarloSHTIterator;
485 typedef typename vcg::SpatialHashTable<VertexType, ScalarType> SampleSHT;
486 typedef typename vcg::SpatialHashTable<VertexType, ScalarType>::CellIterator SampleSHTIterator;
488 typedef typename MeshType::template PerVertexAttributeHandle<float> PerVertexFloatAttribute;
492 static math::MarsenneTwisterRNG &SamplingRandomGenerator()
494 static math::MarsenneTwisterRNG rnd;
500 static unsigned int RandomInt(
unsigned int i)
502 return (SamplingRandomGenerator().generate(i));
508 typedef unsigned int result_type;
510 static constexpr result_type min() {
return 0;}
511 static constexpr result_type max() {
return std::numeric_limits<result_type>::max();}
512 result_type operator()() {
return SamplingRandomGenerator().generate(_max);}
518 static double RandomDouble01()
520 return SamplingRandomGenerator().generate01();
524 static double LnFac(
int n) {
529 C0 = 0.918938533204672722,
535 static double fac_table[FAK_LEN];
536 static bool initialized =
false;
541 if (n < 0) assert(0);
546 double sum = fac_table[0] = 0.;
547 for (
int i=1; i<FAK_LEN; i++) {
548 sum += log(
double(i));
558 return (n1 + 0.5)*log(n1) - n1 + C0 + r*(C1 + r*r*C3);
561 static int PoissonRatioUniforms(
double L) {
583 const double SHAT1 = 2.943035529371538573;
584 const double SHAT2 = 0.8989161620588987408;
590 double pois_a = L + 0.5;
592 double pois_g = log(L);
593 double pois_f0 = mode * pois_g - LnFac(mode);
594 double pois_h = sqrt(SHAT1 * (L+0.5)) + SHAT2;
595 double pois_bound = (int)(pois_a + 6.0 * pois_h);
598 u = RandomDouble01();
599 if (u == 0)
continue;
600 x = pois_a + pois_h * (RandomDouble01() - 0.5) / u;
601 if (x < 0 || x >= pois_bound)
continue;
603 lf = k * pois_g - LnFac(k) - pois_f0;
604 if (lf >= u * (4.0 - u) - 3.0)
break;
605 if (u * (u - lf) > 1.0)
continue;
606 if (2.0 * log(u) <= lf)
break;
625 if(lambda>50)
return PoissonRatioUniforms(lambda);
626 double L = exp(-lambda);
632 p = p*RandomDouble01();
639 static void AllVertex(MeshType & m, VertexSampler &ps)
641 AllVertex(m, ps,
false);
644 static void AllVertex(MeshType & m, VertexSampler &ps,
bool onlySelected)
647 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
649 if ((!onlySelected) || ((*vi).IsS()))
667 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
671 ScalarType samplePerUnit = sampleNum/qSum;
672 ScalarType floatSampleNum =0;
673 std::vector<VertexPointer> vertVec;
674 FillAndShuffleVertexPointerVector(m,vertVec);
676 std::vector<bool> vertUsed(m.vn,
false);
679 while(cnt < sampleNum)
683 floatSampleNum += vertVec[i]->Q() * samplePerUnit;
684 int vertSampleNum = (int) floatSampleNum;
685 floatSampleNum -= (float) vertSampleNum;
688 if(vertSampleNum > 1)
690 ps.AddVert(*vertVec[i]);
704 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
709 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
712 ScalarType areaThird = DoubleArea(*fi)/6.0;
713 (*fi).V(0)->Q()+=areaThird;
714 (*fi).V(1)->Q()+=areaThird;
715 (*fi).V(2)->Q()+=areaThird;
721 static void FillAndShuffleFacePointerVector(MeshType & m, std::vector<FacePointer> &faceVec)
723 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
724 if(!(*fi).IsD()) faceVec.push_back(&*fi);
726 assert((
int)faceVec.size()==m.fn);
731 MarsenneTwisterURBG g(faceVec.size());
732 std::shuffle(faceVec.begin(),faceVec.end(), g);
734 static void FillAndShuffleVertexPointerVector(MeshType & m, std::vector<VertexPointer> &vertVec)
736 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
737 if(!(*vi).IsD()) vertVec.push_back(&*vi);
739 assert((
int)vertVec.size()==m.vn);
744 MarsenneTwisterURBG g(vertVec.size());
745 std::shuffle(vertVec.begin(),vertVec.end(), g);
749 static void VertexUniform(MeshType & m, VertexSampler &ps,
int sampleNum,
bool onlySelected)
751 if (sampleNum >= m.vn) {
752 AllVertex(m, ps, onlySelected);
756 std::vector<VertexPointer> vertVec;
757 FillAndShuffleVertexPointerVector(m, vertVec);
760 for (
int i = 0; ((i < m.vn) && (added < sampleNum)); ++i)
761 if (!(*vertVec[i]).IsD())
762 if ((!onlySelected) || (*vertVec[i]).IsS())
764 ps.AddVert(*vertVec[i]);
771 static void VertexUniform(MeshType & m, VertexSampler &ps,
int sampleNum)
799 tri::RequireEEAdjacency(m);
800 tri::RequireCompactness(m);
801 tri::RequirePerEdgeFlags(m);
802 tri::RequirePerVertexFlags(m);
805 tri::MeshAssert<MeshType>::EEOneManifold(m);
807 for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
811 edge::Pos<EdgeType> ep(&*ei,0);
812 edge::Pos<EdgeType> startep = ep;
818 }
while (startep != ep);
822 assert(ep == startep);
826 edge::Pos<EdgeType> altEp = ep;
828 while (altEp != startep) {
829 if (altEp.V()->cP() < ep.V()->cP())
837 const auto dir0 = ep.VFlip()->cP() - ep.V()->cP();
839 const auto dir1 = ep.VFlip()->cP() - ep.V()->cP();
851 edge::Pos<EdgeType> altEp = ep;
854 }
while (!altEp.IsBorder());
856 if (altEp.V()->cP() < ep.V()->cP())
862 ScalarType totalLen = 0;
868 totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
870 }
while (!ep.E()->IsV() && !ep.IsBorder());
874 totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
877 VertexPointer startVertex = ep.V();
882 double div = double(totalLen) / radius;
885 sampleNum = int(round(div));
888 sampleNum = int(ceil(div));
891 sampleNum = int(floor(div));
895 assert(sampleNum >= 0);
897 ScalarType sampleDist = totalLen / sampleNum;
900 ScalarType curLen = 0;
902 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
906 assert(ep.E()->IsV());
907 ScalarType edgeLen = Distance(ep.VFlip()->cP(), ep.V()->cP());
908 ScalarType d0 = curLen;
909 ScalarType d1 = d0 + edgeLen;
911 while (d1 > sampleCnt * sampleDist && sampleCnt < sampleNum)
913 ScalarType off = (sampleCnt * sampleDist - d0) / edgeLen;
915 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 1.0 - off : off);
919 }
while(!ep.IsBorder() && ep.V() != startVertex);
921 if(ep.V() != startVertex)
923 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
938 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
940 if(vi->IsS()) ps.AddVert(*vi);
963 std::vector< SimpleEdge > Edges;
964 typename std::vector< SimpleEdge >::iterator ei;
967 typename MeshType::template PerVertexAttributeHandle <int> hv =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<int> (m);
969 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
975 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
983 static void FaceUniform(MeshType & m, VertexSampler &ps,
int sampleNum)
985 if(sampleNum>=m.fn) {
990 std::vector<FacePointer> faceVec;
991 FillAndShuffleFacePointerVector(m,faceVec);
993 for(
int i =0; i< sampleNum; ++i)
994 ps.AddFace(*faceVec[i],Barycenter(*faceVec[i]));
997 static void AllFace(MeshType & m, VertexSampler &ps)
1000 for(fi=m.face.begin();fi!=m.face.end();++fi)
1003 ps.AddFace(*fi,Barycenter(*fi));
1008 static void AllEdge(MeshType & m, VertexSampler &ps)
1011 typedef typename UpdateTopology<MeshType>::PEdge SimpleEdge;
1012 std::vector< SimpleEdge > Edges;
1013 typename std::vector< SimpleEdge >::iterator ei;
1014 UpdateTopology<MeshType>::FillUniqueEdgeVector(m,Edges);
1016 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1017 ps.AddFace(*(*ei).f,ei->EdgeBarycentricToFaceBarycentric(0.5));
1024 static void EdgeUniform(MeshType & m, VertexSampler &ps,
int sampleNum,
bool sampleFauxEdge=
true)
1026 typedef typename UpdateTopology<MeshType>::PEdge SimpleEdge;
1028 std::vector< SimpleEdge > Edges;
1029 UpdateTopology<MeshType>::FillUniqueEdgeVector(m,Edges,sampleFauxEdge);
1032 typename std::vector< SimpleEdge >::iterator ei;
1033 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1034 edgeSum+=Distance((*ei).v[0]->P(),(*ei).v[1]->P());
1036 float sampleLen = edgeSum/sampleNum;
1038 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1040 float len = Distance((*ei).v[0]->P(),(*ei).v[1]->P());
1041 float samplePerEdge = floor((len+rest)/sampleLen);
1042 rest = (len+rest) - samplePerEdge * sampleLen;
1043 float step = 1.0/(samplePerEdge+1);
1044 for(
int i=0;i<samplePerEdge;++i)
1046 CoordType interp(0,0,0);
1047 interp[ (*ei).z ]=step*(i+1);
1048 interp[((*ei).z+1)%3]=1.0-step*(i+1);
1049 ps.AddFace(*(*ei).f,interp);
1057 static CoordType RandomBarycentric()
1059 return math::GenerateBarycentricUniform<ScalarType>(SamplingRandomGenerator());
1063 static CoordType RandomPointInTriangle(
const FaceType &f)
1065 CoordType u = RandomBarycentric();
1066 return f.cP(0)*u[0] + f.cP(1)*u[1] + f.cP(2)*u[2];
1069 static void StratifiedMontecarlo(MeshType & m, VertexSampler &ps,
int sampleNum)
1071 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1072 ScalarType samplePerAreaUnit = sampleNum/area;
1074 double floatSampleNum = 0.0;
1077 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1081 floatSampleNum += 0.5*DoubleArea(*fi) * samplePerAreaUnit;
1082 int faceSampleNum = (int) floatSampleNum;
1085 for(
int i=0; i < faceSampleNum; i++)
1086 ps.AddFace(*fi,RandomBarycentric());
1087 floatSampleNum -= (double) faceSampleNum;
1107 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1108 ScalarType samplePerAreaUnit = sampleNum/area;
1111 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1114 float areaT=DoubleArea(*fi) * 0.5f;
1115 int faceSampleNum =
Poisson(areaT*samplePerAreaUnit);
1118 for(
int i=0; i < faceSampleNum; i++)
1119 ps.AddFace(*fi,RandomBarycentric());
1131 static void EdgeMontecarlo(MeshType & m, VertexSampler &ps,
int sampleNum,
bool sampleAllEdges)
1134 std::vector< SimpleEdge > Edges;
1137 assert(!Edges.empty());
1139 typedef std::pair<ScalarType, SimpleEdge*> IntervalType;
1140 std::vector< IntervalType > intervals (Edges.size()+1);
1142 intervals[i]=std::make_pair(0,(SimpleEdge*)(0));
1144 typename std::vector< SimpleEdge >::iterator ei;
1145 for(ei=Edges.begin(); ei != Edges.end(); ei++)
1147 intervals[i+1]=std::make_pair(intervals[i].first+Distance((*ei).v[0]->P(),(*ei).v[1]->P()), &*ei);
1152 ScalarType edgeSum = intervals.back().first;
1153 for(i=0;i<sampleNum;++i)
1155 ScalarType val = edgeSum * RandomDouble01();
1158 typename std::vector<IntervalType>::iterator it = lower_bound(intervals.begin(),intervals.end(),std::make_pair(val,(SimpleEdge*)(0)) );
1159 assert(it != intervals.end() && it != intervals.begin());
1160 assert( ( (*(it-1)).first < val ) && ((*(it)).first >= val) );
1161 SimpleEdge * ep=(*it).second;
1162 ps.AddFace( *(ep->f), ep->EdgeBarycentricToFaceBarycentric(RandomDouble01()) );
1172 static void Montecarlo(MeshType & m, VertexSampler &ps,
int sampleNum)
1174 typedef std::pair<ScalarType, FacePointer> IntervalType;
1175 std::vector< IntervalType > intervals (m.fn+1);
1178 intervals[i]=std::make_pair(0,FacePointer(0));
1180 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1183 intervals[i+1]=std::make_pair(intervals[i].first+0.5*DoubleArea(*fi), &*fi);
1186 ScalarType meshArea = intervals.back().first;
1187 for(i=0;i<sampleNum;++i)
1189 ScalarType val = meshArea * RandomDouble01();
1192 typename std::vector<IntervalType>::iterator it = lower_bound(intervals.begin(),intervals.end(),std::make_pair(val,FacePointer(0)) );
1193 assert(it != intervals.end());
1194 assert(it != intervals.begin());
1195 assert( (*(it-1)).first <val );
1196 assert( (*(it)).first >= val);
1197 ps.AddFace( *(*it).second, RandomBarycentric() );
1201 static ScalarType WeightedArea(FaceType &f, PerVertexFloatAttribute &wH)
1203 ScalarType averageQ = ( wH[f.V(0)] + wH[f.V(1)] + wH[f.V(2)] )/3.0;
1204 return averageQ*averageQ*DoubleArea(f)/2.0;
1217 tri::RequirePerVertexQuality(m);
1218 tri::RequireCompactness(m);
1222 ScalarType weightedArea = 0;
1223 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1224 weightedArea += WeightedArea(*fi,rH);
1226 ScalarType samplePerAreaUnit = sampleNum/weightedArea;
1228 double floatSampleNum = 0.0;
1229 for(FaceIterator fi=m.face.begin(); fi != m.face.end(); fi++)
1232 floatSampleNum += WeightedArea(*fi,rH) * samplePerAreaUnit;
1233 int faceSampleNum = (int) floatSampleNum;
1236 for(
int i=0; i < faceSampleNum; i++)
1237 ps.AddFace(*fi,RandomBarycentric());
1239 floatSampleNum -= (double) faceSampleNum;
1247 static int SingleFaceSubdivision(
int sampleNum,
const CoordType & v0,
const CoordType & v1,
const CoordType & v2, VertexSampler &ps, FacePointer fp,
bool randSample)
1253 CoordType SamplePoint;
1256 CoordType rb=RandomBarycentric();
1257 SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
1259 else SamplePoint=((v0+v1+v2)*(1.0f/3.0f));
1261 ps.AddFace(*fp,SamplePoint);
1265 int s0 = sampleNum /2;
1266 int s1 = sampleNum-s0;
1270 ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
1271 ScalarType w1 = 1.0-w0;
1273 ScalarType maxd01 = SquaredDistance(v0,v1);
1274 ScalarType maxd12 = SquaredDistance(v1,v2);
1275 ScalarType maxd20 = SquaredDistance(v2,v0);
1278 if(maxd01 > maxd20) res = 0;
1281 if(maxd12 > maxd20) res = 1;
1284 int faceSampleNum=0;
1289 case 0 : pp = v0*w0 + v1*w1;
1290 faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
1291 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1293 case 1 : pp = v1*w0 + v2*w1;
1294 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1295 faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
1297 case 2 : pp = v0*w0 + v2*w1;
1298 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1299 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1302 return faceSampleNum;
1307 static void FaceSubdivision(MeshType & m, VertexSampler &ps,
int sampleNum,
bool randSample)
1310 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1311 ScalarType samplePerAreaUnit = sampleNum/area;
1312 std::vector<FacePointer> faceVec;
1313 FillAndShuffleFacePointerVector(m,faceVec);
1315 double floatSampleNum = 0.0;
1318 typename std::vector<FacePointer>::iterator fi;
1319 for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
1321 const CoordType b0(1.0, 0.0, 0.0);
1322 const CoordType b1(0.0, 1.0, 0.0);
1323 const CoordType b2(0.0, 0.0, 1.0);
1325 floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
1326 faceSampleNum = (int) floatSampleNum;
1328 faceSampleNum = SingleFaceSubdivision(faceSampleNum,b0,b1,b2,ps,*fi,randSample);
1329 floatSampleNum -= (double) faceSampleNum;
1336 static int SingleFaceSubdivisionOld(
int sampleNum,
const CoordType & v0,
const CoordType & v1,
const CoordType & v2, VertexSampler &ps, FacePointer fp,
bool randSample)
1342 CoordType SamplePoint;
1345 CoordType rb=RandomBarycentric();
1346 SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
1348 else SamplePoint=((v0+v1+v2)*(1.0f/3.0f));
1350 CoordType SampleBary;
1351 InterpolationParameters(*fp,SamplePoint,SampleBary);
1352 ps.AddFace(*fp,SampleBary);
1356 int s0 = sampleNum /2;
1357 int s1 = sampleNum-s0;
1361 ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
1362 ScalarType w1 = 1.0-w0;
1364 ScalarType maxd01 = SquaredDistance(v0,v1);
1365 ScalarType maxd12 = SquaredDistance(v1,v2);
1366 ScalarType maxd20 = SquaredDistance(v2,v0);
1369 if(maxd01 > maxd20) res = 0;
1372 if(maxd12 > maxd20) res = 1;
1375 int faceSampleNum=0;
1380 case 0 : pp = v0*w0 + v1*w1;
1381 faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
1382 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1384 case 1 : pp = v1*w0 + v2*w1;
1385 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1386 faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
1388 case 2 : pp = v0*w0 + v2*w1;
1389 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1390 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1393 return faceSampleNum;
1401 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1402 ScalarType samplePerAreaUnit = sampleNum/area;
1403 std::vector<FacePointer> faceVec;
1404 FillAndShuffleFacePointerVector(m,faceVec);
1406 double floatSampleNum = 0.0;
1409 typename std::vector<FacePointer>::iterator fi;
1410 for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
1413 floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
1414 faceSampleNum = (int) floatSampleNum;
1416 faceSampleNum = SingleFaceSubdivision(faceSampleNum,(**fi).V(0)->cP(), (**fi).V(1)->cP(), (**fi).V(2)->cP(),ps,*fi,randSample);
1417 floatSampleNum -= (double) faceSampleNum;
1428 static int SingleFaceSimilar(FacePointer fp, VertexSampler &ps,
int n_samples_per_edge)
1432 float segmentNum=n_samples_per_edge -1 ;
1433 float segmentLen = 1.0/segmentNum;
1435 for(i=1; i < n_samples_per_edge-1; i++)
1436 for(j=1; j < n_samples_per_edge-1-i; j++)
1439 CoordType sampleBary(i*segmentLen,j*segmentLen, 1.0 - (i*segmentLen+j*segmentLen) ) ;
1441 ps.AddFace(*fp,sampleBary);
1445 static int SingleFaceSimilarDual(FacePointer fp, VertexSampler &ps,
int n_samples_per_edge,
bool randomFlag)
1449 float segmentNum=n_samples_per_edge -1 ;
1450 float segmentLen = 1.0/segmentNum;
1452 for(i=0; i < n_samples_per_edge-1; i++)
1453 for(j=0; j < n_samples_per_edge-1-i; j++)
1456 CoordType V0((i+0)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+0)*segmentLen) ) ;
1457 CoordType V1((i+1)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+1)*segmentLen+(j+0)*segmentLen) ) ;
1458 CoordType V2((i+0)*segmentLen,(j+1)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+1)*segmentLen) ) ;
1461 CoordType rb=RandomBarycentric();
1462 ps.AddFace(*fp, V0*rb[0]+V1*rb[1]+V2*rb[2]);
1463 }
else ps.AddFace(*fp,(V0+V1+V2)/3.0);
1465 if( j < n_samples_per_edge-i-2 )
1467 CoordType V3((i+1)*segmentLen,(j+1)*segmentLen, 1.0 - ((i+1)*segmentLen+(j+1)*segmentLen) ) ;
1470 CoordType rb=RandomBarycentric();
1471 ps.AddFace(*fp, V3*rb[0]+V1*rb[1]+V2*rb[2]);
1472 }
else ps.AddFace(*fp,(V3+V1+V2)/3.0);
1507 static void FaceSimilar(MeshType & m, VertexSampler &ps,
int sampleNum,
bool dualFlag,
bool randomFlag)
1509 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1510 ScalarType samplePerAreaUnit = sampleNum/area;
1513 int n_samples_per_edge;
1514 double n_samples_decimal = 0.0;
1517 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1520 n_samples_decimal += 0.5*DoubleArea(*fi) * samplePerAreaUnit;
1521 int n_samples = (int) n_samples_decimal;
1527 n_samples_per_edge = (int)((sqrt(1.0+8.0*(
double)n_samples) +5.0)/2.0);
1528 n_samples = SingleFaceSimilar(&*fi,ps, n_samples_per_edge);
1530 n_samples_per_edge = (int)(sqrt((
double)n_samples) +1.0);
1531 n_samples = SingleFaceSimilarDual(&*fi,ps, n_samples_per_edge,randomFlag);
1534 n_samples_decimal -= (double) n_samples;
1548 static void SingleFaceRaster(
typename MeshType::FaceType &f, VertexSampler &ps,
1549 const Point2<typename MeshType::ScalarType> & v0,
1550 const Point2<typename MeshType::ScalarType> & v1,
1551 const Point2<typename MeshType::ScalarType> & v2,
1552 bool correctSafePointsBaryCoords=
true)
1554 typedef typename MeshType::ScalarType S;
1562 bbox.min[0] = floor(bboxf.min[0]);
1563 bbox.min[1] = floor(bboxf.min[1]);
1564 bbox.max[0] = ceil(bboxf.max[0]);
1565 bbox.max[1] = ceil(bboxf.max[1]);
1568 Point2<S> d10 = v1 - v0;
1569 Point2<S> d21 = v2 - v1;
1570 Point2<S> d02 = v0 - v2;
1573 S b0 = (bbox.min[0]-v0[0])*d10[1] - (bbox.min[1]-v0[1])*d10[0];
1574 S b1 = (bbox.min[0]-v1[0])*d21[1] - (bbox.min[1]-v1[1])*d21[0];
1575 S b2 = (bbox.min[0]-v2[0])*d02[1] - (bbox.min[1]-v2[1])*d02[0];
1586 bool flipped = !(d02 * vcg::Point2<S>(-d10[1], d10[0]) >= 0);
1589 Segment2<S> borderEdges[3];
1591 unsigned char edgeMask = 0;
1594 borderEdges[0] = Segment2<S>(v0, v1);
1595 edgeLength[0] = borderEdges[0].Length();
1599 borderEdges[1] = Segment2<S>(v1, v2);
1600 edgeLength[1] = borderEdges[1].Length();
1604 borderEdges[2] = Segment2<S>(v2, v0);
1605 edgeLength[2] = borderEdges[2].Length();
1610 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];
1612 for(
int x=bbox.min[0]-1;x<=bbox.max[0]+1;++x)
1615 S n[3] = { b0-db0-dn0, b1-db1-dn1, b2-db2-dn2};
1616 for(
int y=bbox.min[1]-1;y<=bbox.max[1]+1;++y)
1618 if( ((n[0]>=0 && n[1]>=0 && n[2]>=0) || (n[0]<=0 && n[1]<=0 && n[2]<=0)) && (de != 0))
1620 typename MeshType::CoordType baryCoord;
1621 baryCoord[0] = double(-y*v1[0]+v2[0]*y+v1[1]*x-v2[0]*v1[1]+v1[0]*v2[1]-x*v2[1])/de;
1622 baryCoord[1] = -double( x*v0[1]-x*v2[1]-v0[0]*y+v0[0]*v2[1]-v2[0]*v0[1]+v2[0]*y)/de;
1623 baryCoord[2] = 1-baryCoord[0]-baryCoord[1];
1625 ps.AddTextureSample(f, baryCoord, Point2i(x,y), 0);
1630 Point2<S> closePoint;
1635 for (
int i=0; i<3; ++i)
1637 if (edgeMask & (1 << i))
1641 if ( ((!flipped) && (n[i]<0)) ||
1642 ( flipped && (n[i]>0)) )
1644 dst = ((close = ClosestPoint(borderEdges[i], px)) - px).Norm();
1646 close.X() > px.X()-1 && close.X() < px.X()+1 &&
1647 close.Y() > px.Y()-1 && close.Y() < px.Y()+1)
1659 typename MeshType::CoordType baryCoord;
1660 if (correctSafePointsBaryCoords)
1663 baryCoord[closeEdge] = (closePoint - borderEdges[closeEdge].P1()).Norm()/edgeLength[closeEdge];
1664 baryCoord[(closeEdge+1)%3] = 1 - baryCoord[closeEdge];
1665 baryCoord[(closeEdge+2)%3] = 0;
1668 baryCoord[0] = double(-y*v1[0]+v2[0]*y+v1[1]*x-v2[0]*v1[1]+v1[0]*v2[1]-x*v2[1])/de;
1669 baryCoord[1] = -double( x*v0[1]-x*v2[1]-v0[0]*y+v0[0]*v2[1]-v2[0]*v0[1]+v2[0]*y)/de;
1670 baryCoord[2] = 1-baryCoord[0]-baryCoord[1];
1672 ps.AddTextureSample(f, baryCoord, Point2i(x,y), minDst);
1687 static bool checkPoissonDisk(SampleSHT & sht,
const Point3<ScalarType> & p, ScalarType radius)
1690 std::vector<VertexType*> closests;
1691 typedef EmptyTMark<MeshType> MarkerVert;
1692 static MarkerVert mv;
1694 Box3f bb(p-Point3f(radius,radius,radius),p+Point3f(radius,radius,radius));
1695 GridGetInBox(sht, mv, bb, closests);
1697 ScalarType r2 = radius*radius;
1698 for(
int i=0; i<closests.size(); ++i)
1699 if(SquaredDistance(p,closests[i]->cP()) < r2)
1709 adaptiveRadiusFlag =
false;
1710 bestSampleChoiceFlag =
true;
1711 bestSamplePoolSize = 10;
1714 invertQuality =
false;
1717 geodesicDistanceFlag =
false;
1730 int montecarloSampleNum;
1733 bool geodesicDistanceFlag;
1734 bool bestSampleChoiceFlag;
1735 int bestSamplePoolSize;
1736 bool adaptiveRadiusFlag;
1737 float radiusVariance;
1741 MeshType *preGenMesh;
1752 static VertexPointer getSampleFromCell(
Point3i &cell, MontecarloSHT & samplepool)
1754 MontecarloSHTIterator cellBegin, cellEnd;
1755 samplepool.Grid(cell, cellBegin, cellEnd);
1762 static VertexPointer getBestPrecomputedMontecarloSample(
Point3i &cell, MontecarloSHT & samplepool, ScalarType diskRadius,
const PoissonDiskParam &pp)
1764 MontecarloSHTIterator cellBegin,cellEnd;
1765 samplepool.Grid(cell, cellBegin, cellEnd);
1766 VertexPointer bestSample=0;
1767 int minRemoveCnt = std::numeric_limits<int>::max();
1768 std::vector<typename MontecarloSHT::HashIterator> inSphVec;
1770 for(MontecarloSHTIterator ci=cellBegin; ci!=cellEnd && i<pp.bestSamplePoolSize; ++ci,i++)
1772 VertexPointer sp = *ci;
1773 if(pp.adaptiveRadiusFlag) diskRadius = sp->Q();
1774 int curRemoveCnt = samplepool.CountInSphere(sp->cP(),diskRadius,inSphVec);
1775 if(curRemoveCnt < minRemoveCnt)
1778 minRemoveCnt = curRemoveCnt;
1788 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
1793 meshArea = (origMesh.bbox.DimX()*origMesh.bbox.DimY() +
1794 origMesh.bbox.DimX()*origMesh.bbox.DimZ() +
1795 origMesh.bbox.DimY()*origMesh.bbox.DimZ());
1797 ScalarType diskRadius = sqrt(meshArea / (0.7 * M_PI * sampleNum));
1801 static int ComputePoissonSampleNum(MeshType &origMesh, ScalarType diskRadius)
1803 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
1804 int sampleNum = meshArea / (diskRadius*diskRadius *M_PI *0.7) ;
1815 static void InitRadiusHandleFromQuality(MeshType &sampleMesh, PerVertexFloatAttribute &rH, ScalarType diskRadius, ScalarType radiusVariance,
bool invert)
1817 std::pair<float,float> minmax = tri::Stat<MeshType>::ComputePerVertexQualityMinMax( sampleMesh);
1818 float minRad = diskRadius ;
1819 float maxRad = diskRadius * radiusVariance;
1820 float deltaQ = minmax.second-minmax.first;
1821 float deltaRad = maxRad-minRad;
1822 for (VertexIterator vi = sampleMesh.vert.begin(); vi != sampleMesh.vert.end(); vi++)
1824 rH[*vi] = minRad + deltaRad*((invert ? minmax.second - (*vi).Q() : (*vi).Q() - minmax.first )/deltaQ);
1833 static void InitSpatialHashTable(MeshType &montecarloMesh, MontecarloSHT &montecarloSHT, ScalarType diskRadius,
1834 struct PoissonDiskParam pp=PoissonDiskParam())
1836 ScalarType cellsize = 2.0f* diskRadius / sqrt(3.0);
1837 float occupancyRatio=0;
1841 BoxType bb=montecarloMesh.bbox;
1842 assert(!bb.IsNull());
1843 bb.Offset(cellsize);
1845 int sizeX = std::max(1,
int(bb.DimX() / cellsize));
1846 int sizeY = std::max(1,
int(bb.DimY() / cellsize));
1847 int sizeZ = std::max(1,
int(bb.DimZ() / cellsize));
1848 Point3i gridsize(sizeX, sizeY, sizeZ);
1850 montecarloSHT.InitEmpty(bb, gridsize);
1852 for (VertexIterator vi = montecarloMesh.vert.begin(); vi != montecarloMesh.vert.end(); vi++)
1855 montecarloSHT.Add(&(*vi));
1858 montecarloSHT.UpdateAllocatedCells();
1859 pp.pds.gridSize = gridsize;
1860 pp.pds.gridCellNum = (int)montecarloSHT.AllocatedCells.size();
1862 occupancyRatio = float(montecarloMesh.vn) / float(montecarloSHT.AllocatedCells.size());
1865 while( occupancyRatio> 100);
1868 static void PoissonDiskPruningByNumber(VertexSampler &ps, MeshType &m,
1869 size_t sampleNum, ScalarType &diskRadius,
1870 PoissonDiskParam &pp,
1871 float tolerance=0.04,
1875 size_t sampleNumMin = int(
float(sampleNum)*(1.0f-tolerance));
1876 size_t sampleNumMax = int(
float(sampleNum)*(1.0f+tolerance));
1877 float RangeMinRad = m.bbox.Diag()/50.0;
1878 float RangeMaxRad = m.bbox.Diag()/50.0;
1879 size_t RangeMinRadNum;
1880 size_t RangeMaxRadNum;
1887 RangeMinRadNum = pp.pds.sampleNum;
1889 }
while(RangeMinRadNum < sampleNum);
1895 RangeMaxRadNum = pp.pds.sampleNum;
1897 }
while(RangeMaxRadNum > sampleNum);
1900 float curRadius=RangeMaxRad;
1902 while(iterCnt<maxIter &&
1903 (pp.pds.sampleNum < sampleNumMin || pp.pds.sampleNum > sampleNumMax) )
1907 curRadius=(RangeMaxRad+RangeMinRad)/2.0f;
1910 if(pp.pds.sampleNum > sampleNum){
1911 RangeMinRad = curRadius;
1912 RangeMinRadNum = pp.pds.sampleNum;
1914 if(pp.pds.sampleNum < sampleNum){
1915 RangeMaxRad = curRadius;
1916 RangeMaxRadNum = pp.pds.sampleNum;
1919 diskRadius = curRadius;
1935 tri::RequireCompactness(montecarloMesh);
1936 if(pp.randomSeed) SamplingRandomGenerator().initialize(pp.randomSeed);
1937 if(pp.adaptiveRadiusFlag)
1938 tri::RequirePerVertexQuality(montecarloMesh);
1941 MontecarloSHT montecarloSHT;
1942 InitSpatialHashTable(montecarloMesh,montecarloSHT,diskRadius,pp);
1946 PerVertexFloatAttribute rH =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (montecarloMesh,
"radius");
1947 if(pp.adaptiveRadiusFlag)
1955 std::shuffle(montecarloSHT.AllocatedCells.begin(),montecarloSHT.AllocatedCells.end(), g);
1957 pp.pds.montecarloSampleNum = montecarloMesh.vn;
1958 pp.pds.sampleNum =0;
1963 if(pp.preGenMesh==0)
1965 typename MeshType::template PerVertexAttributeHandle<bool> fixed;
1967 for(VertexIterator vi=montecarloMesh.vert.begin();vi!=montecarloMesh.vert.end();++vi)
1971 removedCnt += montecarloSHT.RemoveInSphere(vi->cP(),diskRadius);
1976 for(VertexIterator vi =pp.preGenMesh->vert.begin(); vi!=pp.preGenMesh->vert.end();++vi)
1980 removedCnt += montecarloSHT.RemoveInSphere(vi->cP(),diskRadius);
1983 montecarloSHT.UpdateAllocatedCells();
1985 vertex::ApproximateGeodesicDistanceFunctor<VertexType> GDF;
1986 while(!montecarloSHT.AllocatedCells.empty())
1989 for (
size_t i = 0; i < montecarloSHT.AllocatedCells.size(); i++)
1991 if( montecarloSHT.EmptyCell(montecarloSHT.AllocatedCells[i]) )
continue;
1992 ScalarType currentRadius =diskRadius;
1994 if(pp.bestSampleChoiceFlag)
1995 sp = getBestPrecomputedMontecarloSample(montecarloSHT.AllocatedCells[i], montecarloSHT, diskRadius, pp);
1997 sp = getSampleFromCell(montecarloSHT.AllocatedCells[i], montecarloSHT);
1999 if(pp.adaptiveRadiusFlag)
2000 currentRadius = rH[sp];
2004 if(pp.geodesicDistanceFlag) removedCnt += montecarloSHT.RemoveInSphereNormal(sp->cP(),sp->cN(),GDF,currentRadius);
2005 else removedCnt += montecarloSHT.RemoveInSphere(sp->cP(),currentRadius);
2007 montecarloSHT.UpdateAllocatedCells();
2010 pp.pds.gridTime = t1-t0;
2011 pp.pds.pruneTime = t2-t1;
2028 MontecarloSHT montecarloSHTVec[5];
2035 ScalarType cellsize = 2.0f* diskRadius / sqrt(3.0);
2038 BoxType bb=origMesh.bbox;
2039 bb.Offset(cellsize);
2041 int sizeX = std::max(1.0f,bb.DimX() / cellsize);
2042 int sizeY = std::max(1.0f,bb.DimY() / cellsize);
2043 int sizeZ = std::max(1.0f,bb.DimZ() / cellsize);
2044 Point3i gridsize(sizeX, sizeY, sizeZ);
2048 checkSHT.InitEmpty(bb, gridsize);
2064 montecarloSHTVec[0].InitEmpty(bb, gridsize);
2066 for (VertexIterator vi = montecarloMesh.vert.begin(); vi != montecarloMesh.vert.end(); vi++)
2067 montecarloSHTVec[0].Add(&(*vi));
2068 montecarloSHTVec[0].UpdateAllocatedCells();
2071 PerVertexFloatAttribute rH =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (montecarloMesh,
"radius");
2072 if(pp.adaptiveRadiusFlag)
2077 MontecarloSHT &montecarloSHT = montecarloSHTVec[level];
2081 montecarloSHT.InitEmpty(bb, gridsize);
2083 for (
typename MontecarloSHT::HashIterator hi = montecarloSHTVec[level-1].hash_table.begin(); hi != montecarloSHTVec[level-1].hash_table.end(); hi++)
2084 montecarloSHT.Add((*hi).second);
2085 montecarloSHT.UpdateAllocatedCells();
2089 std::random_device rd;
2093 std::shuffle(montecarloSHT.AllocatedCells.begin(),montecarloSHT.AllocatedCells.end(), g);
2097 int removedCnt=montecarloSHT.hash_table.size();
2098 int addedCnt=checkSHT.hash_table.size();
2099 for (
int i = 0; i < montecarloSHT.AllocatedCells.size(); i++)
2101 for(
int j=0;j<4;j++)
2103 if( montecarloSHT.EmptyCell(montecarloSHT.AllocatedCells[i]) )
continue;
2106 typename MontecarloSHT::HashIterator hi = montecarloSHT.hash_table.find(montecarloSHT.AllocatedCells[i]);
2108 if(hi==montecarloSHT.hash_table.end()) {
break;}
2109 VertexPointer sp = (*hi).second;
2111 ScalarType sampleRadius = diskRadius;
2112 if(pp.adaptiveRadiusFlag) sampleRadius = rH[sp];
2113 if (checkPoissonDisk(checkSHT, sp->cP(), sampleRadius))
2116 montecarloSHT.RemoveCell(sp);
2121 montecarloSHT.RemovePunctual(sp);
2124 addedCnt = checkSHT.hash_table.size()-addedCnt;
2125 removedCnt = removedCnt-montecarloSHT.hash_table.size();
2149 static void Texture(MeshType & m, VertexSampler &ps,
int textureWidth,
int textureHeight,
bool correctSafePointsBaryCoords=
true)
2151 typedef Point2<ScalarType> Point2x;
2152 printf(
"Similar Triangles face sampling\n");
2153 for(FaceIterator fi=m.face.begin(); fi != m.face.end(); fi++)
2157 for(
int i=0;i<3;++i)
2158 ti[i]=Point2x((*fi).WT(i).U() * textureWidth - 0.5, (*fi).WT(i).V() * textureHeight - 0.5);
2161 SingleFaceRaster(*fi, ps, ti[0],ti[1],ti[2], correctSafePointsBaryCoords);
2165 typedef GridStaticPtr<FaceType, ScalarType > TriMeshGrid;
2172 tri::FaceTmark<MeshType> markerFunctor;
2176 static void RegularRecursiveOffset(MeshType & m, std::vector<CoordType> &pvec, ScalarType offset,
float minDiag)
2183 rrp.markerFunctor.SetMesh(&m);
2185 rrp.gM.Set(m.face.begin(),m.face.end(),bb);
2189 rrp.minDiag=minDiag;
2190 SubdivideAndSample(m, pvec, bb, rrp, bb.
Diag());
2193 static void SubdivideAndSample(MeshType & m, std::vector<CoordType> &pvec,
const Box3<ScalarType> bb, RRParam &rrp,
float curDiag)
2195 CoordType startPt = bb.
Center();
2199 FaceType *nearestF=0;
2200 ScalarType dist_upper_bound = curDiag+rrp.offset;
2201 CoordType closestPt;
2202 vcg::face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
2203 dist=dist_upper_bound;
2204 nearestF = rrp.gM.GetClosest(PDistFunct,rrp.markerFunctor,startPt,dist_upper_bound,dist,closestPt);
2206 if(dist < dist_upper_bound)
2208 if(curDiag/3 < rrp.minDiag)
2211 pvec.push_back(closestPt);
2216 CoordType delta = startPt-closestPt;
2217 pvec.push_back(closestPt+delta*(rrp.offset/dist));
2221 if(curDiag < rrp.minDiag)
return;
2222 CoordType hs = (bb.
max-bb.
min)/2;
2223 for(
int i=0;i<2;i++)
2224 for(
int j=0;j<2;j++)
2225 for(
int k=0;k<2;k++)
2226 SubdivideAndSample(m, pvec,
2227 BoxType(CoordType( bb.
min[0]+i*hs[0], bb.
min[1]+j*hs[1], bb.
min[2]+k*hs[2]),
2228 CoordType(startPt[0]+i*hs[0], startPt[1]+j*hs[1], startPt[2]+k*hs[2]) ),
2236 template <
class MeshType>
2237 typename MeshType::ScalarType ComputePoissonDiskRadius(MeshType &origMesh,
int sampleNum)
2239 typedef typename MeshType::ScalarType ScalarType;
2240 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
2245 meshArea = (origMesh.bbox.DimX()*origMesh.bbox.DimY() +
2246 origMesh.bbox.DimX()*origMesh.bbox.DimZ() +
2247 origMesh.bbox.DimY()*origMesh.bbox.DimZ());
2249 ScalarType diskRadius = sqrt(meshArea / (0.7 * M_PI * sampleNum));
2255 template <
class MeshType>
2256 void MontecarloSampling(MeshType &m,
2260 typedef tri::MeshSampler<MeshType> BaseSampler;
2261 MeshSampler<MeshType> mcSampler(&mm);
2266 template <
class MeshType>
2267 void MontecarloSampling(MeshType &m,
2268 std::vector<Point3f> &montercarloSamples,
2271 typedef tri::TrivialSampler<MeshType> BaseSampler;
2272 BaseSampler mcSampler(montercarloSamples);
2278 template <
class MeshType>
2279 void PoissonSampling(MeshType &m,
2280 std::vector<typename MeshType::CoordType> &poissonSamples,
2282 typename MeshType::ScalarType &radius,
2283 typename MeshType::ScalarType radiusVariance=1,
2284 typename MeshType::ScalarType PruningByNumberTolerance=0.04f,
2285 unsigned int randSeed=0)
2288 typedef tri::TrivialSampler<MeshType> BaseSampler;
2289 typedef tri::MeshSampler<MeshType> MontecarloSampler;
2291 typename tri::SurfaceSampling<MeshType, BaseSampler>::PoissonDiskParam pp;
2295 if(radius>0 && sampleNum==0) sampleNum = tri::SurfaceSampling<MeshType,BaseSampler>::ComputePoissonSampleNum(m,radius);
2297 pp.pds.sampleNum = sampleNum;
2298 pp.randomSeed = randSeed;
2299 poissonSamples.clear();
2301 MeshType MontecarloMesh;
2304 MontecarloSampler mcSampler(MontecarloMesh);
2305 BaseSampler pdSampler(poissonSamples);
2307 if(randSeed) tri::SurfaceSampling<MeshType,MontecarloSampler>::SamplingRandomGenerator().initialize(randSeed);
2312 pp.pds.montecarloTime = t1-t0;
2314 if(radiusVariance !=1)
2316 pp.adaptiveRadiusFlag=
true;
2317 pp.radiusVariance=radiusVariance;
2320 else tri::SurfaceSampling<MeshType,BaseSampler>::PoissonDiskPruningByNumber(pdSampler, MontecarloMesh, sampleNum, radius,pp,PruningByNumberTolerance);
2322 pp.pds.totalTime = t2-t0;
2329 template <
class MeshType>
2331 std::vector<typename MeshType::VertexPointer> &poissonSamples,
2332 float radius,
unsigned int randSeed=0)
2336 pp.randomSeed = randSeed;
2339 BaseSampler pdSampler;
2341 poissonSamples = pdSampler.sampleVec;
2350 template <
class MeshType>
2352 std::vector<typename MeshType::CoordType> &poissonSamples,
2353 float radius,
unsigned int randSeed=0)
2355 std::vector<typename MeshType::VertexPointer> poissonSamplesVP;
2357 poissonSamples.resize(poissonSamplesVP.size());
2358 for(
size_t i=0;i<poissonSamplesVP.size();++i)
2359 poissonSamples[i]=poissonSamplesVP[i]->P();
2369 template <
class MeshType>
2371 std::vector<typename MeshType::VertexPointer> &poissonSamples,
2372 typename MeshType::ScalarType & radius,
2374 float tolerance=0.04,
2376 unsigned int randSeed=0)
2378 size_t sampleNumMin = int(
float(sampleNum)*(1.0f-tolerance));
2379 size_t sampleNumMax = int(
float(sampleNum)*(1.0f+tolerance));
2380 float RangeMinRad = m.bbox.Diag()/10.0f;
2381 float RangeMaxRad = m.bbox.Diag()/10.0f;
2382 size_t RangeMinSampleNum;
2383 size_t RangeMaxSampleNum;
2384 std::vector<typename MeshType::VertexPointer> poissonSamplesTmp;
2390 RangeMinSampleNum = poissonSamplesTmp.size();
2391 }
while(RangeMinSampleNum < sampleNumMin);
2397 RangeMaxSampleNum = poissonSamplesTmp.size();
2398 }
while(RangeMaxSampleNum > sampleNumMax);
2402 while(iterCnt<maxIter &&
2403 (poissonSamplesTmp.size() < sampleNumMin || poissonSamplesTmp.size() > sampleNumMax) )
2405 curRadius=(RangeMaxRad+RangeMinRad)/2.0f;
2408 if(poissonSamplesTmp.size() >
size_t(sampleNum))
2409 RangeMinRad = curRadius;
2410 if(poissonSamplesTmp.size() <
size_t(sampleNum))
2411 RangeMaxRad = curRadius;
2414 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:221
double volume
from the wikipedia defintion RMS DIST is sqrt(Sum(distances^2)/n), here we store Sum(distances^2)
Definition: point_sampling.h:249
MeshType * closestPtMesh
the mesh containing the sample points
Definition: point_sampling.h:239
MeshType * samplePtMesh
the mesh for which we search the closest points.
Definition: point_sampling.h:238
MetroMeshVertexGrid unifGridVert
the mesh containing the corresponding closest points that have been found
Definition: point_sampling.h:241
Definition: point_sampling.h:177
Definition: point_sampling.h:354
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:367
Definition: point_sampling.h:506
Definition: point_sampling.h:2168
Main Class of the Sampling framework.
Definition: point_sampling.h:467
static void Montecarlo(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:1172
static void HierarchicalPoissonDisk(MeshType &origMesh, VertexSampler &ps, MeshType &montecarloMesh, ScalarType diskRadius, const struct PoissonDiskParam pp=PoissonDiskParam())
Definition: point_sampling.h:2024
static void VertexAreaUniform(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:701
static void VertexWeighted(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:663
static void VertexCrease(MeshType &m, VertexSampler &ps)
Definition: point_sampling.h:960
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:749
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:1307
static void PoissonDiskPruning(VertexSampler &ps, MeshType &montecarloMesh, ScalarType diskRadius, PoissonDiskParam &pp)
Definition: point_sampling.h:1932
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:1786
static void VertexBorder(MeshType &m, VertexSampler &ps)
Sample all the border vertices.
Definition: point_sampling.h:949
static void VertexBorderCorner(MeshType &m, VertexSampler &ps, ScalarType angleRad)
Sample all the border corner vertices.
Definition: point_sampling.h:935
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:1398
static int Poisson(double lambda)
Definition: point_sampling.h:623
static void MontecarloPoisson(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:1105
static void WeightedMontecarlo(MeshType &m, VertexSampler &ps, int sampleNum, float variance)
Definition: point_sampling.h:1215
static void InitRadiusHandleFromQuality(MeshType &sampleMesh, PerVertexFloatAttribute &rH, ScalarType diskRadius, ScalarType radiusVariance, bool invert)
Definition: point_sampling.h:1815
static void EdgeMeshUniform(MeshType &m, VertexSampler &ps, float radius, EdgeSamplingStrategy strategy=Floor)
Definition: point_sampling.h:797
static void EdgeMontecarlo(MeshType &m, VertexSampler &ps, int sampleNum, bool sampleAllEdges)
Definition: point_sampling.h:1131
EdgeSamplingStrategy
The EdgeSamplingStrategy enum determines the sampling strategy for edge meshes. Given a sampling radi...
Definition: point_sampling.h:784
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:641
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:2370
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:2330
Definition: namespaces.dox:6
Definition: point_sampling.h:1722
Definition: point_sampling.h:1706