Visual Computing Library
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#include <vclib/math/random.h>
29#include <vclib/mesh/requirements.h>
30#include <vclib/misc/comparators.h>
31#include <vclib/space/complex/sampler.h>
32
50namespace vcl {
51
74template<SamplerConcept SamplerType, MeshConcept MeshType>
76 const MeshType& m,
77 std::vector<uint>& birthVertices,
78 bool onlySelected = false)
79{
80 using VertexType = MeshType::VertexType;
81
83
84 // Determine the number of vertices to sample
85 uint n = onlySelected ? vertexSelectionNumber(m) : m.vertexNumber();
86
87 // Reserve space in the sampler and birthVertices vectors
88 sampler.reserve(n);
89 birthVertices.reserve(n);
90 birthVertices.clear();
91
92 // Loop through all the vertices in the mesh and add them to the sampler if
93 // they are selected
94 for (const VertexType& v : m.vertices()) {
95 if (!onlySelected || v.selected()) {
96 sampler.add(v);
97 birthVertices.push_back(m.index(v));
98 }
99 }
100 return sampler;
101}
102
122template<SamplerConcept SamplerType, MeshConcept MeshType>
124 const MeshType& m,
125 bool onlySelected = false)
126{
127 std::vector<uint> v;
129}
130
157template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
159 const MeshType& m,
160 std::vector<uint>& birthFaces,
161 bool onlySelected = false)
162{
163 using FaceType = MeshType::FaceType;
164
166
167 // Determine the number of vertices to sample
168 uint n = onlySelected ? faceSelectionNumber(m) : m.faceNumber();
169
170 // Reserve space in the sampler and birthVertices vectors
171 sampler.reserve(n);
172 birthFaces.reserve(n);
173 birthFaces.clear();
174
175 for (const FaceType& f : m.faces()) {
176 if (!onlySelected || f.selected()) {
177 sampler.add(f);
178 birthFaces.push_back(m.index(f));
179 }
180 }
181 return sampler;
182}
183
207template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
208SamplerType allFacesPointSampling(const MeshType& m, bool onlySelected = false)
209{
210 std::vector<uint> v;
212}
213
233template<SamplerConcept SamplerType, MeshConcept MeshType>
235 const MeshType& m,
236 uint nSamples,
237 std::vector<uint>& birthVertices,
238 bool onlySelected = false,
239 bool deterministic = false)
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::random_device rd;
258 std::mt19937 gen(rd());
259 if (deterministic)
260 gen = std::mt19937(0);
261
262 std::vector<bool> visited(m.vertexContainerSize(), false);
263 uint nVisited = 0;
264
265 while (nVisited < nSamples) {
266 uint vi = dist(gen);
267 if (!m.vertex(vi).deleted() && !visited[vi] &&
268 (!onlySelected || m.vertex(vi).selected())) {
269 visited[vi] = true;
270 nVisited++;
271 ps.add(m.vertex(vi));
272 birthVertices.push_back(vi);
273 }
274 }
275
276 return ps;
277}
278
296template<SamplerConcept SamplerType, MeshConcept MeshType>
298 const MeshType& m,
299 uint nSamples,
300 bool onlySelected = false,
301 bool deterministic = false)
302{
303 std::vector<uint> v;
306}
307
332template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
334 const MeshType& m,
335 uint nSamples,
336 std::vector<uint>& birthFaces,
337 bool onlySelected = false,
338 bool deterministic = false)
339{
340 uint fn = onlySelected ? faceSelectionNumber(m) : m.faceNumber();
341
342 if (nSamples >= fn) {
344 }
345
347
348 // Reserve space in the sampler and birthFaces vectors
349 ps.reserve(fn);
350 birthFaces.reserve(fn);
351 birthFaces.clear();
352
353 std::uniform_int_distribution<uint> dist(0, m.faceContainerSize() - 1);
354
355 std::random_device rd;
356 std::mt19937 gen(rd());
357 if (deterministic)
358 gen = std::mt19937(0);
359
360 std::vector<bool> visited(m.faceContainerSize(), false);
361 uint nVisited = 0;
362
363 while (nVisited < nSamples) {
364 uint fi = dist(gen);
365 if (!m.face(fi).deleted() && !visited[fi] &&
366 (!onlySelected || m.face(fi).selected())) {
367 visited[fi] = true;
368 nVisited++;
369 ps.add(m.face(fi));
370 birthFaces.push_back(fi);
371 }
372 }
373
374 return ps;
375}
376
398template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
400 const MeshType& m,
401 uint nSamples,
402 bool onlySelected = false,
403 bool deterministic = false)
404{
405 std::vector<uint> v;
408}
409
435template<SamplerConcept SamplerType, MeshConcept MeshType, typename ScalarType>
437 const MeshType& m,
438 const std::vector<ScalarType>& weights,
439 uint nSamples,
440 std::vector<uint>& birthVertices,
441 bool deterministic = false)
442{
443 if (nSamples >= m.vertexNumber()) {
445 }
446
448 ps.reserve(nSamples);
449 birthVertices.reserve(nSamples);
450 birthVertices.clear();
451
452 std::discrete_distribution<> dist(std::begin(weights), std::end(weights));
453
454 std::random_device rd;
455 std::mt19937 gen(rd());
456 if (deterministic)
457 gen = std::mt19937(0);
458
459 std::vector<bool> visited(m.vertexContainerSize(), false);
460 uint nVisited = 0;
461
462 while (nVisited < nSamples) {
463 uint vi = dist(gen);
464 if (vi < m.vertexContainerSize() && !m.vertex(vi).deleted() &&
465 !visited[vi]) {
466 visited[vi] = true;
467 nVisited++;
468 ps.add(m.vertex(vi));
469 birthVertices.push_back(vi);
470 }
471 }
472
473 return ps;
474}
475
498template<SamplerConcept SamplerType, MeshConcept MeshType, typename ScalarType>
500 const MeshType& m,
501 const std::vector<ScalarType>& weights,
502 uint nSamples,
503 bool deterministic = false)
504{
505 std::vector<uint> v;
508}
509
537template<
538 SamplerConcept SamplerType,
539 FaceMeshConcept MeshType,
540 typename ScalarType>
542 const MeshType& m,
543 const std::vector<ScalarType>& weights,
544 uint nSamples,
545 std::vector<uint>& birthFaces,
546 bool deterministic = false)
547{
548 if (nSamples >= m.faceNumber()) {
550 }
551
553
554 // Reserve space in the sampler and birthFaces vectors
555 ps.reserve(nSamples);
556 birthFaces.reserve(nSamples);
557 birthFaces.clear();
558
559 std::discrete_distribution<> dist(std::begin(weights), std::end(weights));
560
561 std::random_device rd;
562 std::mt19937 gen(rd());
563 if (deterministic)
564 gen = std::mt19937(0);
565
566 std::vector<bool> visited(m.faceContainerSize(), false);
567 uint nVisited = 0;
568
569 while (nVisited < nSamples) {
570 uint fi = dist(gen);
571 if (fi < m.faceContainerSize() && !m.face(fi).deleted() &&
572 !visited[fi]) {
573 visited[fi] = true;
574 nVisited++;
575 ps.add(m.face(fi));
576 birthFaces.push_back(fi);
577 }
578 }
579
580 return ps;
581}
582
606template<
607 SamplerConcept SamplerType,
608 FaceMeshConcept MeshType,
609 typename ScalarType>
611 const MeshType& m,
612 const std::vector<ScalarType>& weights,
613 uint nSamples,
614 bool deterministic = false)
615{
616 std::vector<uint> v;
619}
620
633template<SamplerConcept SamplerType, MeshConcept MeshType>
635 const MeshType& m,
636 uint nSamples,
637 bool deterministic = false)
638{
639 requirePerVertexQuality(m);
640
641 using VertexType = MeshType::VertexType;
642 using QualityType = VertexType::QualityType;
643
644 std::vector<QualityType> weights;
645 weights.resize(m.vertexContainerSize(), 0);
646 for (const VertexType& v : m.vertices()) {
647 weights[m.index(v)] = v.quality();
648 }
649
652}
653
666template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
668 const MeshType& m,
669 uint nSamples,
670 bool deterministic = false)
671{
673
674 using FaceType = MeshType::FaceType;
675 using QualityType = FaceType::QualityType;
676
677 std::vector<QualityType> weights;
678 weights.resize(m.faceContainerSize(), 0);
679 for (const FaceType& f : m.faces()) {
680 weights[m.index(f)] = f.quality();
681 }
682
685}
686
699template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
701 const MeshType& m,
702 uint nSamples,
703 bool deterministic = false)
704{
705 using VertexType = MeshType::VertexType;
706 using ScalarType = VertexType::ScalarType;
707 using FaceType = MeshType::FaceType;
708
709 std::vector<ScalarType> weights(m.vertexContainerSize(), 0);
710 std::vector<uint> cnt(m.vertexContainerSize(), 0);
711
712 // for each vertex, store in weights the adjacent faces area and their
713 // number
714 for (const FaceType& f : m.faces()) {
715 ScalarType area = faceArea(f);
716 for (const VertexType* v : f.vertices()) {
717 weights[m.index(v)] += area;
718 cnt[m.index(v)]++;
719 }
720 }
721
722 // divide each area sum by the number of adjacent faces
723 for (uint i = 0; i < weights.size(); i++) {
724 if (cnt[i] > 0)
725 weights[i] /= cnt[i];
726 }
727
728 // use these weights to create a sapler
731}
732
744template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
746 const MeshType& m,
747 uint nSamples,
748 bool deterministic = false)
749{
750 using FaceType = MeshType::FaceType;
751
752 std::vector<double> weights(m.faceContainerSize());
753
754 for (const FaceType& f : m.faces()) {
755 weights[m.index(f)] = faceArea(f);
756 }
757
760}
761
781template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
783 const MeshType& m,
784 uint nSamples,
785 std::vector<uint>& birthFaces,
786 bool deterministic = false)
787{
788 using VertexType = MeshType::VertexType;
789 using ScalarType = VertexType::CoordType::ScalarType;
790 using FaceType = MeshType::FaceType;
791 using Interval = std::pair<ScalarType, const FaceType*>;
792
795
796 // Reserve space in the sampler and birthFaces vectors
797 sampler.reserve(nSamples);
798 birthFaces.reserve(nSamples);
799 birthFaces.clear();
800
801 std::uniform_real_distribution<ScalarType> dist(0, 1);
802
803 std::random_device rd;
804 std::mt19937 gen(rd());
805 if (deterministic)
806 gen = std::mt19937(0);
807
808 std::vector<Interval> intervals(m.faceNumber());
809 uint i = 0;
810 ScalarType area = 0;
811 for (const FaceType& f : m.faces()) {
812 area += faceArea(f);
813 intervals[i] = std::make_pair(area, &f);
814 i++;
815 }
816
817 ScalarType meshArea = intervals.back().first;
818 for (uint i = 0; i < nSamples; i++) {
819 ScalarType val = meshArea * dist(gen);
820 // lower_bound returns the furthermost iterator i in [first, last) such
821 // that, for every iterator j in [first, i), *j < value. E.g. An
822 // iterator pointing to the first element "not less than" val, or end()
823 // if every element is less than val.
824 typename std::vector<Interval>::iterator it = std::lower_bound(
825 intervals.begin(),
826 intervals.end(),
827 std::make_pair(val, nullptr),
828 comparator);
829
830 sampler.add(
831 *it->second,
833 it->second->vertexNumber(), gen));
834 birthFaces.push_back(it->second->index());
835 }
836
837 return sampler;
838}
839
856template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
858 const MeshType& m,
859 uint nSamples,
860 bool deterministic = false)
861{
862 std::vector<uint> birthFaces;
865}
866
867template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
868SamplerType stratifiedMontecarloPointSampling(
869 const MeshType& m,
870 uint nSamples,
871 bool deterministic = false)
872{
873 using FaceType = MeshType::FaceType;
874 using ScalarType = SamplerType::ScalarType;
875
876 SamplerType ps;
877
878 std::random_device rd;
879 std::mt19937 gen(rd());
880 if (deterministic)
881 gen = std::mt19937(0);
882
883 double area = surfaceArea(m);
884 double samplePerAreaUnit = nSamples / area;
885 // Montecarlo sampling.
886 double floatSampleNum = 0.0;
887
888 for (const FaceType& f : m.faces()) {
889 // compute # samples in the current face (taking into account of the
890 // remainders)
891 floatSampleNum += faceArea(f) * samplePerAreaUnit;
892 int faceSampleNum = (int) floatSampleNum;
893 // for every sample p_i in T...
894 for (int i = 0; i < faceSampleNum; i++)
895 ps.add(
896 f,
897 randomPolygonBarycentricCoordinate<ScalarType>(
898 f.vertexNumber(), gen));
899 floatSampleNum -= (double) faceSampleNum;
900 }
901
902 return ps;
903}
904
927template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
929 const MeshType& m,
930 uint nSamples,
931 bool deterministic = false)
932{
933 using FaceType = MeshType::FaceType;
934 using ScalarType = SamplerType::ScalarType;
935
937
938 std::random_device rd;
939 std::mt19937 gen(rd());
940 if (deterministic)
941 gen = std::mt19937(0);
942
943 ScalarType area = surfaceArea(m);
944 ScalarType samplePerAreaUnit = nSamples / area;
945
946 for (const FaceType& f : m.faces()) {
947 ScalarType areaT = faceArea(f);
949
950 // for every sample p_i in T...
951 for (int i = 0; i < faceSampleNum; i++)
952 ps.add(
953 f,
955 f.vertexNumber(), gen));
956 }
957
958 return ps;
959}
960
961template<
962 SamplerConcept SamplerType,
963 FaceMeshConcept MeshType,
964 typename ScalarType>
965SamplerType vertexWeightedMontecarloPointSampling(
966 const MeshType& m,
967 const std::vector<ScalarType>& weights,
968 uint nSamples,
969 double variance,
970 bool deterministic = false)
971{
972 using FaceType = MeshType::FaceType;
973
974 // lambda function to compute radius weighted area of a face
975 auto weightedArea = [](const FaceType& f,
976 const MeshType& m,
977 const std::vector<ScalarType>& r) -> ScalarType {
978 ScalarType averageQ = 0;
979 for (uint i = 0; i < f.vertexNumber(); ++i)
980 averageQ += r[m.index(f.vertex(i))];
981
982 averageQ /= f.vertexNumber();
983 return averageQ * averageQ * faceArea(f);
984 };
985
986 SamplerType ps;
987
988 std::random_device rd;
989 std::mt19937 gen(rd());
990 if (deterministic)
991 gen = std::mt19937(0);
992
993 std::vector<ScalarType> radius =
994 vertexRadiusFromWeights(m, weights, 1.0, variance, true);
995
996 ScalarType wArea = 0;
997 for (const FaceType& f : m.faces())
998 wArea += weightedArea(f, m, radius);
999
1000 ScalarType samplePerAreaUnit = nSamples / wArea;
1001 // Montecarlo sampling.
1002 double floatSampleNum = 0.0;
1003 for (const FaceType& f : m.faces()) {
1004 // compute # samples in the current face (taking into account of the
1005 // remainders)
1006 floatSampleNum += weightedArea(f, m, radius) * samplePerAreaUnit;
1007 uint faceSampleNum = (uint) floatSampleNum;
1008
1009 // for every sample p_i in T...
1010 for (uint i = 0; i < faceSampleNum; i++)
1011 ps.add(
1012 f,
1013 randomPolygonBarycentricCoordinate<ScalarType>(
1014 f.vertexNumber(), gen));
1015
1016 floatSampleNum -= (double) faceSampleNum;
1017 }
1018
1019 return ps;
1020}
1021
1022template<SamplerConcept SamplerType, FaceMeshConcept MeshType>
1023SamplerType vertexQualityWeightedMontecarloPointSampling(
1024 const MeshType& m,
1025 uint nSamples,
1026 double variance,
1027 bool deterministic = false)
1028{
1029 requirePerVertexQuality(m);
1030
1031 using VertexType = MeshType::VertexType;
1032 using QualityType = VertexType::QualityType;
1033
1034 std::vector<QualityType> weights;
1035 weights.resize(m.vertexContainerSize(), 0);
1036 for (const VertexType& v : m.vertices()) {
1037 weights[m.index(v)] = v.quality();
1038 }
1039
1040 return vertexWeightedMontecarloPointSampling<SamplerType>(
1041 m, weights, nSamples, variance, deterministic);
1042}
1043
1044} // namespace vcl
1045
1046#endif // VCL_ALGORITHMS_MESH_POINT_SAMPLING_H
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
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:101
void requirePerFaceQuality(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a Quality Component,...
Definition face_requirements.h:875
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:118
SamplerType vertexQualityWeightedPointSampling(const MeshType &m, uint nSamples, bool deterministic=false)
Samples the vertices in a weighted way, using the per vertex Quality component. Each vertex has a pro...
Definition point_sampling.h:634
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:158
SamplerType montecarloPointSampling(const MeshType &m, uint nSamples, std::vector< uint > &birthFaces, bool deterministic=false)
Computes a montecarlo distribution with an exact number of samples. It works by generating a sequence...
Definition point_sampling.h:782
SamplerType faceWeightedPointSampling(const MeshType &m, const std::vector< ScalarType > &weights, uint nSamples, std::vector< uint > &birthFaces, bool deterministic=false)
Returns a SamplerType object that contains the given number of samples taken from the faces of the gi...
Definition point_sampling.h:541
SamplerType vertexWeightedPointSampling(const MeshType &m, const std::vector< ScalarType > &weights, uint nSamples, std::vector< uint > &birthVertices, bool deterministic=false)
Samples the vertices in a weighted way, using the per vertex weights given as input....
Definition point_sampling.h:436
SamplerType vertexAreaWeightedPointSampling(const MeshType &m, uint nSamples, bool deterministic=false)
Samples the vertices in a weighted way, using the area. Each vertex has a probability of being chosen...
Definition point_sampling.h:700
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:75
SamplerType vertexUniformPointSampling(const MeshType &m, uint nSamples, std::vector< uint > &birthVertices, bool onlySelected=false, bool deterministic=false)
Returns a SamplerType object that contains the given number of samples taken from the vertices of the...
Definition point_sampling.h:234
SamplerType faceAreaWeightedPointSampling(const MeshType &m, uint nSamples, bool deterministic=false)
Samples the faces in a weighted way, using the per face area. Each face has a probability of being ch...
Definition point_sampling.h:745
SamplerType montecarloPoissonPointSampling(const MeshType &m, uint nSamples, bool deterministic=false)
This function compute montecarlo distribution with an approximate number of samples exploiting the po...
Definition point_sampling.h:928
SamplerType faceUniformPointSampling(const MeshType &m, uint nSamples, std::vector< uint > &birthFaces, bool onlySelected=false, bool deterministic=false)
Returns a SamplerType object that contains the given number of samples taken from the faces of the gi...
Definition point_sampling.h:333
SamplerType faceQualityWeightedPointSampling(const MeshType &m, uint nSamples, bool deterministic=false)
Samples the faces in a weighted way, using the per face Quality component. Each face has a probabilit...
Definition point_sampling.h:667
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:52
constexpr detail::VerticesView vertices
A view that allows to iterate over the Vertex elements of an object.
Definition vertex.h:60