Geogram Version 1.9.6-rc
A programming library of geometric algorithms
Loading...
Searching...
No Matches
mesh_sampling.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40#ifndef GEOGRAM_MESH_MESH_SAMPLING
41#define GEOGRAM_MESH_MESH_SAMPLING
42
44#include <geogram/mesh/mesh.h>
48#include <algorithm>
49
56namespace GEO {
57
68 template <index_t DIM>
69 inline double mesh_facet_mass(
70 const Mesh& mesh,
71 index_t f,
72 Attribute<double>& vertex_weight
73 ) {
74 geo_debug_assert(mesh.facets.are_simplices());
75 geo_debug_assert(mesh.vertices.dimension() >= DIM);
76
77 index_t v1 = mesh.facets.vertex(f,0);
78 index_t v2 = mesh.facets.vertex(f,1);
79 index_t v3 = mesh.facets.vertex(f,2);
80
81 if(vertex_weight.is_bound()) {
83 mesh.vertices.point<DIM>(v1),
84 mesh.vertices.point<DIM>(v2),
85 mesh.vertices.point<DIM>(v3),
86 vertex_weight[v1],
87 vertex_weight[v2],
88 vertex_weight[v3]
89 );
90 }
92 mesh.vertices.point<DIM>(v1),
93 mesh.vertices.point<DIM>(v2),
94 mesh.vertices.point<DIM>(v3)
95 );
96 }
97
119 template <index_t DIM>
121 const Mesh& mesh,
122 double* p,
123 index_t nb_points,
124 Attribute<double>& weight,
125 index_t facets_begin_in = NO_INDEX,
126 index_t facets_end_in = NO_INDEX
127 ) {
128 geo_assert(mesh.facets.are_simplices());
129 geo_assert(mesh.vertices.dimension() >= DIM);
130 geo_assert(mesh.facets.nb() > 0);
131
132 index_t facets_begin = 0;
133 index_t facets_end = mesh.facets.nb();
134 if(facets_begin_in != NO_INDEX) {
135 facets_begin = facets_begin_in;
136 }
137 if(facets_end_in != NO_INDEX) {
138 facets_end = facets_end_in;
139 }
140
141 typedef vecng<DIM, double> Point;
142
143 // To ensure reproducibility accros successive
144 // runs, reset the random number generator.
146
147 vector<double> s(nb_points);
148 for(index_t i = 0; i < nb_points; i++) {
150 }
151 std::sort(s.begin(), s.end());
152
153 double Atot = 0.0;
154 for(index_t t = facets_begin; t < facets_end; ++t) {
155 double At = mesh_facet_mass<DIM>(mesh, t, weight);
156 Atot += At;
157 }
158
159 index_t first_t = NO_INDEX;
160 index_t last_t = 0;
161
162 index_t cur_t = facets_begin;
163 double cur_s =
164 mesh_facet_mass<DIM>(mesh, facets_begin, weight) / Atot;
165 for(index_t i = 0; i < nb_points; i++) {
166 geo_debug_assert(i < s.size());
167 while(s[i] > cur_s && cur_t < facets_end - 1) {
168 cur_t++;
169 geo_debug_assert(cur_t < facets_end);
170 cur_s += mesh_facet_mass<DIM>(mesh, cur_t, weight) / Atot;
171 }
172 if(first_t == NO_INDEX) {
173 first_t = cur_t;
174 }
175 last_t = std::max(last_t, cur_t);
176
177 // TODO: take weights into account
178 // with a new random_point_in_triangle_weighted()
179 // function.
180 index_t v1 = mesh.facets.vertex(cur_t,0);
181 index_t v2 = mesh.facets.vertex(cur_t,1);
182 index_t v3 = mesh.facets.vertex(cur_t,2);
183 Point cur_p = Geom::random_point_in_triangle(
184 mesh.vertices.point<DIM>(v1),
185 mesh.vertices.point<DIM>(v2),
186 mesh.vertices.point<DIM>(v3)
187 );
188 for(coord_index_t coord = 0; coord < DIM; coord++) {
189 p[i * DIM + coord] = cur_p[coord];
190 }
191 }
192 if(mesh.facets.nb() > 1 && last_t == first_t) {
193 Logger::warn("Sampler")
194 << "Did put all the points in the same triangle"
195 << std::endl;
196 return false;
197 }
198 return true;
199 }
200
201 /************************************************************************/
202
211 template <index_t DIM>
212 inline double mesh_tetra_mass(
213 const Mesh& mesh,
214 index_t t
215 ) {
216 geo_debug_assert(mesh.vertices.dimension() >= DIM);
217
218 double result = Geom::tetra_volume(
219 mesh.cells.point<DIM>(t,0),
220 mesh.cells.point<DIM>(t,1),
221 mesh.cells.point<DIM>(t,2),
222 mesh.cells.point<DIM>(t,3)
223 );
224
225 return result;
226 }
227
238 template <index_t DIM>
239 inline double mesh_tetra_mass(
240 const Mesh& mesh,
241 index_t t,
242 const Attribute<double>& weight
243 ) {
244 double result = mesh_tetra_mass<DIM>(mesh, t);
245
246 if(weight.is_bound()) {
247 index_t v0 = mesh.cells.vertex(t, 0);
248 index_t v1 = mesh.cells.vertex(t, 1);
249 index_t v2 = mesh.cells.vertex(t, 2);
250 index_t v3 = mesh.cells.vertex(t, 3);
251 result *= (
252 weight[v0] + weight[v1] + weight[v2] + weight[v3]
253 ) / 4.0;
254 }
255
256 return result;
257 }
258
279 template <index_t DIM>
281 const Mesh& mesh,
282 double* p,
283 index_t nb_points,
284 Attribute<double>& vertex_weight,
285 index_t tets_begin_in = NO_INDEX,
286 index_t tets_end_in = NO_INDEX
287 ) {
288 geo_assert(mesh.vertices.dimension() >= DIM);
289 geo_assert(mesh.cells.nb() > 0);
290
291 index_t tets_begin = 0;
292 index_t tets_end = mesh.cells.nb();
293 if(tets_begin_in != NO_INDEX) {
294 tets_begin = tets_begin_in;
295 }
296 if(tets_end_in != NO_INDEX) {
297 tets_end = tets_end_in;
298 }
299
300 typedef vecng<DIM, double> Point;
301
302 // To ensure reproducibility accros successive
303 // runs, reset the random number generator.
305
306 vector<double> s(nb_points);
307 for(index_t i = 0; i < nb_points; i++) {
309 }
310 std::sort(s.begin(), s.end());
311
312 double Vtot = 0.0;
313 for(index_t t = tets_begin; t < tets_end; ++t) {
314 double Vt = mesh_tetra_mass<DIM>(mesh, t, vertex_weight);
315 Vtot += Vt;
316 }
317
318 index_t first_t = NO_INDEX;
319 index_t last_t = 0;
320
321 index_t cur_t = tets_begin;
322 double cur_s =
323 mesh_tetra_mass<DIM>(mesh, tets_begin, vertex_weight) / Vtot;
324 for(index_t i = 0; i < nb_points; i++) {
325 geo_debug_assert(i < s.size());
326 while(s[i] > cur_s && cur_t < tets_end - 1) {
327 cur_t++;
328 geo_debug_assert(cur_t < tets_end);
329 cur_s += mesh_tetra_mass<DIM>(
330 mesh, cur_t, vertex_weight
331 ) / Vtot;
332 }
333 if(first_t == NO_INDEX) {
334 first_t = cur_t;
335 }
336 last_t = std::max(last_t, cur_t);
337
338 index_t v0 = mesh.cells.vertex(cur_t, 0);
339 index_t v1 = mesh.cells.vertex(cur_t, 1);
340 index_t v2 = mesh.cells.vertex(cur_t, 2);
341 index_t v3 = mesh.cells.vertex(cur_t, 3);
342
343 // TODO: take weights into account
344 // with a new random_point_in_tetra_weighted()
345 // function.
346 Point cur_p = Geom::random_point_in_tetra(
347 mesh.vertices.point<DIM>(v0),
348 mesh.vertices.point<DIM>(v1),
349 mesh.vertices.point<DIM>(v2),
350 mesh.vertices.point<DIM>(v3)
351 );
352 for(coord_index_t coord = 0; coord < DIM; coord++) {
353 p[i * DIM + coord] = cur_p[coord];
354 }
355 }
356 if(mesh.cells.nb() > 1 && last_t == first_t) {
357 Logger::warn("Sampler")
358 << "Did put all the points in the same tetrahedron"
359 << std::endl;
360 return false;
361 }
362 return true;
363 }
364}
365
366#endif
#define geo_assert(x)
Verifies that a condition is met.
Definition assert.h:149
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
bool is_bound() const
Tests whether an Attribute is bound.
Manages an attribute attached to a set of object.
const vecng< DIM, double > & point(index_t c, index_t lv) const
Gets a point by cell and local vertex index.
Definition mesh.h:2263
index_t vertex(index_t c, index_t lv) const
Gets a vertex of a cell by local vertex index.
Definition mesh.h:2241
bool are_simplices() const
Tests whether all the facets are triangles.
Definition mesh.h:873
index_t vertex(index_t f, index_t lv) const
Gets a vertex by facet and local vertex index.
Definition mesh.h:1143
index_t nb() const
Gets the number of (sub-)elements.
Definition mesh.h:98
vecng< DIM, double > & point(index_t v)
Gets a point.
Definition mesh.h:504
index_t dimension() const
Gets the dimension of the vertices.
Definition mesh.h:449
Represents a mesh.
Definition mesh.h:3050
Generic maths vector.
Definition vecg.h:70
Vector with aligned memory allocation.
Definition memory.h:660
index_t size() const
Gets the number of elements.
Definition memory.h:706
Common include file, providing basic definitions. Should be included before anything else by all head...
Geometric functions in arbitrary dimension.
Generic logging mechanism.
The class that represents a mesh.
Functions for accessing the geometry in a mesh.
vec3 random_point_in_triangle(const vec3 &p1, const vec3 &p2, const vec3 &p3)
Generates a random point in a 3d triangle.
Definition geometry.h:602
double tetra_volume(const vec3 &p1, const vec3 &p2, const vec3 &p3, const vec3 &p4)
Computes the volume of a 3d tetrahedron.
Definition geometry.h:520
double triangle_mass(const vec3 &p, const vec3 &q, const vec3 &r, double a, double b, double c)
Computes the mass of a 3d triangle with weighted points.
Definition geometry.h:583
double triangle_area(const vec3 &p1, const vec3 &p2, const vec3 &p3)
Computes the area of a 3d triangle.
Definition geometry.h:368
VEC random_point_in_tetra(const VEC &p1, const VEC &p2, const VEC &p3, const VEC &p4)
Generates a random point in a nd tetrahedron.
float64 random_float64()
Returns a 64 bits float between 0 and 1.
void random_reset()
Resets the random number generator.
Global Vorpaline namespace.
Definition basic.h:55
double mesh_tetra_mass(const Mesh &mesh, index_t t)
Computes the mass of a mesh tetrahedron.
bool mesh_generate_random_samples_on_surface(const Mesh &mesh, double *p, index_t nb_points, Attribute< double > &weight, index_t facets_begin_in=NO_INDEX, index_t facets_end_in=NO_INDEX)
Generates a set of random samples over a surfacic mesh.
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:329
double mesh_facet_mass(const Mesh &mesh, index_t f, Attribute< double > &vertex_weight)
Computes the mass of a mesh facet.
geo_coord_index_t coord_index_t
The type for storing coordinate indices, and iterating on the coordinates of a point.
Definition numeric.h:363
bool mesh_generate_random_samples_in_volume(const Mesh &mesh, double *p, index_t nb_points, Attribute< double > &vertex_weight, index_t tets_begin_in=NO_INDEX, index_t tets_end_in=NO_INDEX)
Generates a set of random samples in a volumetric mesh.