@@ -150,7 +150,7 @@ constexpr double EPSILON = std::numeric_limits<double>::epsilon();
150150constexpr std::size_t INVALID_INDEX = std::numeric_limits<std::size_t >::max();
151151
152152// @see https://stackoverflow.com/questions/30208196/maximum-recursive-function-calls-in-c-c-before-stack-is-full-and-gives-a-segme
153- constexpr std::size_t LEGALIZE_STACK_SIZE = 1024 ;
153+ constexpr std::size_t EDGE_STACK_SIZE = 1024 ;
154154
155155inline bool check_pts_equal (double x1, double y1, double x2, double y2) {
156156 return std::fabs (x1 - x2) <= EPSILON &&
@@ -193,7 +193,7 @@ class Delaunator {
193193 double m_center_x;
194194 double m_center_y;
195195 std::size_t m_hash_size;
196- std::size_t m_legalize_stack[LEGALIZE_STACK_SIZE ];
196+ std::size_t m_edge_stack[EDGE_STACK_SIZE ];
197197
198198 std::size_t legalize (std::size_t a);
199199 std::size_t hash_key (double x, double y) const ;
@@ -219,7 +219,7 @@ Delaunator::Delaunator(std::vector<double> const& in_coords)
219219 m_center_x(),
220220 m_center_y(),
221221 m_hash_size(),
222- m_legalize_stack () {
222+ m_edge_stack () {
223223 std::size_t n = coords.size () >> 1 ;
224224
225225 double max_x = std::numeric_limits<double >::min ();
@@ -440,21 +440,13 @@ double Delaunator::get_hull_area() {
440440 return sum (hull_area);
441441}
442442
443- std::size_t Delaunator::legalize (std::size_t ia) {
444- std::size_t b;
445- std::size_t a0;
446- std::size_t b0;
447- std::size_t al;
448- std::size_t ar;
449- std::size_t bl;
443+ std::size_t Delaunator::legalize (std::size_t a) {
444+ std::size_t i = 0 ;
445+ std::size_t ar = 0 ;
450446
451- unsigned int i = 0 ;
452- m_legalize_stack[i] = ia;
453- size_t size = 1 ;
454- while (i < size) {
455-
456- auto const a = m_legalize_stack[i];
457- i++;
447+ // recursion eliminated with a fixed-size stack
448+ while (true ) {
449+ const size_t b = halfedges[a];
458450
459451 /* if the pair of triangles doesn't satisfy the Delaunay condition
460452 * (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
@@ -471,26 +463,29 @@ std::size_t Delaunator::legalize(std::size_t ia) {
471463 * \||/ \ /
472464 * pr pr
473465 */
466+ const size_t a0 = 3 * (a / 3 );
467+ ar = a0 + (a + 2 ) % 3 ;
474468
475- b = halfedges[a];
476-
477- // @see https://embeddedgurus.com/stack-overflow/2011/02/efficient-c-tip-13-use-the-modulus-operator-with-caution/
478- a0 = 3 * (a / 3 ); // a - a % 3;
479- b0 = 3 * (b / 3 ); // b - b % 3;
469+ if (b == INVALID_INDEX) {
470+ if (i > 0 ) {
471+ i--;
472+ a = m_edge_stack[i];
473+ continue ;
474+ } else {
475+ // i = INVALID_INDEX;
476+ break ;
477+ }
478+ }
480479
481- al = a0 + (a + 1 ) % 3 ;
482- ar = a0 + (a + 2 ) % 3 ;
483- bl = b0 + (b + 2 ) % 3 ;
480+ const size_t b0 = 3 * (b / 3 ) ;
481+ const size_t al = a0 + (a + 1 ) % 3 ;
482+ const size_t bl = b0 + (b + 2 ) % 3 ;
484483
485484 const std::size_t p0 = triangles[ar];
486485 const std::size_t pr = triangles[a];
487486 const std::size_t pl = triangles[al];
488487 const std::size_t p1 = triangles[bl];
489488
490- if (b == INVALID_INDEX) {
491- continue ;
492- }
493-
494489 const bool illegal = in_circle (
495490 coords[2 * p0],
496491 coords[2 * p0 + 1 ],
@@ -521,23 +516,19 @@ std::size_t Delaunator::legalize(std::size_t ia) {
521516 link (a, hbl);
522517 link (b, halfedges[ar]);
523518 link (ar, bl);
524-
525519 std::size_t br = b0 + (b + 1 ) % 3 ;
526520
527- if (size + 2 >= (LEGALIZE_STACK_SIZE) ) {
528- throw std::runtime_error ( " Legalize stack overflow " ) ;
521+ if (i + 1 < EDGE_STACK_SIZE ) {
522+ m_edge_stack[i++] = br ;
529523 }
530-
531- if (i < size) {
532- // move elements down the stack
533- for (auto mi = size - 1 ; mi >= i; mi--) {
534- m_legalize_stack[mi + 2 ] = m_legalize_stack[mi];
535- }
524+ } else {
525+ if (i > 0 ) {
526+ i--;
527+ a = m_edge_stack[i];
528+ continue ;
529+ } else {
530+ break ;
536531 }
537-
538- m_legalize_stack[i] = a;
539- m_legalize_stack[i + 1 ] = br;
540- size += 2 ;
541532 }
542533 }
543534 return ar;
0 commit comments