@@ -93,47 +93,38 @@ inline std::pair<double, double> circumcenter(
93
93
return std::make_pair (x, y);
94
94
}
95
95
96
- inline double compare (
97
- std::vector<double > const & coords,
98
- std::size_t i,
99
- std::size_t j,
100
- double cx,
101
- double cy) {
102
- const double d1 = dist (coords[2 * i], coords[2 * i + 1 ], cx, cy);
103
- const double d2 = dist (coords[2 * j], coords[2 * j + 1 ], cx, cy);
104
- const double diff1 = d1 - d2;
105
- const double diff2 = coords[2 * i] - coords[2 * j];
106
- const double diff3 = coords[2 * i + 1 ] - coords[2 * j + 1 ];
107
-
108
- if (diff1 > 0.0 || diff1 < 0.0 ) {
109
- return diff1;
110
- } else if (diff2 > 0.0 || diff2 < 0.0 ) {
111
- return diff2;
112
- } else {
113
- return diff3;
114
- }
115
- }
116
-
117
- struct sort_to_center {
96
+ struct compare {
118
97
119
98
std::vector<double > const & coords;
120
99
double cx;
121
100
double cy;
122
101
123
102
bool operator ()(std::size_t i, std::size_t j) {
124
- return compare (coords, i, j, cx, cy) < 0 ;
103
+ const double d1 = dist (coords[2 * i], coords[2 * i + 1 ], cx, cy);
104
+ const double d2 = dist (coords[2 * j], coords[2 * j + 1 ], cx, cy);
105
+ const double diff1 = d1 - d2;
106
+ const double diff2 = coords[2 * i] - coords[2 * j];
107
+ const double diff3 = coords[2 * i + 1 ] - coords[2 * j + 1 ];
108
+
109
+ if (diff1 > 0.0 || diff1 < 0.0 ) {
110
+ return diff1 < 0 ;
111
+ } else if (diff2 > 0.0 || diff2 < 0.0 ) {
112
+ return diff2 < 0 ;
113
+ } else {
114
+ return diff3 < 0 ;
115
+ }
125
116
}
126
117
};
127
118
128
119
inline bool in_circle (
129
- double ax,
130
- double ay,
131
- double bx,
132
- double by,
133
- double cx,
134
- double cy,
135
- double px,
136
- double py) {
120
+ const double ax,
121
+ const double ay,
122
+ const double bx,
123
+ const double by,
124
+ const double cx,
125
+ const double cy,
126
+ const double px,
127
+ const double py) {
137
128
const double dx = ax - px;
138
129
const double dy = ay - py;
139
130
const double ex = bx - px;
@@ -152,6 +143,7 @@ inline bool in_circle(
152
143
153
144
constexpr double EPSILON = std::numeric_limits<double >::epsilon();
154
145
constexpr std::size_t INVALID_INDEX = std::numeric_limits<std::size_t >::max();
146
+ constexpr std::size_t LEGALIZE_STACK_SIZE = 100 ;
155
147
156
148
inline bool check_pts_equal (double x1, double y1, double x2, double y2) {
157
149
return std::fabs (x1 - x2) <= EPSILON &&
@@ -194,6 +186,7 @@ class Delaunator {
194
186
double m_center_x;
195
187
double m_center_y;
196
188
std::size_t m_hash_size;
189
+ std::size_t m_legalize_stack[LEGALIZE_STACK_SIZE];
197
190
198
191
std::size_t legalize (std::size_t a);
199
192
std::size_t hash_key (double x, double y);
@@ -218,7 +211,8 @@ Delaunator::Delaunator(std::vector<double> const& in_coords)
218
211
m_hash(),
219
212
m_center_x(),
220
213
m_center_y(),
221
- m_hash_size() {
214
+ m_hash_size(),
215
+ m_legalize_stack() {
222
216
std::size_t n = coords.size () >> 1 ;
223
217
224
218
double max_x = std::numeric_limits<double >::min ();
@@ -305,7 +299,7 @@ Delaunator::Delaunator(std::vector<double> const& in_coords)
305
299
std::tie (m_center_x, m_center_y) = circumcenter (i0x, i0y, i1x, i1y, i2x, i2y);
306
300
307
301
// sort the points by distance from the seed triangle circumcenter
308
- std::sort (ids.begin (), ids.end (), sort_to_center { coords, m_center_x, m_center_y });
302
+ std::sort (ids.begin (), ids.end (), compare { coords, m_center_x, m_center_y });
309
303
310
304
// initialize a hash table for storing edges of the advancing convex hull
311
305
m_hash_size = static_cast <std::size_t >(std::llround (std::ceil (std::sqrt (n))));
@@ -439,75 +433,104 @@ double Delaunator::get_hull_area() {
439
433
return sum (hull_area);
440
434
}
441
435
442
- std::size_t Delaunator::legalize (std::size_t a) {
443
- const std::size_t b = halfedges[a];
444
-
445
- /* if the pair of triangles doesn't satisfy the Delaunay condition
446
- * (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
447
- * then do the same check/flip recursively for the new pair of triangles
448
- *
449
- * pl pl
450
- * /||\ / \
451
- * al/ || \bl al/ \a
452
- * / || \ / \
453
- * / a||b \ flip /___ar___\
454
- * p0\ || /p1 => p0\---bl---/p1
455
- * \ || / \ /
456
- * ar\ || /br b\ /br
457
- * \||/ \ /
458
- * pr pr
459
- */
460
- const std::size_t a0 = a - a % 3 ;
461
- const std::size_t b0 = b - b % 3 ;
462
-
463
- const std::size_t al = a0 + (a + 1 ) % 3 ;
464
- const std::size_t ar = a0 + (a + 2 ) % 3 ;
465
- const std::size_t bl = b0 + (b + 2 ) % 3 ;
466
-
467
- const std::size_t p0 = triangles[ar];
468
- const std::size_t pr = triangles[a];
469
- const std::size_t pl = triangles[al];
470
- const std::size_t p1 = triangles[bl];
471
-
472
- if (b == INVALID_INDEX) {
473
- return ar;
474
- }
436
+ std::size_t Delaunator::legalize (std::size_t ia) {
437
+ std::size_t b;
438
+ std::size_t a0;
439
+ std::size_t b0;
440
+ std::size_t al;
441
+ std::size_t ar;
442
+ std::size_t bl;
443
+
444
+ size_t i = 0 ;
445
+ m_legalize_stack[i] = ia;
446
+ size_t size = 1 ;
447
+ while (i < size) {
448
+
449
+ if (i >= LEGALIZE_STACK_SIZE) {
450
+ throw std::runtime_error (" Legalize stack overflow" );
451
+ }
475
452
476
- const bool illegal = in_circle (
477
- coords[2 * p0],
478
- coords[2 * p0 + 1 ],
479
- coords[2 * pr],
480
- coords[2 * pr + 1 ],
481
- coords[2 * pl],
482
- coords[2 * pl + 1 ],
483
- coords[2 * p1],
484
- coords[2 * p1 + 1 ]);
485
-
486
- if (illegal) {
487
- triangles[a] = p1;
488
- triangles[b] = p0;
489
-
490
- auto hbl = halfedges[bl];
491
-
492
- // edge swapped on the other side of the hull (rare); fix the halfedge reference
493
- if (hbl == INVALID_INDEX) {
494
- std::size_t e = hull_start;
495
- do {
496
- if (hull_tri[e] == bl) {
497
- hull_tri[e] = a;
498
- break ;
499
- }
500
- e = hull_next[e];
501
- } while (e != hull_start);
453
+ auto const a = m_legalize_stack[i];
454
+ i++;
455
+
456
+ /* if the pair of triangles doesn't satisfy the Delaunay condition
457
+ * (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
458
+ * then do the same check/flip recursively for the new pair of triangles
459
+ *
460
+ * pl pl
461
+ * /||\ / \
462
+ * al/ || \bl al/ \a
463
+ * / || \ / \
464
+ * / a||b \ flip /___ar___\
465
+ * p0\ || /p1 => p0\---bl---/p1
466
+ * \ || / \ /
467
+ * ar\ || /br b\ /br
468
+ * \||/ \ /
469
+ * pr pr
470
+ */
471
+
472
+ b = halfedges[a];
473
+
474
+ a0 = a - a % 3 ;
475
+ b0 = b - b % 3 ;
476
+
477
+ al = a0 + (a + 1 ) % 3 ;
478
+ ar = a0 + (a + 2 ) % 3 ;
479
+ bl = b0 + (b + 2 ) % 3 ;
480
+
481
+ const std::size_t p0 = triangles[ar];
482
+ const std::size_t pr = triangles[a];
483
+ const std::size_t pl = triangles[al];
484
+ const std::size_t p1 = triangles[bl];
485
+
486
+ if (b == INVALID_INDEX) {
487
+ continue ;
502
488
}
503
- link (a, hbl);
504
- link (b, halfedges[ar]);
505
- link (ar, bl);
506
489
507
- std::size_t br = b0 + (b + 1 ) % 3 ;
490
+ const bool illegal = in_circle (
491
+ coords[2 * p0],
492
+ coords[2 * p0 + 1 ],
493
+ coords[2 * pr],
494
+ coords[2 * pr + 1 ],
495
+ coords[2 * pl],
496
+ coords[2 * pl + 1 ],
497
+ coords[2 * p1],
498
+ coords[2 * p1 + 1 ]);
499
+
500
+ if (illegal) {
501
+ triangles[a] = p1;
502
+ triangles[b] = p0;
503
+
504
+ auto hbl = halfedges[bl];
505
+
506
+ // edge swapped on the other side of the hull (rare); fix the halfedge reference
507
+ if (hbl == INVALID_INDEX) {
508
+ std::size_t e = hull_start;
509
+ do {
510
+ if (hull_tri[e] == bl) {
511
+ hull_tri[e] = a;
512
+ break ;
513
+ }
514
+ e = hull_next[e];
515
+ } while (e != hull_start);
516
+ }
517
+ link (a, hbl);
518
+ link (b, halfedges[ar]);
519
+ link (ar, bl);
520
+
521
+ std::size_t br = b0 + (b + 1 ) % 3 ;
508
522
509
- legalize (a);
510
- return legalize (br);
523
+ if (i < size) {
524
+ // move elements down the stack
525
+ for (auto mi = size - 1 ; mi >= i; mi--) {
526
+ m_legalize_stack[mi + 2 ] = m_legalize_stack[mi];
527
+ }
528
+ }
529
+
530
+ m_legalize_stack[i] = a;
531
+ m_legalize_stack[i + 1 ] = br;
532
+ size+=2 ;
533
+ }
511
534
}
512
535
return ar;
513
536
}
@@ -537,7 +560,7 @@ std::size_t Delaunator::add_triangle(
537
560
return t;
538
561
}
539
562
540
- void Delaunator::link (std::size_t a, std::size_t b) {
563
+ void Delaunator::link (const std::size_t a, const std::size_t b) {
541
564
std::size_t s = halfedges.size ();
542
565
if (a == s) {
543
566
halfedges.push_back (b);
0 commit comments