Visual Computing Library  devel
Loading...
Searching...
No Matches
point_sampling.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_ALGORITHMS_MESH_POINT_SAMPLING_H
24#define VCL_ALGORITHMS_MESH_POINT_SAMPLING_H
25
26#include <vclib/algorithms/mesh/shuffle.h>
27#include <vclib/algorithms/mesh/stat.h>
28
29#include <vclib/mesh.h>
30#include <vclib/space/complex.h>
31
49namespace vcl {
50
73template<SamplerConcept SamplerType, MeshConcept MeshType>
75 const MeshType& m,
76 std::vector<uint>& birthVertices,
77 bool onlySelected = false)
78{
79 using VertexType = MeshType::VertexType;
80
82
83 // Determine the number of vertices to sample
84 uint n = onlySelected ? vertexSelectionNumber(m) : m.vertexNumber();
85
86 // Reserve space in the sampler and birthVertices vectors
87 sampler.reserve(n);
88 birthVertices.reserve(n);
89 birthVertices.clear();
90
91 // Loop through all the vertices in the mesh and add them to the sampler if
92 // they are selected
93 for (const VertexType& v : m.vertices()) {
94 if (!onlySelected || v.selected()) {
95 sampler.add(v);
96 birthVertices.push_back(m.index(v));
97 }
98 }
99 return sampler;
100}
101
121template<SamplerConcept SamplerType, MeshConcept MeshType>
123 const MeshType& m,
124 bool onlySelected = false)
125{
126 std::vector<uint> v;
128}
129
156template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
158 const MeshType& m,
159 std::vector<uint>& birthFaces,
160 bool onlySelected = false)
161{
162 using FaceType = MeshType::FaceType;
163
165
166 // Determine the number of vertices to sample
167 uint n = onlySelected ? faceSelectionNumber(m) : m.faceNumber();
168
169 // Reserve space in the sampler and birthVertices vectors
170 sampler.reserve(n);
171 birthFaces.reserve(n);
172 birthFaces.clear();
173
174 for (const FaceType& f : m.faces()) {
175 if (!onlySelected || f.selected()) {
176 sampler.add(f);
177 birthFaces.push_back(m.index(f));
178 }
179 }
180 return sampler;
181}
182
206template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
207SamplerType allFacesPointSampling(const MeshType& m, bool onlySelected = false)
208{
209 std::vector<uint> v;
211}
212
233template<SamplerConcept SamplerType, MeshConcept MeshType>
235 const MeshType& m,
236 uint nSamples,
237 std::vector<uint>& birthVertices,
238 bool onlySelected = false,
239 std::optional<uint> seed = std::nullopt)
240{
241 uint vn = onlySelected ? vertexSelectionNumber(m) : m.vertexNumber();
242
243 if (nSamples >= vn) {
246 }
247
249
250 // Reserve space in the sampler and birthVertices vectors
251 ps.reserve(vn);
252 birthVertices.reserve(vn);
253 birthVertices.clear();
254
255 std::uniform_int_distribution<uint> dist(0, m.vertexContainerSize() - 1);
256
257 std::mt19937 gen = randomGenerator(seed);
258
259 std::vector<bool> visited(m.vertexContainerSize(), false);
260 uint nVisited = 0;
261
262 while (nVisited < nSamples) {
263 uint vi = dist(gen);
264 if (!m.vertex(vi).deleted() && !visited[vi] &&
265 (!onlySelected || m.vertex(vi).selected())) {
266 visited[vi] = true;
267 nVisited++;
268 ps.add(m.vertex(vi));
269 birthVertices.push_back(vi);
270 }
271 }
272
273 return ps;
274}
275
294template<SamplerConcept SamplerType, MeshConcept MeshType>
296 const MeshType& m,
297 uint nSamples,
298 bool onlySelected = false,
299 std::optional<uint> seed = std::nullopt)
300{
301 std::vector<uint> v;
304}
305
331template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
333 const MeshType& m,
334 uint nSamples,
335 std::vector<uint>& birthFaces,
336 bool onlySelected = false,
337 std::optional<uint> seed = std::nullopt)
338{
339 uint fn = onlySelected ? faceSelectionNumber(m) : m.faceNumber();
340
341 if (nSamples >= fn) {
343 }
344
346
347 // Reserve space in the sampler and birthFaces vectors
348 ps.reserve(fn);
349 birthFaces.reserve(fn);
350 birthFaces.clear();
351
352 std::uniform_int_distribution<uint> dist(0, m.faceContainerSize() - 1);
353
354 std::mt19937 gen = randomGenerator(seed);
355
356 std::vector<bool> visited(m.faceContainerSize(), false);
357 uint nVisited = 0;
358
359 while (nVisited < nSamples) {
360 uint fi = dist(gen);
361 if (!m.face(fi).deleted() && !visited[fi] &&
362 (!onlySelected || m.face(fi).selected())) {
363 visited[fi] = true;
364 nVisited++;
365 ps.add(m.face(fi));
366 birthFaces.push_back(fi);
367 }
368 }
369
370 return ps;
371}
372
395template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
397 const MeshType& m,
398 uint nSamples,
399 bool onlySelected = false,
400 std::optional<uint> seed = std::nullopt)
401{
402 std::vector<uint> v;
405}
406
432template<SamplerConcept SamplerType, MeshConcept MeshType, typename ScalarType>
434 const MeshType& m,
435 const std::vector<ScalarType>& weights,
436 uint nSamples,
437 std::vector<uint>& birthVertices,
438 std::optional<uint> seed = std::nullopt)
439{
440 if (nSamples >= m.vertexNumber()) {
442 }
443
445 ps.reserve(nSamples);
446 birthVertices.reserve(nSamples);
447 birthVertices.clear();
448
449 std::discrete_distribution<> dist(std::begin(weights), std::end(weights));
450
451 std::mt19937 gen = randomGenerator(seed);
452
453 std::vector<bool> visited(m.vertexContainerSize(), false);
454 uint nVisited = 0;
455
456 while (nVisited < nSamples) {
457 uint vi = dist(gen);
458 if (vi < m.vertexContainerSize() && !m.vertex(vi).deleted() &&
459 !visited[vi]) {
460 visited[vi] = true;
461 nVisited++;
462 ps.add(m.vertex(vi));
463 birthVertices.push_back(vi);
464 }
465 }
466
467 return ps;
468}
469
492template<SamplerConcept SamplerType, MeshConcept MeshType, typename ScalarType>
494 const MeshType& m,
495 const std::vector<ScalarType>& weights,
496 uint nSamples,
497 std::optional<uint> seed = std::nullopt)
498{
499 std::vector<uint> v;
501 m, weights, nSamples, v, seed);
502}
503
532template<
533 SamplerConcept SamplerType,
534 FaceMeshConcept MeshType,
535 typename ScalarType>
537 const MeshType& m,
538 const std::vector<ScalarType>& weights,
539 uint nSamples,
540 std::vector<uint>& birthFaces,
541 std::optional<uint> seed = std::nullopt)
542{
543 if (nSamples >= m.faceNumber()) {
545 }
546
548
549 // Reserve space in the sampler and birthFaces vectors
550 ps.reserve(nSamples);
551 birthFaces.reserve(nSamples);
552 birthFaces.clear();
553
554 std::discrete_distribution<> dist(std::begin(weights), std::end(weights));
555
556 std::mt19937 gen = randomGenerator(seed);
557
558 std::vector<bool> visited(m.faceContainerSize(), false);
559 uint nVisited = 0;
560
561 while (nVisited < nSamples) {
562 uint fi = dist(gen);
563 if (fi < m.faceContainerSize() && !m.face(fi).deleted() &&
564 !visited[fi]) {
565 visited[fi] = true;
566 nVisited++;
567 ps.add(m.face(fi));
568 birthFaces.push_back(fi);
569 }
570 }
571
572 return ps;
573}
574
599template<
600 SamplerConcept SamplerType,
601 FaceMeshConcept MeshType,
602 typename ScalarType>
604 const MeshType& m,
605 const std::vector<ScalarType>& weights,
606 uint nSamples,
607 std::optional<uint> seed = std::nullopt)
608{
609 std::vector<uint> v;
611 m, weights, nSamples, v, seed);
612}
613
627template<SamplerConcept SamplerType, MeshConcept MeshType>
629 const MeshType& m,
630 uint nSamples,
631 std::optional<uint> seed = std::nullopt)
632{
633 requirePerVertexQuality(m);
634
635 using VertexType = MeshType::VertexType;
636 using QualityType = VertexType::QualityType;
637
638 std::vector<QualityType> weights;
639 weights.resize(m.vertexContainerSize(), 0);
640 for (const VertexType& v : m.vertices()) {
641 weights[m.index(v)] = v.quality();
642 }
643
645}
646
660template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
662 const MeshType& m,
663 uint nSamples,
664 std::optional<uint> seed = std::nullopt)
665{
667
668 using FaceType = MeshType::FaceType;
669 using QualityType = FaceType::QualityType;
670
671 std::vector<QualityType> weights;
672 weights.resize(m.faceContainerSize(), 0);
673 for (const FaceType& f : m.faces()) {
674 weights[m.index(f)] = f.quality();
675 }
676
678}
679
693template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
695 const MeshType& m,
696 uint nSamples,
697 std::optional<uint> seed = std::nullopt)
698{
699 using VertexType = MeshType::VertexType;
700 using ScalarType = VertexType::ScalarType;
701 using FaceType = MeshType::FaceType;
702
703 std::vector<ScalarType> weights(m.vertexContainerSize(), 0);
704 std::vector<uint> cnt(m.vertexContainerSize(), 0);
705
706 // for each vertex, store in weights the adjacent faces area and their
707 // number
708 for (const FaceType& f : m.faces()) {
709 ScalarType area = faceArea(f);
710 for (const VertexType* v : f.vertices()) {
711 weights[m.index(v)] += area;
712 cnt[m.index(v)]++;
713 }
714 }
715
716 // divide each area sum by the number of adjacent faces
717 for (uint i = 0; i < weights.size(); i++) {
718 if (cnt[i] > 0)
719 weights[i] /= cnt[i];
720 }
721
722 // use these weights to create a sapler
724}
725
738template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
740 const MeshType& m,
741 uint nSamples,
742 std::optional<uint> seed = std::nullopt)
743{
744 using FaceType = MeshType::FaceType;
745
746 std::vector<double> weights(m.faceContainerSize());
747
748 for (const FaceType& f : m.faces()) {
749 weights[m.index(f)] = faceArea(f);
750 }
751
754}
755
776template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
778 const MeshType& m,
779 uint nSamples,
780 std::vector<uint>& birthFaces,
781 std::optional<uint> seed = std::nullopt)
782{
783 using VertexType = MeshType::VertexType;
784 using ScalarType = VertexType::PositionType::ScalarType;
785 using FaceType = MeshType::FaceType;
786 using Interval = std::pair<ScalarType, const FaceType*>;
787
790
791 // Reserve space in the sampler and birthFaces vectors
792 sampler.reserve(nSamples);
793 birthFaces.reserve(nSamples);
794 birthFaces.clear();
795
796 std::uniform_real_distribution<ScalarType> dist(0, 1);
797
798 std::mt19937 gen = randomGenerator(seed);
799
800 std::vector<Interval> intervals(m.faceNumber());
801 uint i = 0;
802 ScalarType area = 0;
803 for (const FaceType& f : m.faces()) {
804 area += faceArea(f);
805 intervals[i] = std::make_pair(area, &f);
806 i++;
807 }
808
809 ScalarType meshArea = intervals.back().first;
810 for (uint i = 0; i < nSamples; i++) {
811 ScalarType val = meshArea * dist(gen);
812 // lower_bound returns the furthermost iterator i in [first, last) such
813 // that, for every iterator j in [first, i), *j < value. E.g. An
814 // iterator pointing to the first element "not less than" val, or end()
815 // if every element is less than val.
816 typename std::vector<Interval>::iterator it = std::lower_bound(
817 intervals.begin(),
818 intervals.end(),
819 std::make_pair(val, nullptr),
820 comparator);
821
822 sampler.add(
823 *it->second,
825 it->second->vertexNumber(), gen));
826 birthFaces.push_back(it->second->index());
827 }
828
829 return sampler;
830}
831
849template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
851 const MeshType& m,
852 uint nSamples,
853 std::optional<uint> seed = std::nullopt)
854{
855 std::vector<uint> birthFaces;
857}
858
859template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
860SamplerType stratifiedMontecarloPointSampling(
861 const MeshType& m,
862 uint nSamples,
863 std::optional<uint> seed = std::nullopt)
864{
865 using FaceType = MeshType::FaceType;
866 using ScalarType = SamplerType::ScalarType;
867
868 SamplerType ps;
869
870 std::mt19937 gen = randomGenerator(seed);
871
872 double area = surfaceArea(m);
873 double samplePerAreaUnit = nSamples / area;
874 // Montecarlo sampling.
875 double floatSampleNum = 0.0;
876
877 for (const FaceType& f : m.faces()) {
878 // compute # samples in the current face (taking into account of the
879 // remainders)
880 floatSampleNum += faceArea(f) * samplePerAreaUnit;
881 int faceSampleNum = (int) floatSampleNum;
882 // for every sample p_i in T...
883 for (int i = 0; i < faceSampleNum; i++)
884 ps.add(
885 f,
886 randomPolygonBarycentricCoordinate<ScalarType>(
887 f.vertexNumber(), gen));
888 floatSampleNum -= (double) faceSampleNum;
889 }
890
891 return ps;
892}
893
917template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
919 const MeshType& m,
920 uint nSamples,
921 std::optional<uint> seed = std::nullopt)
922{
923 using FaceType = MeshType::FaceType;
924 using ScalarType = SamplerType::ScalarType;
925
927
928 std::mt19937 gen = randomGenerator(seed);
929
930 ScalarType area = surfaceArea(m);
931 ScalarType samplePerAreaUnit = nSamples / area;
932
933 for (const FaceType& f : m.faces()) {
934 ScalarType areaT = faceArea(f);
936
937 // for every sample p_i in T...
938 for (int i = 0; i < faceSampleNum; i++)
939 ps.add(
940 f,
942 f.vertexNumber(), gen));
943 }
944
945 return ps;
946}
947
948template<
949 SamplerConcept SamplerType,
950 FaceMeshConcept MeshType,
951 typename ScalarType>
952SamplerType vertexWeightedMontecarloPointSampling(
953 const MeshType& m,
954 const std::vector<ScalarType>& weights,
955 uint nSamples,
956 double variance,
957 std::optional<uint> seed = std::nullopt)
958{
959 using FaceType = MeshType::FaceType;
960
961 // lambda function to compute radius weighted area of a face
962 auto weightedArea = [](const FaceType& f,
963 const MeshType& m,
964 const std::vector<ScalarType>& r) -> ScalarType {
965 ScalarType averageQ = 0;
966 for (uint i = 0; i < f.vertexNumber(); ++i)
967 averageQ += r[m.index(f.vertex(i))];
968
969 averageQ /= f.vertexNumber();
970 return averageQ * averageQ * faceArea(f);
971 };
972
973 SamplerType ps;
974
975 std::mt19937 gen = randomGenerator(seed);
976
977 std::vector<ScalarType> radius =
978 vertexRadiusFromWeights(m, weights, 1.0, variance, true);
979
980 ScalarType wArea = 0;
981 for (const FaceType& f : m.faces())
982 wArea += weightedArea(f, m, radius);
983
984 ScalarType samplePerAreaUnit = nSamples / wArea;
985 // Montecarlo sampling.
986 double floatSampleNum = 0.0;
987 for (const FaceType& f : m.faces()) {
988 // compute # samples in the current face (taking into account of the
989 // remainders)
990 floatSampleNum += weightedArea(f, m, radius) * samplePerAreaUnit;
991 uint faceSampleNum = (uint) floatSampleNum;
992
993 // for every sample p_i in T...
994 for (uint i = 0; i < faceSampleNum; i++)
995 ps.add(
996 f,
997 randomPolygonBarycentricCoordinate<ScalarType>(
998 f.vertexNumber(), gen));
999
1000 floatSampleNum -= (double) faceSampleNum;
1001 }
1002
1003 return ps;
1004}
1005
1006template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
1007SamplerType vertexQualityWeightedMontecarloPointSampling(
1008 const MeshType& m,
1009 uint nSamples,
1010 double variance,
1011 std::optional<uint> seed = std::nullopt)
1012{
1013 requirePerVertexQuality(m);
1014
1015 using VertexType = MeshType::VertexType;
1016 using QualityType = VertexType::QualityType;
1017
1018 std::vector<QualityType> weights;
1019 weights.resize(m.vertexContainerSize(), 0);
1020 for (const VertexType& v : m.vertices()) {
1021 weights[m.index(v)] = v.quality();
1022 }
1023
1024 return vertexWeightedMontecarloPointSampling<SamplerType>(
1025 m, weights, nSamples, variance, seed);
1026}
1027
1028} // namespace vcl
1029
1030#endif // VCL_ALGORITHMS_MESH_POINT_SAMPLING_H
A class representing a box in N-dimensional space.
Definition box.h:46
void add(const PointT &p)
Adds the given point to the current box, expanding this box in order to contain also the values of th...
Definition box.h:385
PointT size() const
Computes the size of the box.
Definition box.h:267
int poissonRandomNumber(double lambda, std::mt19937 &gen)
algorithm poisson random number (Knuth): init: Let L ← e^−λ, k ← 0 and p ← 1. do: k ← k + 1....
Definition random.h:121
std::mt19937 randomGenerator(std::optional< uint > seed=std::nullopt)
Creates a random number generator with an optional seed.
Definition random.h:45
auto faceArea(const FaceType &f)
Computes the area of a face. Works both for triangle and polygonal faces, and it is optimized in case...
Definition geometry.h:108
void requirePerFaceQuality(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a Quality Component,...
Definition face_requirements.h:1137
SamplerType montecarloPoissonPointSampling(const MeshType &m, uint nSamples, std::optional< uint > seed=std::nullopt)
This function compute montecarlo distribution with an approximate number of samples exploiting the po...
Definition point_sampling.h:918
SamplerType allFacesPointSampling(const MeshType &m, std::vector< uint > &birthFaces, bool onlySelected=false)
Returns a SamplerType object that contains all the faces contained in the given mesh.
Definition point_sampling.h:157
SamplerType faceAreaWeightedPointSampling(const MeshType &m, uint nSamples, std::optional< uint > seed=std::nullopt)
Samples the faces in a weighted way, using the per face area. Each face has a probability of being ch...
Definition point_sampling.h:739
SamplerType vertexWeightedPointSampling(const MeshType &m, const std::vector< ScalarType > &weights, uint nSamples, std::vector< uint > &birthVertices, std::optional< uint > seed=std::nullopt)
Samples the vertices in a weighted way, using the per vertex weights given as input....
Definition point_sampling.h:433
SamplerType vertexUniformPointSampling(const MeshType &m, uint nSamples, std::vector< uint > &birthVertices, bool onlySelected=false, std::optional< uint > seed=std::nullopt)
Returns a SamplerType object that contains the given number of samples taken from the vertices of the...
Definition point_sampling.h:234
SamplerType faceWeightedPointSampling(const MeshType &m, const std::vector< ScalarType > &weights, uint nSamples, std::vector< uint > &birthFaces, std::optional< uint > seed=std::nullopt)
Returns a SamplerType object that contains the given number of samples taken from the faces of the gi...
Definition point_sampling.h:536
SamplerType allVerticesPointSampling(const MeshType &m, std::vector< uint > &birthVertices, bool onlySelected=false)
Returns a Sampler object that contains all the vertices contained in the given mesh.
Definition point_sampling.h:74
SamplerType vertexAreaWeightedPointSampling(const MeshType &m, uint nSamples, std::optional< uint > seed=std::nullopt)
Samples the vertices in a weighted way, using the area. Each vertex has a probability of being chosen...
Definition point_sampling.h:694
SamplerType vertexQualityWeightedPointSampling(const MeshType &m, uint nSamples, std::optional< uint > seed=std::nullopt)
Samples the vertices in a weighted way, using the per vertex Quality component. Each vertex has a pro...
Definition point_sampling.h:628
SamplerType faceQualityWeightedPointSampling(const MeshType &m, uint nSamples, std::optional< uint > seed=std::nullopt)
Samples the faces in a weighted way, using the per face Quality component. Each face has a probabilit...
Definition point_sampling.h:661
SamplerType montecarloPointSampling(const MeshType &m, uint nSamples, std::vector< uint > &birthFaces, std::optional< uint > seed=std::nullopt)
Computes a montecarlo distribution with an exact number of samples. It works by generating a sequence...
Definition point_sampling.h:777
SamplerType faceUniformPointSampling(const MeshType &m, uint nSamples, std::vector< uint > &birthFaces, bool onlySelected=false, std::optional< uint > seed=std::nullopt)
Returns a SamplerType object that contains the given number of samples taken from the faces of the gi...
Definition point_sampling.h:332
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:84
constexpr detail::VerticesView vertices
A view that allows to iterate over the Vertex elements of an object.
Definition vertex.h:92