Ocean
Loading...
Searching...
No Matches
Delaunay.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_GEOMETRY_DELAUNAY_H
9#define META_OCEAN_GEOMETRY_DELAUNAY_H
10
12
15#include "ocean/math/Line2.h"
16
17#include <list>
18
19namespace Ocean
20{
21
22namespace Geometry
23{
24
25/**
26 * This class implements Delaunay triangulation functions.
27 * @ingroup geometry
28 */
29class OCEAN_GEOMETRY_EXPORT Delaunay
30{
31 public:
32
33 /**
34 * This class holds three indices of points representing a triangle.
35 */
37 {
38 public:
39
40 /**
41 * Creates an invalid index triangle object.
42 */
43 inline IndexTriangle();
44
45 /**
46 * Creates a new index triangle object.
47 * @param index0 First index
48 * @param index1 Second index
49 * @param index2 Third index
50 */
51 inline IndexTriangle(const unsigned int index0, const unsigned int index1, const unsigned int index2);
52
53 /**
54 * Returns the first index.
55 * First triangle index
56 */
57 inline unsigned int index0() const;
58
59 /**
60 * Returns the second index.
61 * Second triangle index
62 */
63 inline unsigned int index1() const;
64
65 /**
66 * Returns the third index.
67 * Third triangle index
68 */
69 inline unsigned int index2() const;
70
71 /**
72 * Returns whether three individual indices are stored.
73 * @return True, if so
74 */
75 inline bool isValid() const;
76
77 /**
78 * Returns one index of this triangle.
79 * @param n The (corner) index of the triangle for which the index is returned, with range [0, 2]
80 * @return The requested index
81 */
82 inline unsigned int operator[](const unsigned int n) const;
83
84 /**
85 * Returns whether two triangles are equal (i.e. whether both triangles are composed with the same indices, independent of their order).
86 * @param second The second triangle to test
87 * @return True, if both triangles are equal
88 */
89 inline bool operator==(const IndexTriangle &second) const;
90
91 /**
92 * Creates a 2D triangle with positions as corners from this index triangle.
93 * Beware: The number of points in the provided set, must exceed the maximal index, no check is done!
94 * @param points The set of points from which the corners are taken
95 */
96 inline Triangle2 triangle2(const Vector2* points) const;
97
98 /**
99 * Creates a 3D triangle with positions as corners from this index triangle.
100 * Beware: The number of points in the provided set, must exceed the maximal index, not check is done!
101 * @param points The set of points from which the corners are taken
102 */
103 inline Triangle3 triangle3(const Vector3* points) const;
104
105 protected:
106
107 /// Triangle indices;
108 unsigned int indices_[3];
109 };
110
111 /**
112 * Definition of a vector holding index triangles.
113 */
114 typedef std::vector<IndexTriangle> IndexTriangles;
115
116 protected:
117
118 /**
119 * This class extends the IndexTriangle class by an additional circumcircle as the Delaunay triangulation is based on this information.
120 */
122 {
123 public:
124
125 /**
126 * Creates a new index triangle object and calculates circumcenter and radius.
127 * Beware: The number of points in the provided set, must exceed the maximal index, no range check is done!
128 * @param index0 First index
129 * @param index1 Second index
130 * @param index2 Third index
131 * @param points The set of points from which the corners are taken, must be valid
132 */
133 inline CircumCricleIndexTriangle(const unsigned int index0, const unsigned int index1, const unsigned int index2, const Vector2* points);
134
135 /**
136 * Creates a new index triangle object and calculates circumcenter and radius.
137 * This constructor takes either the corners from the set of provided points or from a second set of points defining the super triangle.<br>
138 * The indices of the three corners of the super triangle are considered to be [size, size + 1, size + 2], while 'size' will be subtracted from those indices before accessing the corresponding point from 'pointsSuperTriangle'.
139 * @param index0 First index, with range [0, size + 3)
140 * @param index1 Second index, with range [0, size + 3)
141 * @param index2 Third index, with range [0, size + 3)
142 * @param points The set of points from which the corners are taken, must be valid
143 * @param size The number of points not including points from the super triangle
144 * @param pointsSuperTriangle The three points from the super triangle
145 */
146 inline CircumCricleIndexTriangle(const unsigned int index0, const unsigned int index1, const unsigned int index2, const Vector2* points, const size_t size, const Vector2* pointsSuperTriangle);
147
148 /**
149 * Swaps the order of the indices from a counter clockwise order to a clockwise order or vice versa.
150 */
151 inline void swap();
152
153 /**
154 * Returns whether a point is within the circumcircle of the triangle.
155 * @param point The point to evaluate if inside circumcircle
156 * @param epsilon The epsilon value used for a slightly more generous comparison, with range [0, infinity)
157 * @return True, if so
158 */
159 inline bool isInsideCircumCircle(const Vector2 &point, const Scalar epsilon = Numeric::eps()) const;
160
161 /**
162 * Returns whether a point is outside the circumcircle of the triangle.
163 * @param point The point to evaluate if outside circumcircle
164 * @param epsilon The epsilon value used for a slightly more generous comparison, with range [0, infinity)
165 * @return True, if so
166 */
167 inline bool isOutsideCircumCircle(const Vector2 &point, const Scalar epsilon = Numeric::eps()) const;
168
169 /**
170 * Returns whether a point is completely right of the circumcircle (i.e. point.x > circle.center + circle radius).
171 * This IndexTriangle must be initialized with a defined point set (i.e. circumcenter and circumradius must be calculated during initialization).
172 * @param point The point to evaluate if completely left of circumcircle
173 * @return True, if so
174 */
175 inline bool isRightOfCircumCircle(const Vector2 &point) const;
176
177 private:
178
179 /// 2D (Cartesian) circumcenter.
180 Vector2 circumcenter_ = Vector2(0, 0);
181
182 /// Radius of the circumcircle, with range [0, infinity), -1 for and invalid triangle object.
183 Scalar circumcircleRadius_ = -1;
184 };
185
186 /**
187 * Definition of a vector holding extended index triangles.
188 */
189 typedef std::vector<CircumCricleIndexTriangle> CircumCricleIndexTriangles;
190
191 /**
192 * Definition of a list holding extended index triangles.
193 */
194 typedef std::list<CircumCricleIndexTriangle> CircumCricleIndexTriangleList;
195
196 /**
197 * This class implements the lesser operator for indices of points.
198 * The sorting will be applied according to x coordinates of points, but instead of modifying the order of points, this class modifies the order of indices of points.
199 */
201 {
202 public:
203
204 /**
205 * Creates a new comparison object by a set of given points.
206 * @param points The points to be used for sorting, must be valid
207 */
208 explicit inline ComparePointsX(const Vector2* points);
209
210 /**
211 * Compares two point indices and returns whether the x coordinate of the first point is below the x coordinate of the second point.
212 * @param a The index of the first point
213 * @param b The index of the second point
214 * @return True, if so
215 */
216 inline bool operator()(const unsigned int a, const unsigned int b) const;
217
218 protected:
219
220 /// The points to be compared.
221 const Vector2* dataPoints_ = nullptr;
222 };
223
224 /**
225 * This class stores the sorted indices of an edge.
226 */
228 {
229 public:
230
231 /**
232 * Creates a new edge object and sorts the provided two point indices to ensure that the first index is smaller than the second index.
233 * @param indexFirst The index of the first point
234 * @param indexSecond The index of the second point, must be different from indexFirst
235 */
236 inline IndexEdge(const unsigned int indexFirst, const unsigned int indexSecond);
237
238 /**
239 * Creates a new edge object and sorts the provided two point indices to ensure that the point of the first index is 'smaller' than the point of the second index.
240 * @param indexFirst The index of the first point
241 * @param indexSecond The index of the second point, must be different from indexFirst
242 * @param points The points to be used for sorting, must be valid, ensure that enough points are provided
243 */
244 inline IndexEdge(const unsigned int indexFirst, const unsigned int indexSecond, const Vector2* points);
245
246 /**
247 * Returns the index of the first point.
248 * @return The point's first index
249 */
250 inline unsigned int firstIndex() const;
251
252 /**
253 * Returns the index of the second point.
254 * @return The point's second index
255 */
256 inline unsigned int secondIndex() const;
257
258 /**
259 * Lesser operator for two edge objects.
260 * @param right The second edge object to compare
261 * @return True, if this edge object is 'lesser' than the second one
262 */
263 inline bool operator<(const IndexEdge& right) const;
264
265 protected:
266
267 /// The index of the first point.
268 unsigned int firstIndex_ = (unsigned int)(-1);
269
270 /// The index of the second point.
271 unsigned int secondIndex_ = (unsigned int)(-1);
272 };
273
274 /**
275 * Definition of a map mapping edge pairs to a counter.
276 */
277 typedef std::map<IndexEdge, unsigned int> EdgeMap;
278
279 public:
280
281 /**
282 * Determines the delaunay triangulation for a given 2D point set.
283 * The implementation is based on the Bowyer-Watson algorithm.
284 * @param points 2D point set to be triangulated, at least three
285 * @return Resulting triangulation
286 */
287 static IndexTriangles triangulation(const Vectors2& points);
288
289 /**
290 * Checks a Delaunay triangulation for integrity: no points are allowed within the circumcircle of a triangle.
291 * @param triangles Delaunay triangulation
292 * @param points Vector with points coordinates
293 * @param epsilon The epsilon value used for a slightly more generous comparison, with range [0, infinity)
294 * @return True, if the provided triangulation is a valid Delaunay triangulation
295 */
296 static bool checkTriangulation(const IndexTriangles& triangles, const Vectors2& points, const Scalar epsilon = Numeric::eps());
297
298 protected:
299
300 /**
301 * Checks a Delaunay triangulation for integrity: no points are allowed within the circumcircle of a triangle.
302 * @param triangles Delaunay triangulation
303 * @param points Vector with points coordinates
304 * @param epsilon The epsilon value used for a slightly more generous comparison, with range [0, infinity)
305 * @return True, if the provided triangulation is a valid Delaunay triangulation
306 */
307 static bool checkTriangulation(const CircumCricleIndexTriangles& triangles, const Vectors2& points, const Scalar epsilon = Numeric::eps());
308};
309
311{
312 indices_[0] = (unsigned int)(-1);
313 indices_[1] = (unsigned int)(-1);
314 indices_[2] = (unsigned int)(-1);
315
316 ocean_assert(!isValid());
317}
318
319inline Delaunay::IndexTriangle::IndexTriangle(const unsigned int index0, const unsigned int index1, const unsigned int index2)
320{
321 indices_[0] = index0;
322 indices_[1] = index1;
323 indices_[2] = index2;
324
325 ocean_assert(isValid());
326}
327
328inline unsigned int Delaunay::IndexTriangle::index0() const
329{
330 return indices_[0];
331}
332
333inline unsigned int Delaunay::IndexTriangle::index1() const
334{
335 return indices_[1];
336}
337
338inline unsigned int Delaunay::IndexTriangle::index2() const
339{
340 return indices_[2];
341}
342
344{
345 return indices_[0] != indices_[1] && indices_[0] != indices_[2] && indices_[1] != indices_[2];
346}
347
348inline unsigned int Delaunay::IndexTriangle::operator[](const unsigned int n) const
349{
350 ocean_assert(n < 3u);
351 return indices_[n];
352}
353
355{
356 ocean_assert(isValid() && second.isValid());
357
358 return (index0() == second.index0() || index0() == second.index1() || index0() == second.index2())
359 && (index1() == second.index0() || index1() == second.index1() || index1() == second.index2())
360 && (index2() == second.index0() || index2() == second.index1() || index2() == second.index2());
361}
362
364{
365 ocean_assert(isValid() && points);
366
367 return Triangle2(points[indices_[0]], points[indices_[1]], points[indices_[2]]);
368}
369
371{
372 ocean_assert(isValid() && points);
373
374 return Triangle3(points[indices_[0]], points[indices_[1]], points[indices_[2]]);
375}
376
377inline Delaunay::CircumCricleIndexTriangle::CircumCricleIndexTriangle(const unsigned int index0, const unsigned int index1, const unsigned int index2, const Vector2* points) :
378 IndexTriangle(index0, index1, index2),
379 circumcenter_(0, 0),
380 circumcircleRadius_(-1)
381{
382 ocean_assert(points);
383
384 // make sure points are not co-linear
385 ocean_assert(points[index0] != points[index1] && points[index0] != points[index2] && points[index1] != points[index2]);
386
387 if constexpr (std::is_same<double, Scalar>::value)
388 {
389 ocean_assert(!Line2(points[index0], (points[index1] - points[index0]).normalizedOrZero()).isOnLine(points[index2]));
390 }
391
392 const Triangle2 triangle = triangle2(points);
393 ocean_assert(triangle.isValid());
394
396
397 // radius is equivalent to the distance between the circumcenter and all corners
399
400#ifdef OCEAN_DEBUG
401
402 if constexpr (std::is_same<double, Scalar>::value)
403 {
404 // sanity check, all distances should be equal
408 }
409
410#endif
411}
412
413inline Delaunay::CircumCricleIndexTriangle::CircumCricleIndexTriangle(const unsigned int index0, const unsigned int index1, const unsigned int index2, const Vector2* points, const size_t size, const Vector2* pointsSuperTriangle) :
414 IndexTriangle(index0, index1, index2),
415 circumcenter_(0, 0),
416 circumcircleRadius_(-1)
417{
418 ocean_assert(points && pointsSuperTriangle);
419
420 const Vector2& point0 = size_t(index0) < size ? points[index0] : pointsSuperTriangle[size_t(index0) - size];
421 const Vector2& point1 = size_t(index1) < size ? points[index1] : pointsSuperTriangle[size_t(index1) - size];
422 const Vector2& point2 = size_t(index2) < size ? points[index2] : pointsSuperTriangle[size_t(index2) - size];
423
424 // make sure points are not co-linear
425 ocean_assert(point0 != point1 && point0 != point2 && point1 != point2);
426
427 if constexpr (std::is_same<double, Scalar>::value)
428 {
429 ocean_assert(!Line2(point0, (point1 - point0).normalizedOrZero()).isOnLine(point2));
430 }
431
432 const Triangle2 triangle(point0, point1, point2);
433 ocean_assert(triangle.isValid());
434
436
437 // radius is equivalent to the distance between the circumcenter and all corners
439
440#ifdef OCEAN_DEBUG
441
442 if constexpr (std::is_same<double, Scalar>::value)
443 {
444 // sanity check, all distances should be equal
448 }
449
450#endif
451}
452
454{
455 std::swap(indices_[1], indices_[2]);
456}
457
459{
460 ocean_assert(isValid());
461 ocean_assert(circumcircleRadius_ >= 0);
462 ocean_assert(epsilon >= 0);
463
464 // make radius slightly higher in order to catch co-circular points
465 return circumcenter_.sqrDistance(point) <= Numeric::sqr(circumcircleRadius_ + epsilon);
466}
467
469{
470 ocean_assert(isValid());
471 ocean_assert(circumcircleRadius_ >= 0);
472 ocean_assert(epsilon >= 0);
473
474 // make radius slightly smaller in order to catch co-circular points
475 return circumcenter_.sqrDistance(point) + Numeric::sqr(epsilon) >= Numeric::sqr(circumcircleRadius_);
476}
477
479{
480 ocean_assert(isValid());
481 ocean_assert(circumcircleRadius_ >= 0);
482
483 return (circumcenter_.x() + circumcircleRadius_) < point.x();
484}
485
487 dataPoints_(points)
488{
489 ocean_assert(dataPoints_);
490}
491
492inline bool Delaunay::ComparePointsX::operator()(const unsigned int a, const unsigned int b) const
493{
494 ocean_assert(dataPoints_);
495
496 return dataPoints_[a].x() < dataPoints_[b].x();
497}
498
499inline Delaunay::IndexEdge::IndexEdge(const unsigned int indexFirst, const unsigned int indexSecond) :
500 firstIndex_(indexFirst < indexSecond ? indexFirst : indexSecond),
501 secondIndex_(indexFirst < indexSecond ? indexSecond : indexFirst)
502{
503 ocean_assert(firstIndex_ != secondIndex_);
504 ocean_assert(firstIndex_ < secondIndex_);
505}
506
507inline Delaunay::IndexEdge::IndexEdge(const unsigned int indexFirst, const unsigned int indexSecond, const Vector2* points) :
508 firstIndex_(points[indexFirst] < points[indexSecond] ? indexFirst : indexSecond),
509 secondIndex_(points[indexFirst] < points[indexSecond] ? indexSecond : indexFirst)
510{
511 ocean_assert(firstIndex_ != secondIndex_);
512 ocean_assert(firstIndex_ < secondIndex_);
513}
514
515inline unsigned int Delaunay::IndexEdge::firstIndex() const
516{
517 return firstIndex_;
518}
519
520inline unsigned int Delaunay::IndexEdge::secondIndex() const
521{
522 return secondIndex_;
523}
524
525inline bool Delaunay::IndexEdge::operator<(const IndexEdge& right) const
526{
527 return firstIndex_ < right.firstIndex_ || (firstIndex_ == right.firstIndex_ && secondIndex_ < right.secondIndex_);
528}
529
530}
531
532}
533
534#endif // META_OCEAN_GEOMETRY_DELAUNAY_H
This class extends the IndexTriangle class by an additional circumcircle as the Delaunay triangulatio...
Definition Delaunay.h:122
Scalar circumcircleRadius_
Radius of the circumcircle, with range [0, infinity), -1 for and invalid triangle object.
Definition Delaunay.h:183
CircumCricleIndexTriangle(const unsigned int index0, const unsigned int index1, const unsigned int index2, const Vector2 *points)
Creates a new index triangle object and calculates circumcenter and radius.
Definition Delaunay.h:377
bool isOutsideCircumCircle(const Vector2 &point, const Scalar epsilon=Numeric::eps()) const
Returns whether a point is outside the circumcircle of the triangle.
Definition Delaunay.h:468
bool isInsideCircumCircle(const Vector2 &point, const Scalar epsilon=Numeric::eps()) const
Returns whether a point is within the circumcircle of the triangle.
Definition Delaunay.h:458
bool isRightOfCircumCircle(const Vector2 &point) const
Returns whether a point is completely right of the circumcircle (i.e.
Definition Delaunay.h:478
Vector2 circumcenter_
2D (Cartesian) circumcenter.
Definition Delaunay.h:180
void swap()
Swaps the order of the indices from a counter clockwise order to a clockwise order or vice versa.
Definition Delaunay.h:453
This class implements the lesser operator for indices of points.
Definition Delaunay.h:201
bool operator()(const unsigned int a, const unsigned int b) const
Compares two point indices and returns whether the x coordinate of the first point is below the x coo...
Definition Delaunay.h:492
const Vector2 * dataPoints_
The points to be compared.
Definition Delaunay.h:221
ComparePointsX(const Vector2 *points)
Creates a new comparison object by a set of given points.
Definition Delaunay.h:486
This class stores the sorted indices of an edge.
Definition Delaunay.h:228
bool operator<(const IndexEdge &right) const
Lesser operator for two edge objects.
Definition Delaunay.h:525
unsigned int firstIndex_
The index of the first point.
Definition Delaunay.h:268
unsigned int secondIndex() const
Returns the index of the second point.
Definition Delaunay.h:520
unsigned int secondIndex_
The index of the second point.
Definition Delaunay.h:271
IndexEdge(const unsigned int indexFirst, const unsigned int indexSecond)
Creates a new edge object and sorts the provided two point indices to ensure that the first index is ...
Definition Delaunay.h:499
unsigned int firstIndex() const
Returns the index of the first point.
Definition Delaunay.h:515
This class holds three indices of points representing a triangle.
Definition Delaunay.h:37
unsigned int index2() const
Returns the third index.
Definition Delaunay.h:338
Triangle3 triangle3(const Vector3 *points) const
Creates a 3D triangle with positions as corners from this index triangle.
Definition Delaunay.h:370
IndexTriangle()
Creates an invalid index triangle object.
Definition Delaunay.h:310
Triangle2 triangle2(const Vector2 *points) const
Creates a 2D triangle with positions as corners from this index triangle.
Definition Delaunay.h:363
bool operator==(const IndexTriangle &second) const
Returns whether two triangles are equal (i.e.
Definition Delaunay.h:354
bool isValid() const
Returns whether three individual indices are stored.
Definition Delaunay.h:343
unsigned int index1() const
Returns the second index.
Definition Delaunay.h:333
unsigned int operator[](const unsigned int n) const
Returns one index of this triangle.
Definition Delaunay.h:348
unsigned int indices_[3]
Triangle indices;.
Definition Delaunay.h:108
unsigned int index0() const
Returns the first index.
Definition Delaunay.h:328
This class implements Delaunay triangulation functions.
Definition Delaunay.h:30
static bool checkTriangulation(const CircumCricleIndexTriangles &triangles, const Vectors2 &points, const Scalar epsilon=Numeric::eps())
Checks a Delaunay triangulation for integrity: no points are allowed within the circumcircle of a tri...
std::map< IndexEdge, unsigned int > EdgeMap
Definition of a map mapping edge pairs to a counter.
Definition Delaunay.h:277
std::vector< CircumCricleIndexTriangle > CircumCricleIndexTriangles
Definition of a vector holding extended index triangles.
Definition Delaunay.h:189
std::vector< IndexTriangle > IndexTriangles
Definition of a vector holding index triangles.
Definition Delaunay.h:114
static bool checkTriangulation(const IndexTriangles &triangles, const Vectors2 &points, const Scalar epsilon=Numeric::eps())
Checks a Delaunay triangulation for integrity: no points are allowed within the circumcircle of a tri...
std::list< CircumCricleIndexTriangle > CircumCricleIndexTriangleList
Definition of a list holding extended index triangles.
Definition Delaunay.h:194
static IndexTriangles triangulation(const Vectors2 &points)
Determines the delaunay triangulation for a given 2D point set.
static constexpr T weakEps()
Returns a weak epsilon.
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition Numeric.h:2386
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition Numeric.h:1495
This class implements a 2D triangle with Cartesian coordinates.
Definition Triangle2.h:81
const VectorT2< T > & point2() const
Returns the third triangle corner.
Definition Triangle2.h:415
const VectorT2< T > & point0() const
Returns the first triangle corner.
Definition Triangle2.h:403
VectorT2< T > cartesianCircumcenter() const
Returns the circumcenter for this triangle in Cartesian coordinates.
Definition Triangle2.h:792
const VectorT2< T > & point1() const
Returns the second triangle corner.
Definition Triangle2.h:409
bool isValid() const
Returns whether this triangle can provide valid barycentric coordinates (for 64 bit floating point va...
Definition Triangle2.h:806
This class implements a 3D triangle.
Definition Triangle3.h:80
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:710
T distance(const VectorT2< T > &right) const
Returns the distance between this 2D position and a second 2D position.
Definition Vector2.h:639
TriangleT3< Scalar > Triangle3
Definition of the Triangle3 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with sing...
Definition Triangle3.h:28
float Scalar
Definition of a scalar type.
Definition Math.h:129
LineT2< Scalar > Line2
Definition of the Line2 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single o...
Definition Line2.h:28
TriangleT2< Scalar > Triangle2
Definition of the Triangle2 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with sing...
Definition Triangle2.h:28
std::vector< Vector2 > Vectors2
Definition of a vector holding Vector2 objects.
Definition Vector2.h:64
The namespace covering the entire Ocean framework.
Definition Accessor.h:15