GCC Code Coverage Report


Directory: ./
File: lib/geogram/voronoi/RVD_callback.h
Date: 2026-09-07 02:36:43
Exec Total Coverage
Lines: 11 36 30.6%
Functions: 4 11 36.4%
Branches: 1 6 16.7%

Line Branch Exec Source
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_VORONOI_RVD_CALLBACK
41 #define GEOGRAM_VORONOI_RVD_CALLBACK
42
43 #include <geogram/basic/common.h>
44 #include <geogram/voronoi/generic_RVD_vertex.h>
45 #include <geogram/mesh/mesh.h>
46 #include <geogram/basic/numeric.h>
47 #include <geogram/basic/attributes.h>
48 #include <geogram/basic/thread_sync.h>
49
50 namespace GEOGen {
51 class SymbolicVertex;
52 class Polygon;
53 class ConvexCell;
54 }
55
56 namespace GEO {
57 class RVDVertexMap;
58 class Mesh;
59 }
60
61 /**
62 * \file geogram/voronoi/RVD_callback.h
63 * \brief Declaration of base types for implementing user-defined
64 * code that queries the cells of a restricted Voronoi diagram.
65 */
66
67 namespace GEO {
68
69 /***************************************************************/
70
71 /**
72 * \brief Baseclass for user functions called for each
73 * element (polygon or polyhedron) of a restricted Voronoi
74 * diagram traversal.
75 */
76 class GEOGRAM_API RVDCallback {
77 public:
78
79 /**
80 * \brief RVDCallback constructor.
81 */
82 RVDCallback();
83
84 /**
85 * \brief RVDCallback destructor.
86 */
87 virtual ~RVDCallback();
88
89 /**
90 * \brief Called at the beginning of the RVD traversal.
91 */
92 virtual void begin();
93
94 /**
95 * \brief Called at the end of the RVD traversal.
96 */
97 virtual void end();
98
99 /**
100 * \brief Gets the index of the seed that corresponds to the current
101 * polygon/polyhedron.
102 * \return The index of the seed that corresponds to the
103 * current polygon/polyhedron.
104 * \details The current polygon/polyhedron is the intersection
105 * between a Voronoi cell (associted with a seed) and a simplex.
106 */
107 302488 index_t seed() const {
108 302488 return seed_;
109 }
110
111 /**
112 * \brief Gets the index of the simplex that corresponds to the
113 * current polygon/polyhedron.
114 * \return The index of the simplex that corresponds to the
115 * current polygon/polyhedron. Points to a simplex in the mesh that the
116 * Voronoi diagram is restricted to.
117 * \details The current polygon/polyhedron is the intersection between
118 * a Voronoi cell and a simplex.
119 */
120 index_t simplex() const {
121 return simplex_;
122 }
123
124 /**
125 * \brief Sets the spinlocks array.
126 * \details In multithreading mode, a spinlocks array can
127 * be used to manage concurrent accesses.
128 * \param[in] spinlocks a pointer to the Process::SpinLockArray
129 * or nullptr if no spinlocks are used.
130 */
131 void set_spinlocks(Process::SpinLockArray* spinlocks) {
132 spinlocks_ = spinlocks;
133 }
134
135 protected:
136 index_t seed_;
137 index_t simplex_;
138 Process::SpinLockArray* spinlocks_;
139 };
140
141 /***************************************************************/
142
143 /**
144 * \brief Baseclass for user functions called for each
145 * polygon of a surfacic restricted Voronoi diagram.
146 * \details A surfacic restricted Voronoi diagram is the
147 * intersection between Voronoi cells and the triangles of
148 * a given triangulated mesh. The member functions of this
149 * class are called for each intersection between a Voronoi
150 * cell and a triangle.
151 */
152
153 class GEOGRAM_API RVDPolygonCallback : public RVDCallback {
154 public:
155
156 /**
157 * \brief PolyhedronCallback constructor.
158 */
159 RVDPolygonCallback();
160
161 /**
162 * \brief PolyhedronCallback destructor.
163 */
164 ~RVDPolygonCallback() override;
165
166 /**
167 * \copydoc RVDCallback::begin()
168 */
169 void begin() override;
170
171 /**
172 * \copydoc RVDCallback::end()
173 */
174 void end() override;
175
176 /**
177 * \brief The default callback called for each polygon
178 * \param[in] v index of current Delaunay seed
179 * \param[in] t index of current mesh triangle
180 * \param[in] C intersection between current mesh triangle
181 * and the Voronoi cell of \p v
182 */
183 virtual void operator() (
184 index_t v,
185 index_t t,
186 const GEOGen::Polygon& C
187 ) const;
188
189 };
190
191 /***************************************************************/
192
193 /**
194 * \brief Baseclass for user functions called for each
195 * polyhedron of a volumetric restricted Voronoi diagram.
196 * \details A volumetric restricted Voronoi diagram is the
197 * intersection between Voronoi cells and the tetrahedra of
198 * a given tetrahedral mesh. The member functions of this
199 * class are called for each intersection between a Voronoi
200 * cell and a tetrahedron.
201 */
202 class GEOGRAM_API RVDPolyhedronCallback : public RVDCallback {
203 public:
204
205 /**
206 * \brief PolyhedronCallback constructor.
207 */
208 RVDPolyhedronCallback();
209
210 /**
211 * \brief PolyhedronCallback destructor.
212 */
213 ~RVDPolyhedronCallback() override;
214
215 /**
216 * \copydoc RVDCallback::begin()
217 */
218 void begin() override;
219
220 /**
221 * \copydoc RVDCallback::end()
222 */
223 void end() override;
224
225
226 /**
227 * \brief The default callback called for each polyhedron
228 * \details This default implementation routes the callback to the
229 * begin_polyhedron_internal(), end_polyhedron_internal(),
230 * begin_facet_internal(), end_facet_internal() and vertex_internal()
231 * functions (that in turn route the callbacks to their without
232 * "_internal" counterparts).
233 * \param[in] v index of current Delaunay seed
234 * \param[in] t index of current mesh tetrahedron
235 * \param[in] C intersection between current mesh tetrahedron
236 * and the Voronoi cell of \p v
237 */
238 virtual void operator() (
239 index_t v,
240 index_t t,
241 const GEOGen::ConvexCell& C
242 ) const;
243
244
245 /**
246 * \brief Called at the beginning of each intersection polyhedron.
247 * \details Each intersection polyhedron is defined as the intersection
248 * between a Voronoi cell and a tetrahedron.
249 * \param[in] seed index of the seed associated with the Voronoi cell
250 * \param[in] tetrahedron index of the tetrahedron
251 */
252 virtual void begin_polyhedron(index_t seed, index_t tetrahedron);
253
254 /**
255 * \brief Called at the beginning of each facet of each intersection
256 * polyhedron.
257 * \details A facet can be a subset of either a bisector (defined by
258 * two seeds), or it can be a subset of a facet of a tetrahedron.
259 * \param[in] facet_seed if the facet corresponds to a bisector,
260 * the index of the seed that defines the bisector, or index_t(-1)
261 * otherwise
262 * \param[in] facet_tet if the facet corresponds to a facet
263 * of the current tetrahedron, the index of the tetrahedron
264 * adjacent to that facet, or index_t(-1) otherwise
265 */
266 virtual void begin_facet(index_t facet_seed, index_t facet_tet);
267
268 /**
269 * \brief Called for each vertex of the current facet.
270 * \param[in] geometry a pointer to the coordinates of the vertex
271 * \param[in] symb the symbolic representation of the vertex
272 */
273 virtual void vertex(
274 const double* geometry, const GEOGen::SymbolicVertex& symb
275 );
276
277 /**
278 * \brief Called at the end of each polyhedron facet.
279 */
280 virtual void end_facet();
281
282 /**
283 * \brief Called at the end of each polyhedron.
284 */
285 virtual void end_polyhedron();
286
287 /**
288 * \brief Gets the index of the tetrahedron that corresponds to the
289 * current polyhedron.
290 * \return The index of the tetrahedron that corresponds to the
291 * current polyhedron.
292 * \details The current polyhedron is the intersection between a Voronoi
293 * cell and a tetrahedron.
294 */
295 index_t tet() const {
296 return simplex();
297 }
298
299 /**
300 * \brief Gets the index of the seed that defines the bisector on which
301 * the current facet lies, or index_t(-1).
302 * \return The index of the seed that defines the bisector on which
303 * the current facet lies, or index_t(-1).
304 * \details Each facet is either on a bisector or on a tetrahedron
305 * facet. If the current facet is on a bisector, it is defined by
306 * seed() and facet_seed(), otherwise facet_seed() returns index_t(-1).
307 */
308 index_t facet_seed() const {
309 return facet_seed_;
310 }
311
312 /**
313 * \brief Gets the index of the tetrahedron adjacent to the current
314 * facet or index_t(-1) if there is no such facet.
315 * \return the index of the tetrahedron adjacent to the current
316 * facet or index_t(-1).
317 * \details Each facet is either on a bisector or on a tetrahedron
318 * facet. If the current facet is on a tetrahedron facet, then it
319 * is defined by tet() and facet_tet(), otherwise
320 * facet_tet() returns index_t(-1).
321 */
322 index_t facet_tet() const {
323 return facet_tet_;
324 }
325
326 /**
327 * \brief Specifies whether internal tetrahedron facets should be
328 * removed.
329 * \details If set, a single polyhedron is generated for each
330 * (connected component) of the restricted Voronoi cells. If not
331 * set (default), each tetrahedron-Voronoi cell intersection
332 * generates a new polyhedron.
333 * \param[in] x true if internal facets should be removed, false
334 * otherwise
335 */
336 4 void set_simplify_internal_tet_facets(bool x) {
337 4 simplify_internal_tet_facets_ = x;
338 4 }
339
340 /**
341 * \brief Specifies whether Voronoi facets should be simplified.
342 * \details By default, the computed Voronoi facets are composed
343 * of multiple polyhedra that correspond to the intersection with
344 * the tetrahedra of the input volume mesh. They can be simplified
345 * and replaced by a single polygon. This implies simplifying the
346 * internal tetrahedron facets and using a mesh.
347 * \param[in] x true if Voronoi facets should be simplified,
348 * false otherwise.
349 */
350 void set_simplify_voronoi_facets(bool x) {
351 simplify_voronoi_facets_ = x;
352 if(x) {
353 set_simplify_internal_tet_facets(true);
354 set_use_mesh(true);
355 }
356 }
357
358 /**
359 * \brief Specifies whether boundary facets should be simplified.
360 * \details By default, the intersection between a Voronoi cell and
361 * the boundary is possibly composed of multiple polygons, that
362 * correspond to the initial polygons of the boundary. They can be
363 * simplified as a single polygon per Voronoi cell. This implies
364 * simplifying the internal tetrahedron facets, simplifying the
365 * Voronoi facets and using a mesh.
366 * \param[in] x true if boundary facets should be simplified,
367 * false otherwise.
368 * \param[in] angle_threshold an edge shared by two adjacent facets
369 * is suppressed if the angle between the facet normals is smaller
370 * than \p angle_threshold
371 */
372 void set_simplify_boundary_facets(bool x, double angle_threshold=45.0) {
373 simplify_boundary_facets_ = x;
374 if(x) {
375 set_simplify_voronoi_facets(true);
376 simplify_boundary_facets_angle_threshold_ = angle_threshold;
377 } else {
378 simplify_boundary_facets_angle_threshold_ = 0.0;
379 }
380 }
381
382 /**
383 * \brief Specifies whether non-convex facets should be tessellated.
384 * \param[in] x true if non-convex facets should be tessellated,
385 * false otherwise.
386 * \details Only taken into account if set_use_mesh(true) was called.
387 */
388 4 void set_tessellate_non_convex_facets(bool x) {
389 4 tessellate_non_convex_facets_ = x;
390 4 }
391
392
393 /**
394 * \brief Specifies whether a mesh should be built for each
395 * traversed polyhedron.
396 * \details The build mesh can then be modified (e.g., simplified)
397 * by overloading process_mesh().
398 * \param[in] x true if a mesh should be build, false otherwise
399 */
400 void set_use_mesh(bool x);
401
402 /**
403 * \brief Sets the dimension of the internal mesh if need be.
404 * \details This function is called automatically by
405 * RestrictedVoronoiDiagram::for_each_polyhedron().
406 * \param[in] dim the dimension of the mesh (3 for 3d).
407 */
408 4 void set_dimension(index_t dim) {
409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(use_mesh_) {
410 mesh_.vertices.set_dimension(dim);
411 }
412 4 }
413
414 protected:
415 /**
416 * \brief Filters callbacks between operator() and client callbacks.
417 * \details This is used to implement cells simplifications (remove
418 * internal boundaries and intersections with tetrahedra).
419 * \see begin_polyhedron()
420 */
421 virtual void begin_polyhedron_internal(
422 index_t seed, index_t tetrahedron
423 );
424
425 /**
426 * \brief Filters callbacks between operator() and client callbacks.
427 * \details This is used to implement cells simplifications (remove
428 * internal boundaries and intersections with tetrahedra).
429 * \see begin_facet()
430 */
431 virtual void begin_facet_internal(
432 index_t facet_seed, index_t facet_tet
433 );
434
435 /**
436 * \brief Filters callbacks between operator() and client callbacks.
437 * \details This is used to implement cells simplifications (remove
438 * internal boundaries and intersections with tetrahedra).
439 * \see vertex()
440 */
441 virtual void vertex_internal(
442 const double* geometry, const GEOGen::SymbolicVertex& symb
443 );
444
445 /**
446 * \brief Filters callbacks between operator() and client callbacks.
447 * \details This is used to implement cells simplifications (remove
448 * internal boundaries and intersections with tetrahedra).
449 * \see end_facet()
450 */
451 virtual void end_facet_internal();
452
453 /**
454 * \brief Filters callbacks between operator() and client callbacks.
455 * \details This is used to implement cells simplifications (remove
456 * internal boundaries and intersections with tetrahedra).
457 * \see end_polyhedron()
458 */
459 virtual void end_polyhedron_internal();
460
461 /**
462 * \brief If use_mesh is set, then this function is called for
463 * each generated mesh.
464 * \details Default implementation simplifies the mesh based on
465 * sipmlify_xxx flags, then it calls user callbacks
466 * begin_facet(), end_facet(), vertex() for each facet of the mesh,
467 * as well as begin_polyhedron() and end_polyhedron() once per mesh.
468 * Derived classes may modify (e.g., simplify) the mesh before calling
469 * user callbacks.
470 */
471 virtual void process_polyhedron_mesh();
472
473 protected:
474
475 index_t facet_seed_;
476 index_t facet_tet_;
477 index_t last_seed_;
478
479 bool simplify_internal_tet_facets_;
480 bool simplify_voronoi_facets_;
481 bool simplify_boundary_facets_;
482 double simplify_boundary_facets_angle_threshold_;
483 bool tessellate_non_convex_facets_;
484
485 bool use_mesh_;
486 bool facet_is_skipped_;
487
488 Mesh mesh_;
489 Attribute<GEOGen::SymbolicVertex> mesh_vertex_sym_;
490 Attribute<index_t> mesh_facet_seed_;
491 Attribute<index_t> mesh_facet_tet_;
492 RVDVertexMap* vertex_map_;
493 vector<index_t> base_current_facet_;
494 };
495
496 /***************************************************************/
497
498 /**
499 * \brief Constructs a polyhedral mesh from a restricted Voronoi diagram.
500 * \details Its member functions are called for each RVD polyhedron,
501 * i.e. the intersections between the volumetric mesh tetrahedra and
502 * the Voronoi cells. Based on set_simplify_xxx(), a smaller number of
503 * polyhedra can be generated.
504 */
505 class GEOGRAM_API BuildRVDMesh : public RVDPolyhedronCallback {
506 public:
507
508 /**
509 * \brief BuildRVDMesh constructor.
510 * \param[out] output_mesh a reference to the generated mesh
511 */
512 BuildRVDMesh(Mesh& output_mesh);
513
514 /**
515 * \brief BuildRVDMesh destructor.
516 */
517 ~BuildRVDMesh() override;
518
519 /**
520 * \brief Specifies whether ids should be generated.
521 * \details If enabled, unique vertex ids, seed ids and cell ids are
522 * generated and attached to the mesh vertices ("vertex_id" attribute)
523 * and mesh facets ("seed_id" and "cell_id" attributes) respectively.
524 * There is a cell_id per generated polyhedron, and seed_id refers to
525 * the Voronoi seed (the point that the Voronoi cell is associated
526 * with).
527 * \param[in] x true if ids should be generated, false
528 * otherwise (default)
529 */
530 void set_generate_ids(bool x);
531
532 /**
533 * \brief Defines the optional shrink factor for cells.
534 * \param[in] x shrink factor, 0.0 means no shrink, 1.0 means
535 * maximum shrink (cell reduced to a point).
536 */
537 void set_shrink(double x);
538
539 /**
540 * \brief Called at the beginning of RVD traversal.
541 */
542 void begin() override;
543
544 /**
545 * \brief Called at the end of RVD traversal.
546 */
547 void end() override;
548
549 /**
550 * \brief Called at the beginning of each RVD polyhedron.
551 * \param[in] seed , tetrahedron the (seed,tetrahedron) pair that
552 * defines the RVD polyhedron, as the intersection between the Voronoi
553 * cell of the seed and the tetrahedron.
554 */
555 void begin_polyhedron(index_t seed, index_t tetrahedron) override;
556
557 /**
558 * \copydoc RVDPolyhedronCallback::begin_facet()
559 */
560 void begin_facet(index_t facet_seed, index_t facet_tet_facet) override;
561
562 /**
563 * \copydoc RVDPolyhedronCallback::vertex()
564 */
565 void vertex(
566 const double* geometry, const GEOGen::SymbolicVertex& symb
567 ) override;
568
569 /**
570 * \copydoc RVDPolyhedronCallback::end_facet()
571 */
572 void end_facet() override;
573
574 /**
575 * \copydoc RVDPolyhedronCallback::end_polyhedron()
576 */
577 void end_polyhedron() override;
578
579 /**
580 * \copydoc RVDPolyhedronCallback::process_polyhedron_mesh()
581 */
582 void process_polyhedron_mesh() override;
583
584 private:
585 vector<index_t> current_facet_;
586 Mesh& output_mesh_;
587 RVDVertexMap* global_vertex_map_;
588 RVDVertexMap* cell_vertex_map_;
589 double shrink_;
590 bool generate_ids_;
591 Attribute<int> cell_id_;
592 Attribute<int> seed_id_;
593 Attribute<int> vertex_id_;
594 Attribute<int> facet_seed_id_;
595 index_t current_cell_id_;
596 };
597
598
599 /***************************************************************/
600
601 }
602
603 #endif
604