Easy3D 2.5.3
delaunay_3d.h
1/********************************************************************
2 * Copyright (C) 2015-2021 by Liangliang Nan <liangliang.nan@gmail.com>
3 * Copyright (C) 2000-2005 INRIA - Project ALICE
4 *
5 * The code in this file is partly from OGF/Graphite (2.0 alpha-4) with
6 * modifications and enhancement:
7 * https://gforge.inria.fr/forum/forum.php?forum_id=11459
8 * The original code was distributed under the GNU GPL license.
9 ********************************************************************/
10
11#ifndef EASY3D_ALGO_DELAUNAY_3D_H
12#define EASY3D_ALGO_DELAUNAY_3D_H
13
14
15#include <cassert>
16
17#include <easy3d/algo/delaunay.h>
18
19
20class tetgenio;
21
22
23namespace easy3d {
24
25 class VoronoiCell3d;
26
30
31 class Delaunay3 : public Delaunay {
32 public:
33 Delaunay3();
34
35 ~Delaunay3() override;
36
39 void set_vertices(unsigned int nb_vertices, const float *vertices) override;
40
42 void set_vertices(const std::vector<vec3> &vertices) {
43 // for QDel
44 if (vertices.capacity() - vertices.size() < 8) {
45 const_cast<std::vector<vec3> &>(vertices).reserve(vertices.size() + 8);
46 }
47 set_vertices((unsigned int) vertices.size(), &vertices[0].x);
48 }
49
51 unsigned int nb_tets() const { return nb_cells(); }
52
53 const int *tet_to_v() const { return cell_to_v(); }
54
55 const int *tet_to_tet() const { return cell_to_cell(); }
56
57 int vertex_tet(int v) const { return vertex_cell(v); }
58
59 unsigned int nearest_vertex(const float *p) const override {
60 return Delaunay::nearest_vertex(p);
61 }
62
63 unsigned int nearest_vertex(const vec3 &p) const {
64 return nearest_vertex(p.data());
65 }
66
67 const vec3 &vertex(unsigned int i) const {
68 return *(const vec3 *) vertex_ptr(i);
69 }
70
72 int tet_vertex(unsigned int t, unsigned int lv) const {
73 return cell_vertex(t, lv);
74 }
75
76 int tet_adjacent(unsigned int t, unsigned int lf) const {
77 return cell_adjacent(t, lf);
78 }
79
80 int tet_facet_vertex(unsigned int t, unsigned int lf, unsigned int lv) const {
81 assert(lf < 4);
82 assert(lv < 3);
83 return tet_vertex(t, facet_vertex_[lf][lv]);
84 }
85
86 int next_around_halfedge(int t, unsigned int lv1, unsigned int lv2) const {
87 assert(t < (int) nb_tets());
88 assert(t >= 0);
89 assert(lv1 < 4);
90 assert(lv2 < 4);
91 assert(lv1 != lv2);
92 return tet_adjacent(t, next_around_halfedge_[lv1][lv2]);
93 }
94
95 int prev_around_halfedge(int t, unsigned int lv1, unsigned int lv2) const {
96 return next_around_halfedge(t, lv2, lv1);
97 }
98
99 vec3 facet_normal(unsigned int t, unsigned int f) const {
100 assert(t < nb_tets());
101 assert(f < 4);
102 const vec3 &p1 = vertex(tet_vertex(t, facet_vertex_[f][0]));
103 const vec3 &p2 = vertex(tet_vertex(t, facet_vertex_[f][1]));
104 const vec3 &p3 = vertex(tet_vertex(t, facet_vertex_[f][2]));
105 vec3 result = cross(p2 - p1, p3 - p1);
106 return result;
107 }
108
109 vec3 tet_circumcenter(unsigned int t) const {
110 const vec3 &p0 = vertex(tet_vertex(t, 0));
111 const vec3 &p1 = vertex(tet_vertex(t, 1));
112 const vec3 &p2 = vertex(tet_vertex(t, 2));
113 const vec3 &p3 = vertex(tet_vertex(t, 3));
114 return geom::tetra_circum_center(p0, p1, p2, p3);
115 }
116
118 void get_voronoi_cell(
119 unsigned int v, VoronoiCell3d &cell, bool geometry = true
120 ) const;
121
122 protected:
123 void get_voronoi_facet(
124 VoronoiCell3d &cell, unsigned int t,
125 unsigned int lv1, unsigned int lv2, bool geometry
126 ) const;
127
128 static unsigned int other_in_face(
129 unsigned int f, unsigned int lv1, unsigned int lv2
130 ) {
131 assert(f < 4);
132 assert(lv1 < 4);
133 assert(lv2 < 4);
134 unsigned int ov1 = facet_vertex_[f][0];
135 unsigned int ov2 = facet_vertex_[f][1];
136 unsigned int ov3 = facet_vertex_[f][2];
137 if (lv1 == ov1 && lv2 == ov2) { return ov3; }
138 if (lv1 == ov2 && lv2 == ov1) { return ov3; }
139 if (lv1 == ov1 && lv2 == ov3) { return ov2; }
140 if (lv1 == ov3 && lv2 == ov1) { return ov2; }
141 if (lv1 == ov2 && lv2 == ov3) { return ov1; }
142 if (lv1 == ov3 && lv2 == ov2) { return ov1; }
143 DCHECK(false) << "should not have reached here";
144 return 4;
145 }
146
147 protected:
148 static unsigned int next_around_halfedge_[4][4];
149 static unsigned int facet_vertex_[4][3];
150
151 protected:
152 tetgenio *tetgen_out_;
153 tetgenio *tetgen_in_;
154 };
155
156 //________________________________________________________________________________
157
168 public:
169 VoronoiCell3d() { facet_ptr_.push_back(0); }
170
171 void clear() {
172 facet_ptr_.resize(0);
173 facet_bisector_.resize(0);
174 edge_bisector_.resize(0);
175 vertex_.resize(0);
176 infinite_.resize(0);
177 facet_ptr_.push_back(0);
178 }
179
180 unsigned int nb_facets() const {
181 return (unsigned int) facet_ptr_.size() - 1;
182 }
183
184 unsigned int facet_begin(unsigned int f) const {
185 assert(f < nb_facets());
186 return facet_ptr_[f];
187 }
188
189 unsigned int facet_end(unsigned int f) const {
190 assert(f < nb_facets());
191 return facet_ptr_[f + 1];
192 }
193
194 unsigned int nb_vertices(unsigned int f) const {
195 assert(f < nb_facets());
196 return facet_end(f) - facet_begin(f);
197 }
198
199 unsigned int next_around_facet(unsigned int f, unsigned int i) const {
200 assert(i >= facet_begin(f) && i < facet_end(f));
201 return (i + 1 == facet_end(f) ? facet_begin(f) : i + 1);
202 }
203
204 unsigned int prev_around_facet(unsigned int f, unsigned int i) const {
205 assert(i >= facet_begin(f) && i < facet_end(f));
206 return (i == facet_begin(f) ? facet_end(f) - 1 : i - 1);
207 }
208
214 unsigned int facet_bisector(unsigned int f) const {
215 assert(f < nb_facets());
216 return facet_bisector_[f];
217 }
218
233 int edge_bisector(unsigned int i) const {
234 assert(i < edge_bisector_.size());
235 return edge_bisector_[i];
236 }
237
243 const vec3 &vertex(unsigned int i) const {
244 assert(i < vertex_.size());
245 return vertex_[i];
246 }
247
248 bool vertex_is_infinite(unsigned int i) const {
249 assert(i < infinite_.size());
250 return infinite_[i];
251 }
252
253 void begin_facet(unsigned int f_bisector) {
254 facet_bisector_.push_back(f_bisector);
255 }
256
257 void add_to_facet(
258 int e_bisector, const vec3 &v, bool infinite
259 ) {
260 edge_bisector_.push_back(e_bisector);
261 vertex_.push_back(v);
262 infinite_.push_back(infinite);
263 }
264
265 void add_to_facet(
266 int e_bisector, bool infinite
267 ) {
268 edge_bisector_.push_back(e_bisector);
269 infinite_.push_back(infinite);
270 }
271
272 void end_facet() {
273 facet_ptr_.push_back((unsigned int) edge_bisector_.size());
274 }
275
276 unsigned int find_facet(unsigned int bisector) {
277 for (unsigned int i = 0; i < facet_bisector_.size(); i++) {
278 if (facet_bisector_[i] == bisector) {
279 return i;
280 }
281 }
282
283 // unexpected thing has happened, let's print some information for debugging
284 std::cerr << "bisector = " << bisector;
285 std::cerr << " facet = [";
286 for (auto fb : facet_bisector_) {
287 std::cerr << fb << " ";
288 }
289 std::cerr << "]" << std::endl;
290 DCHECK(false) << "should not have reached here";
291 return 0;
292 }
293
294 private:
295 std::vector<unsigned int> facet_ptr_;
296 std::vector<unsigned int> facet_bisector_;
297 std::vector<int> edge_bisector_;
298 std::vector<vec3> vertex_;
299 std::vector<bool> infinite_;
300 };
301
302/*
303 * The commented one is enough for basic 3D Delaunay implementation.
304 * The above one is verbose for easy understanding of the interface
305 * APIs and accessing Voronoi cells.
306 */
307
308//class MATH_API Delaunay3 : public Delaunay
309//{
310//public:
311// Delaunay3() ;
312// virtual ~Delaunay3() ;
313// virtual void set_vertices(unsigned int nb_vertices, const double* vertices) ;
314//
315//protected:
316// tetgenio* tetgen_out_ ;
317// tetgenio* tetgen_in_ ;
318//} ;
319
320} // namespace easy3d
321
322
323#endif // EASY3D_ALGO_DELAUNAY_3D_H
3D Delaunay triangulation, using Hang Si's tetgen.
Definition: delaunay_3d.h:31
unsigned int nb_tets() const
Returns the number of tetrahedra.
Definition: delaunay_3d.h:51
void set_vertices(const std::vector< vec3 > &vertices)
Sets the vertices from an array of 3D points.
Definition: delaunay_3d.h:42
void set_vertices(unsigned int nb_vertices, const float *vertices) override
Sets the vertices from an array of floating point numbers in which each consecutive number triple den...
Definition: delaunay_3d.cpp:33
void get_voronoi_cell(unsigned int v, VoronoiCell3d &cell, bool geometry=true) const
Returns the Voronoi cell associated with vertex v.
Definition: delaunay_3d.cpp:120
int tet_vertex(unsigned int t, unsigned int lv) const
Returns the index of the lv_th vertex in the t_th tetrahedron.
Definition: delaunay_3d.h:72
Base class for Delaunay triangulation.
Definition: delaunay.h:25
unsigned int nb_cells() const
Returns the number of cells.
Definition: delaunay.h:56
unsigned int nb_vertices() const
Returns the number of vertices.
Definition: delaunay.h:53
const float * vertex_ptr(unsigned int i) const
Returns the pointer to the vertex of index i.
Definition: delaunay.h:47
int cell_vertex(unsigned int c, unsigned int lv) const
Returns the index of the lv_th vertex in the c_th cell.
Definition: delaunay.h:65
A data structure for 3D Voronoi cells.
Definition: delaunay_3d.h:167
int edge_bisector(unsigned int i) const
Definition: delaunay_3d.h:233
const vec3 & vertex(unsigned int i) const
Definition: delaunay_3d.h:243
unsigned int facet_bisector(unsigned int f) const
Definition: delaunay_3d.h:214
vec3 tetra_circum_center(const vec3 &p, const vec3 &q, const vec3 &r, const vec3 &s)
Computes the circum center of a tetrahedron.
Definition: collider.cpp:182
Vec< 3, float > vec3
A 3D point/vector of float type.
Definition: types.h:45
Vec< 3, T > cross(const Vec< 3, T > &v1, const Vec< 3, T > &v2)
Compute the cross product of two 3D vectors.
Definition: vec.h:534