From 4be7b59a8050fd66c694a9d2fbdff0322708acdf Mon Sep 17 00:00:00 2001 From: cignoni Date: Thu, 17 Apr 2014 09:51:48 +0000 Subject: [PATCH] Added TrivialPointerSampler to sample a mesh returning pointers to the chosen vertexes. Added another poisson pruning wrapper to make even easier to choose a subset of vertexes from a mesh with good distribution. --- vcg/complex/algorithms/point_sampling.h | 97 +++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 8 deletions(-) diff --git a/vcg/complex/algorithms/point_sampling.h b/vcg/complex/algorithms/point_sampling.h index a959ed73..9289129f 100644 --- a/vcg/complex/algorithms/point_sampling.h +++ b/vcg/complex/algorithms/point_sampling.h @@ -115,8 +115,28 @@ public: } }; // end class TrivialSampler +template +class TrivialPointerSampler +{ +public: + typedef typename MeshType::CoordType CoordType; + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::FaceType FaceType; + TrivialPointerSampler() {} + ~TrivialPointerSampler() {} +public: + std::vector sampleVec; + + void AddVert(const VertexType &p) + { + sampleVec->push_back(&p); + } + // This sampler should be used only for getting vertex pointers. Meaningless in other case. + void AddFace(const FaceType &, const CoordType &) { assert(0); } + void AddTextureSample(const FaceType &, const CoordType &, const Point2i &, float ) { assert(0); } +}; // end class TrivialSampler template @@ -1381,6 +1401,8 @@ static void InitSpatialHashTable(MetroMesh &montecarloMesh, MontecarloSHT &monte static void PoissonDiskPruning(VertexSampler &ps, MetroMesh &montecarloMesh, ScalarType diskRadius, const struct PoissonDiskParam pp=PoissonDiskParam()) { + if(pp.adaptiveRadiusFlag) + tri::RequirePerVertexQuality(montecarloMesh); int t0 = clock(); // spatial index of montecarlo samples - used to choose a new sample to insert MontecarloSHT montecarloSHT; @@ -1733,15 +1755,74 @@ void PoissonSampling(MeshType &m, // the mesh that has to be sampled template void PoissonPruning(MeshType &m, // the mesh that has to be pruned std::vector &poissonSamples, // the vector that will contain the chosen set of points - float & radius) + float & radius, int sampleNum=0) { - typedef tri::TrivialSampler BaseSampler; - typename tri::SurfaceSampling::PoissonDiskParam pp; - typename tri::SurfaceSampling::PoissonDiskParam::Stat stat; - pp.pds = &stat; - tri::UpdateBounding::Box(m); - BaseSampler pdSampler(poissonSamples); - tri::SurfaceSampling::PoissonDiskPruning(pdSampler, m, radius,pp); + typedef tri::TrivialSampler BaseSampler; + typename tri::SurfaceSampling::PoissonDiskParam pp; + if(sampleNum>0 && radius==0) + radius = tri::SurfaceSampling::ComputePoissonDiskRadius(m,sampleNum); + tri::UpdateBounding::Box(m); + BaseSampler pdSampler(poissonSamples); + tri::SurfaceSampling::PoissonDiskPruning(pdSampler, m, radius,pp); +} + + +/// \brief Very simple wrapping for the Poisson Disk Pruning +/// +/// This function simply takes a mesh and a radius and returns a vector of points +// +template +void PoissonPruning(MeshType &m, // the mesh that has to be pruned + std::vector &poissonSamples, // the vector that will contain the chosen set of points + float & radius, int sampleNum=0) +{ + typedef tri::TrivialPointerSampler BaseSampler; + typename tri::SurfaceSampling::PoissonDiskParam pp; + if(sampleNum>0 && radius==0) + radius = tri::SurfaceSampling::ComputePoissonDiskRadius(m,sampleNum); + + tri::UpdateBounding::Box(m); + BaseSampler pdSampler; + tri::SurfaceSampling::PoissonDiskPruning(pdSampler, m, radius,pp); + std::swap(pdSampler.sampleVec,poissonSamples); +} + +/// \brief Very simple wrapping for the Exact Poisson Disk Pruning +/// +/// This function simply takes a mesh and an expected number of points and returns +/// vector of points. It performs multiple attempts with varius radii to correctly get the expected number of samples. +/// It is obviously much slower than the other versions... + + +template +void PoissonPruningExact(MeshType &m, // the mesh that has to be pruned + std::vector &poissonSamples, // the vector that will contain the chosen set of points + float & radius, + int sampleNum, + float tolerance=0.04, + int maxIter=20) +{ + int sampleNumMin = int(float(sampleNum)*(1.0f-tolerance)); + int sampleNumMax = int(float(sampleNum)*(1.0f+tolerance)); + float RadiusRangeMin = m.bbox.Diag()/100.0; + float RadiusRangeMax = m.bbox.Diag(); + std::vector poissonSamplesTmp; + float curRadius; + int iterCnt=0; + while(iterCnt sampleNumMax) ) + { + curRadius=(RadiusRangeMax+RadiusRangeMin)/2.0f; + PoissonPruning(m,poissonSamplesTmp,curRadius); + //qDebug("(%f %f) Cur Radius %f -> %i sample instead of %i",RadiusRangeMin,RadiusRangeMax,curRadius,poissonSamplesTmp.size(),sampleNum); + if(poissonSamplesTmp.size() > sampleNum) + RadiusRangeMin = curRadius; + if(poissonSamplesTmp.size() < sampleNum) + RadiusRangeMax = curRadius; + } + + swap(poissonSamples,poissonSamplesTmp); + radius = curRadius; } } // end namespace tri } // end namespace vcg