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));
533 typedef unsigned int result_type;
536 static constexpr result_type min() {
return 0;}
537 static constexpr result_type max() {
return std::numeric_limits<result_type>::max();}
538 result_type operator()() {
return SamplingRandomGenerator().generate();}
542static double RandomDouble01()
544 return SamplingRandomGenerator().generate01();
548static double LnFac(
int n) {
553 C0 = 0.918938533204672722,
559 static double fac_table[FAK_LEN];
560 static bool initialized =
false;
565 if (n < 0) assert(0);
570 double sum = fac_table[0] = 0.;
571 for (
int i=1; i<FAK_LEN; i++) {
572 sum += log(
double(i));
582 return (n1 + 0.5)*log(n1) - n1 + C0 + r*(C1 + r*r*C3);
585static int PoissonRatioUniforms(
double L) {
607 const double SHAT1 = 2.943035529371538573;
608 const double SHAT2 = 0.8989161620588987408;
614 double pois_a = L + 0.5;
616 double pois_g = log(L);
617 double pois_f0 = mode * pois_g - LnFac(mode);
618 double pois_h = sqrt(SHAT1 * (L+0.5)) + SHAT2;
619 double pois_bound = (int)(pois_a + 6.0 * pois_h);
622 u = RandomDouble01();
623 if (u == 0)
continue;
624 x = pois_a + pois_h * (RandomDouble01() - 0.5) / u;
625 if (x < 0 || x >= pois_bound)
continue;
627 lf = k * pois_g - LnFac(k) - pois_f0;
628 if (lf >= u * (4.0 - u) - 3.0)
break;
629 if (u * (u - lf) > 1.0)
continue;
630 if (2.0 * log(u) <= lf)
break;
649 if(lambda>50)
return PoissonRatioUniforms(lambda);
650 double L = exp(-lambda);
656 p = p*RandomDouble01();
663static void AllVertex(MeshType & m, VertexSampler &ps)
665 AllVertex(m, ps,
false);
668static void AllVertex(MeshType & m, VertexSampler &ps,
bool onlySelected)
671 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
673 if ((!onlySelected) || ((*vi).IsS()))
691 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
695 ScalarType samplePerUnit = sampleNum/qSum;
696 ScalarType floatSampleNum =0;
697 std::vector<VertexPointer> vertVec;
698 FillAndShuffleVertexPointerVector(m,vertVec);
700 std::vector<bool> vertUsed(m.vn,
false);
703 while(cnt < sampleNum)
707 floatSampleNum += vertVec[i]->Q() * samplePerUnit;
708 int vertSampleNum = (int) floatSampleNum;
709 floatSampleNum -= (float) vertSampleNum;
712 if(vertSampleNum > 1)
714 ps.AddVert(*vertVec[i]);
728 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
733 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
736 ScalarType areaThird = DoubleArea(*fi)/6.0;
737 (*fi).V(0)->Q()+=areaThird;
738 (*fi).V(1)->Q()+=areaThird;
739 (*fi).V(2)->Q()+=areaThird;
745static void FillAndShuffleFacePointerVector(MeshType & m, std::vector<FacePointer> &faceVec)
747 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
748 if(!(*fi).IsD()) faceVec.push_back(&*fi);
750 assert((
int)faceVec.size()==m.fn);
755 MarsenneTwisterURBG g;
756 std::shuffle(faceVec.begin(),faceVec.end(), g);
758static void FillAndShuffleVertexPointerVector(MeshType & m, std::vector<VertexPointer> &vertVec)
760 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
761 if(!(*vi).IsD()) vertVec.push_back(&*vi);
763 assert((
int)vertVec.size()==m.vn);
768 MarsenneTwisterURBG g;
769 std::shuffle(vertVec.begin(),vertVec.end(), g);
773static void VertexUniform(MeshType & m, VertexSampler &ps,
int sampleNum,
bool onlySelected)
775 if (sampleNum >= m.vn) {
776 AllVertex(m, ps, onlySelected);
780 std::vector<VertexPointer> vertVec;
781 FillAndShuffleVertexPointerVector(m, vertVec);
784 for (
int i = 0; ((i < m.vn) && (added < sampleNum)); ++i)
785 if (!(*vertVec[i]).IsD())
786 if ((!onlySelected) || (*vertVec[i]).IsS())
788 ps.AddVert(*vertVec[i]);
795static void VertexUniform(MeshType & m, VertexSampler &ps,
int sampleNum)
832 tri::RequireEEAdjacency(m);
833 tri::RequireCompactness(m);
834 tri::RequirePerEdgeFlags(m);
835 tri::RequirePerVertexFlags(m);
838 tri::MeshAssert<MeshType>::EEOneManifold(m);
840 for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
844 edge::Pos<EdgeType> ep(&*ei,0);
845 edge::Pos<EdgeType> startep = ep;
851 }
while (startep != ep);
855 assert(ep == startep);
859 edge::Pos<EdgeType> altEp = ep;
861 while (altEp != startep) {
862 if (altEp.V()->cP() < ep.V()->cP())
870 const auto dir0 = ep.VFlip()->cP() - ep.V()->cP();
872 const auto dir1 = ep.VFlip()->cP() - ep.V()->cP();
880 edge::Pos<EdgeType> altEp = ep;
883 }
while (!altEp.IsBorder());
885 if (altEp.V()->cP() < ep.V()->cP())
891 ScalarType totalLen = 0;
897 totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
899 }
while (!ep.E()->IsV() && !ep.IsBorder());
900 if (ep.IsBorder() && !ep.E()->IsV())
903 totalLen += Distance(ep.V()->cP(), ep.VFlip()->cP());
906 VertexPointer startVertex = ep.V();
911 double div = double(totalLen) / radius;
913 case Round: sampleNum = int(round(div));
break;
914 case Ceil: sampleNum = int( ceil(div));
break;
915 default: sampleNum = int(floor(div));
break;
918 assert(sampleNum >= 0);
920 ScalarType sampleDist = totalLen / sampleNum;
924 ScalarType curLen = 0;
926 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
930 assert(ep.E()->IsV());
931 ScalarType edgeLen = Distance(ep.VFlip()->cP(), ep.V()->cP());
932 ScalarType d0 = curLen;
933 ScalarType d1 = d0 + edgeLen;
935 while (d1 > sampleCnt * sampleDist && sampleCnt < sampleNum)
937 ScalarType off = (sampleCnt * sampleDist - d0) / edgeLen;
939 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 1.0 - off : off);
943 }
while(!ep.IsBorder() && ep.V() != startVertex);
945 if(ep.V() != startVertex)
947 ps.AddEdge(*(ep.E()), ep.VInd() == 0 ? 0.0 : 1.0);
962 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
964 if(vi->IsS()) ps.AddVert(*vi);
987 std::vector< SimpleEdge > Edges;
988 typename std::vector< SimpleEdge >::iterator ei;
991 typename MeshType::template PerVertexAttributeHandle <int> hv =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<int> (m);
993 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
999 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
1012static inline CoordType CentroidBarycentricCoord()
1014 return CoordType(ScalarType(1.0/3.0), ScalarType(1.0/3.0), ScalarType(1.0/3.0));
1017static void FaceUniform(MeshType & m, VertexSampler &ps,
int sampleNum)
1019 if(sampleNum>=m.fn) {
1024 std::vector<FacePointer> faceVec;
1025 FillAndShuffleFacePointerVector(m,faceVec);
1027 for(
int i =0; i< sampleNum; ++i)
1028 ps.AddFace(*faceVec[i],CentroidBarycentricCoord());
1031static void AllFace(MeshType & m, VertexSampler &ps)
1034 for(fi=m.face.begin();fi!=m.face.end();++fi)
1037 ps.AddFace(*fi,CentroidBarycentricCoord());
1042static void AllEdge(MeshType & m, VertexSampler &ps)
1045 typedef typename UpdateTopology<MeshType>::PEdge SimpleEdge;
1046 std::vector< SimpleEdge > Edges;
1047 typename std::vector< SimpleEdge >::iterator ei;
1048 UpdateTopology<MeshType>::FillUniqueEdgeVector(m,Edges);
1050 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1051 ps.AddFace(*(*ei).f,ei->EdgeBarycentricToFaceBarycentric(0.5));
1058static void EdgeUniform(MeshType & m, VertexSampler &ps,
int sampleNum,
bool sampleFauxEdge=
true)
1060 typedef typename UpdateTopology<MeshType>::PEdge SimpleEdge;
1062 std::vector< SimpleEdge > Edges;
1063 UpdateTopology<MeshType>::FillUniqueEdgeVector(m,Edges,sampleFauxEdge);
1066 typename std::vector< SimpleEdge >::iterator ei;
1067 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1068 edgeSum+=Distance((*ei).v[0]->P(),(*ei).v[1]->P());
1070 float sampleLen = edgeSum/sampleNum;
1072 for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
1074 float len = Distance((*ei).v[0]->P(),(*ei).v[1]->P());
1075 float samplePerEdge = floor((len+rest)/sampleLen);
1076 rest = (len+rest) - samplePerEdge * sampleLen;
1077 float step = 1.0/(samplePerEdge+1);
1078 for(
int i=0;i<samplePerEdge;++i)
1080 CoordType interp(0,0,0);
1081 interp[ (*ei).z ]=step*(i+1);
1082 interp[((*ei).z+1)%3]=1.0-step*(i+1);
1083 ps.AddFace(*(*ei).f,interp);
1091static CoordType RandomBarycentric()
1093 return math::GenerateBarycentricUniform<ScalarType>(SamplingRandomGenerator());
1097static CoordType RandomPointInTriangle(
const FaceType &f)
1099 CoordType u = RandomBarycentric();
1100 return f.cP(0)*u[0] + f.cP(1)*u[1] + f.cP(2)*u[2];
1103static void StratifiedMontecarlo(MeshType & m, VertexSampler &ps,
int sampleNum)
1105 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1106 ScalarType samplePerAreaUnit = sampleNum/area;
1108 double floatSampleNum = 0.0;
1111 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1115 floatSampleNum += 0.5*DoubleArea(*fi) * samplePerAreaUnit;
1116 int faceSampleNum = (int) floatSampleNum;
1119 for(
int i=0; i < faceSampleNum; i++)
1120 ps.AddFace(*fi,RandomBarycentric());
1121 floatSampleNum -= (double) faceSampleNum;
1141 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1142 ScalarType samplePerAreaUnit = sampleNum/area;
1145 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1148 float areaT=DoubleArea(*fi) * 0.5f;
1149 int faceSampleNum =
Poisson(areaT*samplePerAreaUnit);
1152 for(
int i=0; i < faceSampleNum; i++)
1153 ps.AddFace(*fi,RandomBarycentric());
1165static void EdgeMontecarlo(MeshType & m, VertexSampler &ps,
int sampleNum,
bool sampleAllEdges)
1168 std::vector< SimpleEdge > Edges;
1171 assert(!Edges.empty());
1173 typedef std::pair<ScalarType, SimpleEdge*> IntervalType;
1174 std::vector< IntervalType > intervals (Edges.size()+1);
1176 intervals[i]=std::make_pair(0,(SimpleEdge*)(0));
1178 typename std::vector< SimpleEdge >::iterator ei;
1179 for(ei=Edges.begin(); ei != Edges.end(); ei++)
1181 intervals[i+1]=std::make_pair(intervals[i].first+Distance((*ei).v[0]->P(),(*ei).v[1]->P()), &*ei);
1186 ScalarType edgeSum = intervals.back().first;
1187 for(i=0;i<sampleNum;++i)
1189 ScalarType val = edgeSum * RandomDouble01();
1192 typename std::vector<IntervalType>::iterator it = lower_bound(intervals.begin(),intervals.end(),std::make_pair(val,(SimpleEdge*)(0)) );
1193 assert(it != intervals.end() && it != intervals.begin());
1194 assert( ( (*(it-1)).first < val ) && ((*(it)).first >= val) );
1195 SimpleEdge * ep=(*it).second;
1196 ps.AddFace( *(ep->f), ep->EdgeBarycentricToFaceBarycentric(RandomDouble01()) );
1206static void Montecarlo(MeshType & m, VertexSampler &ps,
int sampleNum)
1208 typedef std::pair<ScalarType, FacePointer> IntervalType;
1209 std::vector< IntervalType > intervals (m.fn+1);
1212 intervals[i]=std::make_pair(0,FacePointer(0));
1214 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1217 intervals[i+1]=std::make_pair(intervals[i].first+0.5*DoubleArea(*fi), &*fi);
1220 ScalarType meshArea = intervals.back().first;
1221 for(i=0;i<sampleNum;++i)
1223 ScalarType val = meshArea * RandomDouble01();
1226 typename std::vector<IntervalType>::iterator it = lower_bound(intervals.begin(),intervals.end(),std::make_pair(val,FacePointer(0)) );
1227 assert(it != intervals.end());
1228 assert(it != intervals.begin());
1229 assert( (*(it-1)).first <val );
1230 assert( (*(it)).first >= val);
1231 ps.AddFace( *(*it).second, RandomBarycentric() );
1235static ScalarType WeightedArea(FaceType &f, PerVertexFloatAttribute &wH)
1237 ScalarType averageQ = ( wH[f.V(0)] + wH[f.V(1)] + wH[f.V(2)] )/3.0;
1238 return averageQ*averageQ*DoubleArea(f)/2.0;
1251 tri::RequirePerVertexQuality(m);
1252 tri::RequireCompactness(m);
1256 ScalarType weightedArea = 0;
1257 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1258 weightedArea += WeightedArea(*fi,rH);
1260 ScalarType samplePerAreaUnit = sampleNum/weightedArea;
1262 double floatSampleNum = 0.0;
1263 for(FaceIterator fi=m.face.begin(); fi != m.face.end(); fi++)
1266 floatSampleNum += WeightedArea(*fi,rH) * samplePerAreaUnit;
1267 int faceSampleNum = (int) floatSampleNum;
1270 for(
int i=0; i < faceSampleNum; i++)
1271 ps.AddFace(*fi,RandomBarycentric());
1273 floatSampleNum -= (double) faceSampleNum;
1281static int SingleFaceSubdivision(
int sampleNum,
const CoordType & v0,
const CoordType & v1,
const CoordType & v2, VertexSampler &ps, FacePointer fp,
bool randSample)
1287 CoordType SamplePoint;
1290 CoordType rb=RandomBarycentric();
1291 SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
1293 else SamplePoint=((v0+v1+v2)*(1.0f/3.0f));
1295 ps.AddFace(*fp,SamplePoint);
1299 int s0 = sampleNum /2;
1300 int s1 = sampleNum-s0;
1304 ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
1305 ScalarType w1 = 1.0-w0;
1307 ScalarType maxd01 = SquaredDistance(v0,v1);
1308 ScalarType maxd12 = SquaredDistance(v1,v2);
1309 ScalarType maxd20 = SquaredDistance(v2,v0);
1312 if(maxd01 > maxd20) res = 0;
1315 if(maxd12 > maxd20) res = 1;
1318 int faceSampleNum=0;
1323 case 0 : pp = v0*w0 + v1*w1;
1324 faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
1325 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1327 case 1 : pp = v1*w0 + v2*w1;
1328 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1329 faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
1331 case 2 : pp = v0*w0 + v2*w1;
1332 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1333 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1336 return faceSampleNum;
1341static void FaceSubdivision(MeshType & m, VertexSampler &ps,
int sampleNum,
bool randSample)
1344 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1345 ScalarType samplePerAreaUnit = sampleNum/area;
1346 std::vector<FacePointer> faceVec;
1347 FillAndShuffleFacePointerVector(m,faceVec);
1349 double floatSampleNum = 0.0;
1352 typename std::vector<FacePointer>::iterator fi;
1353 for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
1355 const CoordType b0(1.0, 0.0, 0.0);
1356 const CoordType b1(0.0, 1.0, 0.0);
1357 const CoordType b2(0.0, 0.0, 1.0);
1359 floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
1360 faceSampleNum = (int) floatSampleNum;
1362 faceSampleNum = SingleFaceSubdivision(faceSampleNum,b0,b1,b2,ps,*fi,randSample);
1363 floatSampleNum -= (double) faceSampleNum;
1370static int SingleFaceSubdivisionOld(
int sampleNum,
const CoordType & v0,
const CoordType & v1,
const CoordType & v2, VertexSampler &ps, FacePointer fp,
bool randSample)
1376 CoordType SamplePoint;
1379 CoordType rb=RandomBarycentric();
1380 SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
1382 else SamplePoint=((v0+v1+v2)*(1.0f/3.0f));
1384 CoordType SampleBary;
1385 InterpolationParameters(*fp,SamplePoint,SampleBary);
1386 ps.AddFace(*fp,SampleBary);
1390 int s0 = sampleNum /2;
1391 int s1 = sampleNum-s0;
1395 ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
1396 ScalarType w1 = 1.0-w0;
1398 ScalarType maxd01 = SquaredDistance(v0,v1);
1399 ScalarType maxd12 = SquaredDistance(v1,v2);
1400 ScalarType maxd20 = SquaredDistance(v2,v0);
1403 if(maxd01 > maxd20) res = 0;
1406 if(maxd12 > maxd20) res = 1;
1409 int faceSampleNum=0;
1414 case 0 : pp = v0*w0 + v1*w1;
1415 faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
1416 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1418 case 1 : pp = v1*w0 + v2*w1;
1419 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1420 faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
1422 case 2 : pp = v0*w0 + v2*w1;
1423 faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
1424 faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
1427 return faceSampleNum;
1435 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1436 ScalarType samplePerAreaUnit = sampleNum/area;
1437 std::vector<FacePointer> faceVec;
1438 FillAndShuffleFacePointerVector(m,faceVec);
1440 double floatSampleNum = 0.0;
1443 typename std::vector<FacePointer>::iterator fi;
1444 for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
1447 floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
1448 faceSampleNum = (int) floatSampleNum;
1450 faceSampleNum = SingleFaceSubdivision(faceSampleNum,(**fi).V(0)->cP(), (**fi).V(1)->cP(), (**fi).V(2)->cP(),ps,*fi,randSample);
1451 floatSampleNum -= (double) faceSampleNum;
1462static int SingleFaceSimilar(FacePointer fp, VertexSampler &ps,
int n_samples_per_edge)
1466 float segmentNum=n_samples_per_edge -1 ;
1467 float segmentLen = 1.0/segmentNum;
1469 for(i=1; i < n_samples_per_edge-1; i++)
1470 for(j=1; j < n_samples_per_edge-1-i; j++)
1473 CoordType sampleBary(i*segmentLen,j*segmentLen, 1.0 - (i*segmentLen+j*segmentLen) ) ;
1475 ps.AddFace(*fp,sampleBary);
1479static int SingleFaceSimilarDual(FacePointer fp, VertexSampler &ps,
int n_samples_per_edge,
bool randomFlag)
1483 float segmentNum=n_samples_per_edge -1 ;
1484 float segmentLen = 1.0/segmentNum;
1486 for(i=0; i < n_samples_per_edge-1; i++)
1487 for(j=0; j < n_samples_per_edge-1-i; j++)
1490 CoordType V0((i+0)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+0)*segmentLen) ) ;
1491 CoordType V1((i+1)*segmentLen,(j+0)*segmentLen, 1.0 - ((i+1)*segmentLen+(j+0)*segmentLen) ) ;
1492 CoordType V2((i+0)*segmentLen,(j+1)*segmentLen, 1.0 - ((i+0)*segmentLen+(j+1)*segmentLen) ) ;
1495 CoordType rb=RandomBarycentric();
1496 ps.AddFace(*fp, V0*rb[0]+V1*rb[1]+V2*rb[2]);
1497 }
else ps.AddFace(*fp,(V0+V1+V2)/3.0);
1499 if( j < n_samples_per_edge-i-2 )
1501 CoordType V3((i+1)*segmentLen,(j+1)*segmentLen, 1.0 - ((i+1)*segmentLen+(j+1)*segmentLen) ) ;
1504 CoordType rb=RandomBarycentric();
1505 ps.AddFace(*fp, V3*rb[0]+V1*rb[1]+V2*rb[2]);
1506 }
else ps.AddFace(*fp,(V3+V1+V2)/3.0);
1541static void FaceSimilar(MeshType & m, VertexSampler &ps,
int sampleNum,
bool dualFlag,
bool randomFlag)
1543 ScalarType area = Stat<MeshType>::ComputeMeshArea(m);
1544 ScalarType samplePerAreaUnit = sampleNum/area;
1547 int n_samples_per_edge;
1548 double n_samples_decimal = 0.0;
1551 for(fi=m.face.begin(); fi != m.face.end(); fi++)
1554 n_samples_decimal += 0.5*DoubleArea(*fi) * samplePerAreaUnit;
1555 int n_samples = (int) n_samples_decimal;
1561 n_samples_per_edge = (int)((sqrt(1.0+8.0*(
double)n_samples) +5.0)/2.0);
1562 n_samples = SingleFaceSimilar(&*fi,ps, n_samples_per_edge);
1564 n_samples_per_edge = (int)(sqrt((
double)n_samples) +1.0);
1565 n_samples = SingleFaceSimilarDual(&*fi,ps, n_samples_per_edge,randomFlag);
1568 n_samples_decimal -= (double) n_samples;
1582 static void SingleFaceRaster(
typename MeshType::FaceType &f, VertexSampler &ps,
1583 const Point2<typename MeshType::ScalarType> & v0,
1584 const Point2<typename MeshType::ScalarType> & v1,
1585 const Point2<typename MeshType::ScalarType> & v2,
1586 bool correctSafePointsBaryCoords=
true)
1588 typedef typename MeshType::ScalarType S;
1596 bbox.min[0] = floor(bboxf.min[0]);
1597 bbox.min[1] = floor(bboxf.min[1]);
1598 bbox.max[0] = ceil(bboxf.max[0]);
1599 bbox.max[1] = ceil(bboxf.max[1]);
1602 Point2<S> d10 = v1 - v0;
1603 Point2<S> d21 = v2 - v1;
1604 Point2<S> d02 = v0 - v2;
1607 S b0 = (bbox.min[0]-v0[0])*d10[1] - (bbox.min[1]-v0[1])*d10[0];
1608 S b1 = (bbox.min[0]-v1[0])*d21[1] - (bbox.min[1]-v1[1])*d21[0];
1609 S b2 = (bbox.min[0]-v2[0])*d02[1] - (bbox.min[1]-v2[1])*d02[0];
1620 bool flipped = !(d02 * vcg::Point2<S>(-d10[1], d10[0]) >= 0);
1623 Segment2<S> borderEdges[3];
1625 unsigned char edgeMask = 0;
1628 borderEdges[0] = Segment2<S>(v0, v1);
1629 edgeLength[0] = borderEdges[0].Length();
1633 borderEdges[1] = Segment2<S>(v1, v2);
1634 edgeLength[1] = borderEdges[1].Length();
1638 borderEdges[2] = Segment2<S>(v2, v0);
1639 edgeLength[2] = borderEdges[2].Length();
1644 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];
1646 for(
int x=bbox.min[0]-1;x<=bbox.max[0]+1;++x)
1649 S n[3] = { b0-db0-dn0, b1-db1-dn1, b2-db2-dn2};
1650 for(
int y=bbox.min[1]-1;y<=bbox.max[1]+1;++y)
1652 if( ((n[0]>=0 && n[1]>=0 && n[2]>=0) || (n[0]<=0 && n[1]<=0 && n[2]<=0)) && (de != 0))
1654 typename MeshType::CoordType baryCoord;
1655 baryCoord[0] = double(-y*v1[0]+v2[0]*y+v1[1]*x-v2[0]*v1[1]+v1[0]*v2[1]-x*v2[1])/de;
1656 baryCoord[1] = -double( x*v0[1]-x*v2[1]-v0[0]*y+v0[0]*v2[1]-v2[0]*v0[1]+v2[0]*y)/de;
1657 baryCoord[2] = 1-baryCoord[0]-baryCoord[1];
1659 ps.AddTextureSample(f, baryCoord, Point2i(x,y), 0);
1664 Point2<S> closePoint;
1669 for (
int i=0; i<3; ++i)
1671 if (edgeMask & (1 << i))
1675 if ( ((!flipped) && (n[i]<0)) ||
1676 ( flipped && (n[i]>0)) )
1678 dst = ((close = ClosestPoint(borderEdges[i], px)) - px).Norm();
1680 close.X() > px.X()-1 && close.X() < px.X()+1 &&
1681 close.Y() > px.Y()-1 && close.Y() < px.Y()+1)
1693 typename MeshType::CoordType baryCoord;
1694 if (correctSafePointsBaryCoords)
1697 baryCoord[closeEdge] = (closePoint - borderEdges[closeEdge].P1()).Norm()/edgeLength[closeEdge];
1698 baryCoord[(closeEdge+1)%3] = 1 - baryCoord[closeEdge];
1699 baryCoord[(closeEdge+2)%3] = 0;
1702 baryCoord[0] = double(-y*v1[0]+v2[0]*y+v1[1]*x-v2[0]*v1[1]+v1[0]*v2[1]-x*v2[1])/de;
1703 baryCoord[1] = -double( x*v0[1]-x*v2[1]-v0[0]*y+v0[0]*v2[1]-v2[0]*v0[1]+v2[0]*y)/de;
1704 baryCoord[2] = 1-baryCoord[0]-baryCoord[1];
1706 ps.AddTextureSample(f, baryCoord, Point2i(x,y), minDst);
1721static bool checkPoissonDisk(SampleSHT & sht,
const Point3<ScalarType> & p, ScalarType radius)
1724 std::vector<VertexType*> closests;
1725 typedef EmptyTMark<MeshType> MarkerVert;
1726 static MarkerVert mv;
1728 Box3f bb(p-Point3f(radius,radius,radius),p+Point3f(radius,radius,radius));
1729 GridGetInBox(sht, mv, bb, closests);
1731 ScalarType r2 = radius*radius;
1732 for(
int i=0; i<closests.size(); ++i)
1733 if(SquaredDistance(p,closests[i]->cP()) < r2)
1743 adaptiveRadiusFlag =
false;
1744 bestSampleChoiceFlag =
true;
1745 bestSamplePoolSize = 10;
1748 invertQuality =
false;
1751 geodesicDistanceFlag =
false;
1764 int montecarloSampleNum;
1767 bool geodesicDistanceFlag;
1768 bool bestSampleChoiceFlag;
1769 int bestSamplePoolSize;
1770 bool adaptiveRadiusFlag;
1771 float radiusVariance;
1775 MeshType *preGenMesh;
1786static VertexPointer getSampleFromCell(
Point3i &cell, MontecarloSHT & samplepool)
1788 MontecarloSHTIterator cellBegin, cellEnd;
1789 samplepool.Grid(cell, cellBegin, cellEnd);
1796static VertexPointer getBestPrecomputedMontecarloSample(
Point3i &cell, MontecarloSHT & samplepool, ScalarType diskRadius,
const PoissonDiskParam &pp)
1798 MontecarloSHTIterator cellBegin,cellEnd;
1799 samplepool.Grid(cell, cellBegin, cellEnd);
1800 VertexPointer bestSample=0;
1801 int minRemoveCnt = std::numeric_limits<int>::max();
1802 std::vector<typename MontecarloSHT::HashIterator> inSphVec;
1804 for(MontecarloSHTIterator ci=cellBegin; ci!=cellEnd && i<pp.bestSamplePoolSize; ++ci,i++)
1806 VertexPointer sp = *ci;
1807 if(pp.adaptiveRadiusFlag) diskRadius = sp->Q();
1808 int curRemoveCnt = samplepool.CountInSphere(sp->cP(),diskRadius,inSphVec);
1809 if(curRemoveCnt < minRemoveCnt)
1812 minRemoveCnt = curRemoveCnt;
1822 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
1827 meshArea = (origMesh.bbox.DimX()*origMesh.bbox.DimY() +
1828 origMesh.bbox.DimX()*origMesh.bbox.DimZ() +
1829 origMesh.bbox.DimY()*origMesh.bbox.DimZ());
1831 ScalarType diskRadius = sqrt(meshArea / (0.7 * M_PI * sampleNum));
1835static int ComputePoissonSampleNum(MeshType &origMesh, ScalarType diskRadius)
1837 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
1838 int sampleNum = meshArea / (diskRadius*diskRadius *M_PI *0.7) ;
1849static void InitRadiusHandleFromQuality(MeshType &sampleMesh, PerVertexFloatAttribute &rH, ScalarType diskRadius, ScalarType radiusVariance,
bool invert)
1851 std::pair<float,float> minmax = tri::Stat<MeshType>::ComputePerVertexQualityMinMax( sampleMesh);
1852 float minRad = diskRadius ;
1853 float maxRad = diskRadius * radiusVariance;
1854 float deltaQ = minmax.second-minmax.first;
1855 float deltaRad = maxRad-minRad;
1856 for (VertexIterator vi = sampleMesh.vert.begin(); vi != sampleMesh.vert.end(); vi++)
1858 rH[*vi] = minRad + deltaRad*((invert ? minmax.second - (*vi).Q() : (*vi).Q() - minmax.first )/deltaQ);
1867static void InitSpatialHashTable(MeshType &montecarloMesh, MontecarloSHT &montecarloSHT, ScalarType diskRadius,
1868 struct PoissonDiskParam pp=PoissonDiskParam())
1870 ScalarType cellsize = 2.0f* diskRadius / sqrt(3.0);
1871 float occupancyRatio=0;
1875 BoxType bb=montecarloMesh.bbox;
1876 assert(!bb.IsNull());
1877 bb.Offset(cellsize);
1879 int sizeX = std::max(1,
int(bb.DimX() / cellsize));
1880 int sizeY = std::max(1,
int(bb.DimY() / cellsize));
1881 int sizeZ = std::max(1,
int(bb.DimZ() / cellsize));
1882 Point3i gridsize(sizeX, sizeY, sizeZ);
1884 montecarloSHT.InitEmpty(bb, gridsize);
1886 for (VertexIterator vi = montecarloMesh.vert.begin(); vi != montecarloMesh.vert.end(); vi++)
1889 montecarloSHT.Add(&(*vi));
1892 montecarloSHT.UpdateAllocatedCells();
1893 pp.pds.gridSize = gridsize;
1894 pp.pds.gridCellNum = (int)montecarloSHT.AllocatedCells.size();
1896 occupancyRatio = float(montecarloMesh.vn) / float(montecarloSHT.AllocatedCells.size());
1899 while( occupancyRatio> 100);
1902static void PoissonDiskPruningByNumber(VertexSampler &ps, MeshType &m,
1903 size_t sampleNum, ScalarType &diskRadius,
1904 PoissonDiskParam &pp,
1905 float tolerance=0.04,
1909 size_t sampleNumMin = int(
float(sampleNum)*(1.0f-tolerance));
1910 size_t sampleNumMax = int(
float(sampleNum)*(1.0f+tolerance));
1911 float RangeMinRad = m.bbox.Diag()/50.0;
1912 float RangeMaxRad = m.bbox.Diag()/50.0;
1913 size_t RangeMinRadNum;
1914 size_t RangeMaxRadNum;
1921 RangeMinRadNum = pp.pds.sampleNum;
1923 }
while(RangeMinRadNum < sampleNum);
1929 RangeMaxRadNum = pp.pds.sampleNum;
1931 }
while(RangeMaxRadNum > sampleNum);
1934 float curRadius=RangeMaxRad;
1936 while(iterCnt<maxIter &&
1937 (pp.pds.sampleNum < sampleNumMin || pp.pds.sampleNum > sampleNumMax) )
1941 curRadius=(RangeMaxRad+RangeMinRad)/2.0f;
1944 if(pp.pds.sampleNum > sampleNum){
1945 RangeMinRad = curRadius;
1946 RangeMinRadNum = pp.pds.sampleNum;
1948 if(pp.pds.sampleNum < sampleNum){
1949 RangeMaxRad = curRadius;
1950 RangeMaxRadNum = pp.pds.sampleNum;
1953 diskRadius = curRadius;
1969 tri::RequireCompactness(montecarloMesh);
1970 if(pp.randomSeed) SamplingRandomGenerator().initialize(pp.randomSeed);
1971 if(pp.adaptiveRadiusFlag)
1972 tri::RequirePerVertexQuality(montecarloMesh);
1975 MontecarloSHT montecarloSHT;
1976 InitSpatialHashTable(montecarloMesh,montecarloSHT,diskRadius,pp);
1980 PerVertexFloatAttribute rH =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (montecarloMesh,
"radius");
1981 if(pp.adaptiveRadiusFlag)
1989 std::shuffle(montecarloSHT.AllocatedCells.begin(),montecarloSHT.AllocatedCells.end(), g);
1991 pp.pds.montecarloSampleNum = montecarloMesh.vn;
1992 pp.pds.sampleNum =0;
1997 if(pp.preGenMesh==0)
1999 typename MeshType::template PerVertexAttributeHandle<bool> fixed;
2001 for(VertexIterator vi=montecarloMesh.vert.begin();vi!=montecarloMesh.vert.end();++vi)
2005 removedCnt += montecarloSHT.RemoveInSphere(vi->cP(),diskRadius);
2010 for(VertexIterator vi =pp.preGenMesh->vert.begin(); vi!=pp.preGenMesh->vert.end();++vi)
2014 removedCnt += montecarloSHT.RemoveInSphere(vi->cP(),diskRadius);
2017 montecarloSHT.UpdateAllocatedCells();
2019 vertex::ApproximateGeodesicDistanceFunctor<VertexType> GDF;
2020 while(!montecarloSHT.AllocatedCells.empty())
2023 for (
size_t i = 0; i < montecarloSHT.AllocatedCells.size(); i++)
2025 if( montecarloSHT.EmptyCell(montecarloSHT.AllocatedCells[i]) )
continue;
2026 ScalarType currentRadius =diskRadius;
2028 if(pp.bestSampleChoiceFlag)
2029 sp = getBestPrecomputedMontecarloSample(montecarloSHT.AllocatedCells[i], montecarloSHT, diskRadius, pp);
2031 sp = getSampleFromCell(montecarloSHT.AllocatedCells[i], montecarloSHT);
2033 if(pp.adaptiveRadiusFlag)
2034 currentRadius = rH[sp];
2038 if(pp.geodesicDistanceFlag) removedCnt += montecarloSHT.RemoveInSphereNormal(sp->cP(),sp->cN(),GDF,currentRadius);
2039 else removedCnt += montecarloSHT.RemoveInSphere(sp->cP(),currentRadius);
2041 montecarloSHT.UpdateAllocatedCells();
2044 pp.pds.gridTime = t1-t0;
2045 pp.pds.pruneTime = t2-t1;
2062 MontecarloSHT montecarloSHTVec[5];
2069 ScalarType cellsize = 2.0f* diskRadius / sqrt(3.0);
2072 BoxType bb=origMesh.bbox;
2073 bb.Offset(cellsize);
2075 int sizeX = std::max(1.0f,bb.DimX() / cellsize);
2076 int sizeY = std::max(1.0f,bb.DimY() / cellsize);
2077 int sizeZ = std::max(1.0f,bb.DimZ() / cellsize);
2078 Point3i gridsize(sizeX, sizeY, sizeZ);
2082 checkSHT.InitEmpty(bb, gridsize);
2098 montecarloSHTVec[0].InitEmpty(bb, gridsize);
2100 for (VertexIterator vi = montecarloMesh.vert.begin(); vi != montecarloMesh.vert.end(); vi++)
2101 montecarloSHTVec[0].Add(&(*vi));
2102 montecarloSHTVec[0].UpdateAllocatedCells();
2105 PerVertexFloatAttribute rH =
tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (montecarloMesh,
"radius");
2106 if(pp.adaptiveRadiusFlag)
2111 MontecarloSHT &montecarloSHT = montecarloSHTVec[level];
2115 montecarloSHT.InitEmpty(bb, gridsize);
2117 for (
typename MontecarloSHT::HashIterator hi = montecarloSHTVec[level-1].hash_table.begin(); hi != montecarloSHTVec[level-1].hash_table.end(); hi++)
2118 montecarloSHT.Add((*hi).second);
2119 montecarloSHT.UpdateAllocatedCells();
2123 std::random_device rd;
2127 std::shuffle(montecarloSHT.AllocatedCells.begin(),montecarloSHT.AllocatedCells.end(), g);
2131 int removedCnt=montecarloSHT.hash_table.size();
2132 int addedCnt=checkSHT.hash_table.size();
2133 for (
int i = 0; i < montecarloSHT.AllocatedCells.size(); i++)
2135 for(
int j=0;j<4;j++)
2137 if( montecarloSHT.EmptyCell(montecarloSHT.AllocatedCells[i]) )
continue;
2140 typename MontecarloSHT::HashIterator hi = montecarloSHT.hash_table.find(montecarloSHT.AllocatedCells[i]);
2142 if(hi==montecarloSHT.hash_table.end()) {
break;}
2143 VertexPointer sp = (*hi).second;
2145 ScalarType sampleRadius = diskRadius;
2146 if(pp.adaptiveRadiusFlag) sampleRadius = rH[sp];
2147 if (checkPoissonDisk(checkSHT, sp->cP(), sampleRadius))
2150 montecarloSHT.RemoveCell(sp);
2155 montecarloSHT.RemovePunctual(sp);
2158 addedCnt = checkSHT.hash_table.size()-addedCnt;
2159 removedCnt = removedCnt-montecarloSHT.hash_table.size();
2183static void Texture(MeshType & m, VertexSampler &ps,
int textureWidth,
int textureHeight,
bool correctSafePointsBaryCoords=
true)
2185typedef Point2<ScalarType> Point2x;
2187 for(FaceIterator fi=m.face.begin(); fi != m.face.end(); fi++)
2191 for(
int i=0;i<3;++i)
2192 ti[i]=Point2x((*fi).WT(i).U() * textureWidth - 0.5, (*fi).WT(i).V() * textureHeight - 0.5);
2195 SingleFaceRaster(*fi, ps, ti[0],ti[1],ti[2], correctSafePointsBaryCoords);
2199typedef GridStaticPtr<FaceType, ScalarType > TriMeshGrid;
2206tri::FaceTmark<MeshType> markerFunctor;
2210static void RegularRecursiveOffset(MeshType & m, std::vector<CoordType> &pvec, ScalarType offset,
float minDiag)
2217 rrp.markerFunctor.SetMesh(&m);
2219 rrp.gM.Set(m.face.begin(),m.face.end(),bb);
2223 rrp.minDiag=minDiag;
2224 SubdivideAndSample(m, pvec, bb, rrp, bb.
Diag());
2227static void SubdivideAndSample(MeshType & m, std::vector<CoordType> &pvec,
const Box3<ScalarType> bb, RRParam &rrp,
float curDiag)
2229 CoordType startPt = bb.
Center();
2233 FaceType *nearestF=0;
2234 ScalarType dist_upper_bound = curDiag+rrp.offset;
2235 CoordType closestPt;
2236 vcg::face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
2237 dist=dist_upper_bound;
2238 nearestF = rrp.gM.GetClosest(PDistFunct,rrp.markerFunctor,startPt,dist_upper_bound,dist,closestPt);
2240 if(dist < dist_upper_bound)
2242 if(curDiag/3 < rrp.minDiag)
2245 pvec.push_back(closestPt);
2250 CoordType delta = startPt-closestPt;
2251 pvec.push_back(closestPt+delta*(rrp.offset/dist));
2255 if(curDiag < rrp.minDiag)
return;
2256 CoordType hs = (bb.
max-bb.
min)/2;
2257 for(
int i=0;i<2;i++)
2258 for(
int j=0;j<2;j++)
2259 for(
int k=0;k<2;k++)
2260 SubdivideAndSample(m, pvec,
2261 BoxType(CoordType( bb.
min[0]+i*hs[0], bb.
min[1]+j*hs[1], bb.
min[2]+k*hs[2]),
2262 CoordType(startPt[0]+i*hs[0], startPt[1]+j*hs[1], startPt[2]+k*hs[2]) ),
2270template <
class MeshType>
2271typename MeshType::ScalarType ComputePoissonDiskRadius(MeshType &origMesh,
int sampleNum)
2273 typedef typename MeshType::ScalarType ScalarType;
2274 ScalarType meshArea = Stat<MeshType>::ComputeMeshArea(origMesh);
2279 meshArea = (origMesh.bbox.DimX()*origMesh.bbox.DimY() +
2280 origMesh.bbox.DimX()*origMesh.bbox.DimZ() +
2281 origMesh.bbox.DimY()*origMesh.bbox.DimZ());
2283 ScalarType diskRadius = sqrt(meshArea / (0.7 * M_PI * sampleNum));
2289template <
class MeshType>
2290void MontecarloSampling(MeshType &m,
2294 typedef tri::MeshSampler<MeshType> BaseSampler;
2295 MeshSampler<MeshType> mcSampler(&mm);
2300template <
class MeshType>
2301void MontecarloSampling(MeshType &m,
2302 std::vector<Point3f> &montercarloSamples,
2305 typedef tri::TrivialSampler<MeshType> BaseSampler;
2306 BaseSampler mcSampler(montercarloSamples);
2312template <
class MeshType>
2313void PoissonSampling(MeshType &m,
2314 std::vector<typename MeshType::CoordType> &poissonSamples,
2316 typename MeshType::ScalarType &radius,
2317 typename MeshType::ScalarType radiusVariance=1,
2318 typename MeshType::ScalarType PruningByNumberTolerance=0.04f,
2319 unsigned int randSeed=0)
2322 typedef tri::TrivialSampler<MeshType> BaseSampler;
2323 typedef tri::MeshSampler<MeshType> MontecarloSampler;
2325 typename tri::SurfaceSampling<MeshType, BaseSampler>::PoissonDiskParam pp;
2329 if(radius>0 && sampleNum==0) sampleNum = tri::SurfaceSampling<MeshType,BaseSampler>::ComputePoissonSampleNum(m,radius);
2331 pp.pds.sampleNum = sampleNum;
2332 pp.randomSeed = randSeed;
2333 poissonSamples.clear();
2335 MeshType MontecarloMesh;
2338 MontecarloSampler mcSampler(MontecarloMesh);
2339 BaseSampler pdSampler(poissonSamples);
2341 if(randSeed) tri::SurfaceSampling<MeshType,MontecarloSampler>::SamplingRandomGenerator().initialize(randSeed);
2346 pp.pds.montecarloTime = t1-t0;
2348 if(radiusVariance !=1)
2350 pp.adaptiveRadiusFlag=
true;
2351 pp.radiusVariance=radiusVariance;
2354 else tri::SurfaceSampling<MeshType,BaseSampler>::PoissonDiskPruningByNumber(pdSampler, MontecarloMesh, sampleNum, radius,pp,PruningByNumberTolerance);
2356 pp.pds.totalTime = t2-t0;
2363template <
class MeshType>
2365 std::vector<typename MeshType::VertexPointer> &poissonSamples,
2366 float radius,
unsigned int randSeed=0)
2370 pp.randomSeed = randSeed;
2373 BaseSampler pdSampler;
2375 poissonSamples = pdSampler.sampleVec;
2384template <
class MeshType>
2386 std::vector<typename MeshType::CoordType> &poissonSamples,
2387 float radius,
unsigned int randSeed=0)
2389 std::vector<typename MeshType::VertexPointer> poissonSamplesVP;
2391 poissonSamples.resize(poissonSamplesVP.size());
2392 for(
size_t i=0;i<poissonSamplesVP.size();++i)
2393 poissonSamples[i]=poissonSamplesVP[i]->P();
2403template <
class MeshType>
2405 std::vector<typename MeshType::VertexPointer> &poissonSamples,
2406 typename MeshType::ScalarType & radius,
2408 float tolerance=0.04,
2410 unsigned int randSeed=0)
2412 size_t sampleNumMin = int(
float(sampleNum)*(1.0f-tolerance));
2413 size_t sampleNumMax = int(
float(sampleNum)*(1.0f+tolerance));
2414 float RangeMinRad = m.bbox.Diag()/10.0f;
2415 float RangeMaxRad = m.bbox.Diag()/10.0f;
2416 size_t RangeMinSampleNum;
2417 size_t RangeMaxSampleNum;
2418 std::vector<typename MeshType::VertexPointer> poissonSamplesTmp;
2424 RangeMinSampleNum = poissonSamplesTmp.size();
2425 }
while(RangeMinSampleNum < sampleNumMin);
2431 RangeMaxSampleNum = poissonSamplesTmp.size();
2432 }
while(RangeMaxSampleNum > sampleNumMax);
2436 while(iterCnt<maxIter &&
2437 (poissonSamplesTmp.size() < sampleNumMin || poissonSamplesTmp.size() > sampleNumMax) )
2439 curRadius=(RangeMaxRad+RangeMinRad)/2.0f;
2442 if(poissonSamplesTmp.size() >
size_t(sampleNum))
2443 RangeMinRad = curRadius;
2444 if(poissonSamplesTmp.size() <
size_t(sampleNum))
2445 RangeMaxRad = curRadius;
2448 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:531
Definition: point_sampling.h:2202
Main Class of the Sampling framework.
Definition: point_sampling.h:476
static void Montecarlo(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:1206
static void HierarchicalPoissonDisk(MeshType &origMesh, VertexSampler &ps, MeshType &montecarloMesh, ScalarType diskRadius, const struct PoissonDiskParam pp=PoissonDiskParam())
Definition: point_sampling.h:2058
static void VertexAreaUniform(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:725
static void VertexWeighted(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:687
static void VertexCrease(MeshType &m, VertexSampler &ps)
Definition: point_sampling.h:984
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:773
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:1341
static void PoissonDiskPruning(VertexSampler &ps, MeshType &montecarloMesh, ScalarType diskRadius, PoissonDiskParam &pp)
Definition: point_sampling.h:1966
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:1820
EdgeSamplingRoundingStrategy
The EdgeSamplingStrategy enum determines the sampling strategy for edge meshes. Given a sampling radi...
Definition: point_sampling.h:808
static void VertexBorder(MeshType &m, VertexSampler &ps)
Sample all the border vertices.
Definition: point_sampling.h:973
static void VertexBorderCorner(MeshType &m, VertexSampler &ps, ScalarType angleRad)
Sample all the border corner vertices.
Definition: point_sampling.h:959
static void EdgeMeshUniform(MeshType &m, VertexSampler &ps, float radius, EdgeSamplingRoundingStrategy strategy=Floor)
Definition: point_sampling.h:830
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:1432
static int Poisson(double lambda)
Definition: point_sampling.h:647
static void MontecarloPoisson(MeshType &m, VertexSampler &ps, int sampleNum)
Definition: point_sampling.h:1139
static void WeightedMontecarlo(MeshType &m, VertexSampler &ps, int sampleNum, float variance)
Definition: point_sampling.h:1249
static void InitRadiusHandleFromQuality(MeshType &sampleMesh, PerVertexFloatAttribute &rH, ScalarType diskRadius, ScalarType radiusVariance, bool invert)
Definition: point_sampling.h:1849
static void EdgeMontecarlo(MeshType &m, VertexSampler &ps, int sampleNum, bool sampleAllEdges)
Definition: point_sampling.h:1165
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:2404
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:2364
Definition: point_sampling.h:1756
Definition: point_sampling.h:1740