Incremental_delaunay.h
1// SPDX-License-Identifier: GPL-3.0-or-later
2// As an exception, if you have a commercial license for the CGAL package Triangulation,
3// you may use this file under the same conditions.
4//
5// Author(s) : Michael Kerber, Marc Glisse, (Samuel Hornus for the original CGAL code)
6
7#include <CGAL/Delaunay_triangulation.h>
8#include <iterator>
9#include <vector>
10
11namespace Gudhi {
12
41template<typename K, typename SimplicialComplex, typename PointRange>
42void construct_incremental_delaunay(K const&k, SimplicialComplex& complex, PointRange const& points) {
43 using TDS = CGAL::Triangulation_data_structure<
44 typename K::Dimension,
45 CGAL::Triangulation_vertex<K, typename SimplicialComplex::Vertex_handle>,
46 CGAL::Triangulation_ds_full_cell<void, CGAL::TDS_full_cell_mirror_storage_policy> >;
47 using Triangulation = CGAL::Delaunay_triangulation<K, TDS>;
48 auto pt_it = std::begin(points);
49 auto pt_end = std::end(points);
50 if(pt_it == pt_end) return;
51 int d = k.point_dimension_d_object()(*pt_it);
52 Triangulation tri(d);
53
54 // local variables pulled out for recycling
55 typedef std::vector<typename Triangulation::Full_cell_handle> Full_cell_h_vector;
56 Full_cell_h_vector cs;
57 std::vector<typename SimplicialComplex::Vertex_handle> splx;
58
59 for(int idx = 0; pt_it != pt_end; ++pt_it, ++idx) {
60 // Adapted from Delaunay_triangulation::insert(Point)
61 auto&& p = *pt_it;
62 typename Triangulation::Locate_type lt;
63 typename Triangulation::Face f(d);
64 typename Triangulation::Facet ft;
65 typename Triangulation::Full_cell_handle s = tri.locate(p, lt, f, ft);
66 // Adapted from Delaunay_triangulation::insert(Point,Locate_type,Face,Facet,Full_cell_handle)
67 if (lt == Triangulation::OUTSIDE_AFFINE_HULL) {
68 // nothing disappears
69 tri.insert_outside_affine_hull(p)->data() = idx;
70 }
71 else if (lt == Triangulation::ON_VERTEX) {
72 // nothing disappears
73 }
74 else {
75 if(tri.current_dimension() == 1) {
76 if(lt == Triangulation::OUTSIDE_CONVEX_HULL) {
77 // only an infinite face disappears
78 } else {
79 complex.insert_simplex_and_subfaces({s->vertex(0)->data(), s->vertex(1)->data(), idx});
80 }
81 typename Triangulation::Vertex_handle v = tri.tds().insert_in_full_cell(s);
82 v->set_point(p);
83 v->data() = idx;
84 } else { // main case
85 // Adapted from Delaunay_triangulation::insert_in_conflicting_cell(Point,Full_cell_handle)
86 /* Full_cell_h_vector cs; */ cs.clear();
87 std::back_insert_iterator<Full_cell_h_vector> out(cs);
88 typename Triangulation::Facet ft = tri.compute_conflict_zone(p, s, out);
89 for(auto c : cs) {
90 /* std::vector<int> splx; */ splx.clear();
91 bool interrupted = false;
92 for(int i = 0; i <= tri.current_dimension(); ++i) {
93 // We could skip the infinite vertex and output a (new) simplex, but that's not so useful
94 if(tri.is_infinite(c->vertex(i))) { interrupted = true; break; }
95 splx.push_back(c->vertex(i)->data());
96 }
97 if (interrupted) continue;
98 // We could put idx at the beginning of the vector once instead of reinserting it each time
99 splx.push_back(idx);
100 complex.insert_simplex_and_subfaces(splx);
101 }
102 tri.insert_in_hole(p, cs.begin(), cs.end(), ft)->data() = idx;
103 }
104 }
105 }
106 // We have added all the conflict cells, but we are missing some current cells.
107 // There will be a lot of redundancy though.
108 for(auto it = tri.finite_full_cells_begin(); it != tri.finite_full_cells_end(); ++it) {
109 /* std::vector<int> splx; */ splx.clear();
110 for(int i = 0; i <= tri.current_dimension(); i++) {
111 splx.push_back(it->vertex(i)->data());
112 }
113 complex.insert_simplex_and_subfaces(splx);
114 // Or we could call insert_simplex_and_subfaces on a transform_iterator.
115 }
116}
117
118/* Strategies
119 1. Current
120 - every time a finite simplex disappears, output the conflict simplex
121 - output the final triangulation at the end (a bit costly)
122 2. Alternative from Kerber's function_delaunay
123 - every time a full-dimensional simplex disappears, output the finite faces of the conflict simplex
124 - this only works with some assumptions, for instance that the first d+1 points are affinely independent and
125 that the simplex they define is not in the final Delaunay triangulation.
126 3. Mix?
127 - we could use 1. until the triangulation reaches the ambient dimension then switch to 2.
128 - we could pretend the current dimension is going to be the final one, use 2, but fix things up every time
129 we insert a point outside the affine hull. Probably not very interesting, since triangulations of non-full
130 dimension should be rare.
131*/
132
133/* Possibilities:
134 - output conflict cells, new boundary cells, and final cells separately in case a user wants to handle them differently?
135 - we could remove duplicates in `points` so the numbering becomes contiguous, but then we have to output the new `points`.
136 - use less undocumented functions. Calling `insert` shouldn't cost that much more.
137*/
138} // namespace Gudhi
void construct_incremental_delaunay(K const &k, SimplicialComplex &complex, PointRange const &points)
Definition: Incremental_delaunay.h:42
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14