Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

mapbox_earcut.h
Go to the documentation of this file.
1 
19 #pragma once
20 
21 #include <algorithm>
22 #include <cassert>
23 #include <cmath>
24 #include <memory>
25 #include <vector>
26 
27 #pragma GCC visibility push(default)
28 namespace mapbox {
29 
30 namespace util {
31 
32 template <std::size_t I, typename T> struct nth {
33  inline static typename std::tuple_element<I, T>::type
34  get(const T& t) { return std::get<I>(t); };
35 };
36 
37 }
38 
39 namespace detail {
40 
41 template <typename N = uint32_t>
42 class Earcut {
43 public:
44  std::vector<N> indices;
45  std::size_t vertices = 0;
46 
47  template <typename Polygon>
48  void operator()(const Polygon& points);
49 
50 private:
51  struct Node {
52  Node(N index, double x_, double y_) : i(index), x(x_), y(y_) {}
53  Node(const Node&) = delete;
54  Node& operator=(const Node&) = delete;
55  Node(Node&&) = delete;
56  Node& operator=(Node&&) = delete;
57 
58  const N i;
59  const double x;
60  const double y;
61 
62  // previous and next vertice nodes in a polygon ring
63  Node* prev = nullptr;
64  Node* next = nullptr;
65 
66  // z-order curve value
67  int32_t z = 0;
68 
69  // previous and next nodes in z-order
70  Node* prevZ = nullptr;
71  Node* nextZ = nullptr;
72 
73  // indicates whether this is a steiner point
74  bool steiner = false;
75  };
76 
77  template <typename Ring> Node* linkedList(const Ring& points, const bool clockwise);
78  Node* filterPoints(Node* start, Node* end = nullptr);
79  void earcutLinked(Node* ear, int pass = 0);
80  bool isEar(Node* ear);
81  bool isEarHashed(Node* ear);
83  void splitEarcut(Node* start);
84  template <typename Polygon> Node* eliminateHoles(const Polygon& points, Node* outerNode);
85  void eliminateHole(Node* hole, Node* outerNode);
86  Node* findHoleBridge(Node* hole, Node* outerNode);
87  void indexCurve(Node* start);
88  Node* sortLinked(Node* list);
89  int32_t zOrder(const double x_, const double y_);
90  Node* getLeftmost(Node* start);
91  bool pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const;
92  bool isValidDiagonal(Node* a, Node* b);
93  double area(const Node* p, const Node* q, const Node* r) const;
94  bool equals(const Node* p1, const Node* p2);
95  bool intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2);
96  bool intersectsPolygon(const Node* a, const Node* b);
97  bool locallyInside(const Node* a, const Node* b);
98  bool middleInside(const Node* a, const Node* b);
99  Node* splitPolygon(Node* a, Node* b);
100  template <typename Point> Node* insertNode(std::size_t i, const Point& p, Node* last);
101  void removeNode(Node* p);
102 
103  bool hashing;
104  double minX, maxX;
105  double minY, maxY;
106  double inv_size = 0;
107 
108  template <typename T, typename Alloc = std::allocator<T>>
109  class ObjectPool {
110  public:
112  ObjectPool(std::size_t blockSize_) {
113  reset(blockSize_);
114  }
116  clear();
117  }
118  template <typename... Args>
119  T* construct(Args&&... args) {
120  if (currentIndex >= blockSize) {
121  currentBlock = alloc_traits::allocate(alloc, blockSize);
122  allocations.emplace_back(currentBlock);
123  currentIndex = 0;
124  }
125  T* object = &currentBlock[currentIndex++];
126  alloc_traits::construct(alloc, object, std::forward<Args>(args)...);
127  return object;
128  }
129  void reset(std::size_t newBlockSize) {
130  for (auto allocation : allocations) {
131  alloc_traits::deallocate(alloc, allocation, blockSize);
132  }
133  allocations.clear();
134  blockSize = std::max<std::size_t>(1, newBlockSize);
135  currentBlock = nullptr;
137  }
138  void clear() { reset(blockSize); }
139  private:
140  T* currentBlock = nullptr;
141  std::size_t currentIndex = 1;
142  std::size_t blockSize = 1;
143  std::vector<T*> allocations;
144  Alloc alloc;
145  using alloc_traits = typename std::allocator_traits<Alloc>;
146  };
148 };
149 
150 template <typename N> template <typename Polygon>
151 void Earcut<N>::operator()(const Polygon& points) {
152  // reset
153  indices.clear();
154  vertices = 0;
155 
156  if (points.empty()) return;
157 
158  double x;
159  double y;
160  int threshold = 80;
161  std::size_t len = 0;
162 
163  for (size_t i = 0; threshold >= 0 && i < points.size(); i++) {
164  threshold -= static_cast<int>(points[i].size());
165  len += points[i].size();
166  }
167 
168  //estimate size of nodes and indices
169  nodes.reset(len * 3 / 2);
170  indices.reserve(len + points[0].size());
171 
172  Node* outerNode = linkedList(points[0], true);
173  if (!outerNode || outerNode->prev == outerNode->next) return;
174 
175  if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
176 
177  // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
178  hashing = threshold < 0;
179  if (hashing) {
180  Node* p = outerNode->next;
181  minX = maxX = outerNode->x;
182  minY = maxY = outerNode->y;
183  do {
184  x = p->x;
185  y = p->y;
186  minX = std::min<double>(minX, x);
187  minY = std::min<double>(minY, y);
188  maxX = std::max<double>(maxX, x);
189  maxY = std::max<double>(maxY, y);
190  p = p->next;
191  } while (p != outerNode);
192 
193  // minX, minY and size are later used to transform coords into integers for z-order calculation
194  inv_size = std::max<double>(maxX - minX, maxY - minY);
195  inv_size = inv_size != .0 ? (1. / inv_size) : .0;
196  }
197 
198  earcutLinked(outerNode);
199 
200  nodes.clear();
201 }
202 
203 // create a circular doubly linked list from polygon points in the specified winding order
204 template <typename N> template <typename Ring>
205 typename Earcut<N>::Node*
206 Earcut<N>::linkedList(const Ring& points, const bool clockwise) {
207  using Point = typename Ring::value_type;
208  double sum = 0;
209  const std::size_t len = points.size();
210  std::size_t i, j;
211  Node* last = nullptr;
212 
213  // calculate original winding order of a polygon ring
214  for (i = 0, j = len > 0 ? len - 1 : 0; i < len; j = i++) {
215  const auto& p1 = points[i];
216  const auto& p2 = points[j];
217  const double p20 = util::nth<0, Point>::get(p2);
218  const double p10 = util::nth<0, Point>::get(p1);
219  const double p11 = util::nth<1, Point>::get(p1);
220  const double p21 = util::nth<1, Point>::get(p2);
221  sum += (p20 - p10) * (p11 + p21);
222  }
223 
224  // link points into circular doubly-linked list in the specified winding order
225  if (clockwise == (sum > 0)) {
226  for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last);
227  } else {
228  for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last);
229  }
230 
231  if (last && equals(last, last->next)) {
232  removeNode(last);
233  last = last->next;
234  }
235 
236  vertices += len;
237 
238  return last;
239 }
240 
241 // eliminate colinear or duplicate points
242 template <typename N>
243 typename Earcut<N>::Node*
245  if (!end) end = start;
246 
247  Node* p = start;
248  bool again;
249  do {
250  again = false;
251 
252  if (!p->steiner && (equals(p, p->next) || area(p->prev, p, p->next) == 0)) {
253  removeNode(p);
254  p = end = p->prev;
255 
256  if (p == p->next) break;
257  again = true;
258 
259  } else {
260  p = p->next;
261  }
262  } while (again || p != end);
263 
264  return end;
265 }
266 
267 // main ear slicing loop which triangulates a polygon (given as a linked list)
268 template <typename N>
269 void Earcut<N>::earcutLinked(Node* ear, int pass) {
270  if (!ear) return;
271 
272  // interlink polygon nodes in z-order
273  if (!pass && hashing) indexCurve(ear);
274 
275  Node* stop = ear;
276  Node* prev;
277  Node* next;
278 
279  // iterate through ears, slicing them one by one
280  while (ear->prev != ear->next) {
281  prev = ear->prev;
282  next = ear->next;
283 
284  if (hashing ? isEarHashed(ear) : isEar(ear)) {
285  // cut off the triangle
286  indices.emplace_back(prev->i);
287  indices.emplace_back(ear->i);
288  indices.emplace_back(next->i);
289 
290  removeNode(ear);
291 
292  // skipping the next vertice leads to less sliver triangles
293  ear = next->next;
294  stop = next->next;
295 
296  continue;
297  }
298 
299  ear = next;
300 
301  // if we looped through the whole remaining polygon and can't find any more ears
302  if (ear == stop) {
303  // try filtering points and slicing again
304  if (!pass) earcutLinked(filterPoints(ear), 1);
305 
306  // if this didn't work, try curing all small self-intersections locally
307  else if (pass == 1) {
308  ear = cureLocalIntersections(ear);
309  earcutLinked(ear, 2);
310 
311  // as a last resort, try splitting the remaining polygon into two
312  } else if (pass == 2) splitEarcut(ear);
313 
314  break;
315  }
316  }
317 }
318 
319 // check whether a polygon node forms a valid ear with adjacent nodes
320 template <typename N>
321 bool Earcut<N>::isEar(Node* ear) {
322  const Node* a = ear->prev;
323  const Node* b = ear;
324  const Node* c = ear->next;
325 
326  if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
327 
328  // now make sure we don't have other points inside the potential ear
329  Node* p = ear->next->next;
330 
331  while (p != ear->prev) {
332  if (pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
333  area(p->prev, p, p->next) >= 0) return false;
334  p = p->next;
335  }
336 
337  return true;
338 }
339 
340 template <typename N>
342  const Node* a = ear->prev;
343  const Node* b = ear;
344  const Node* c = ear->next;
345 
346  if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
347 
348  // triangle bbox; min & max are calculated like this for speed
349  const double minTX = std::min<double>(a->x, std::min<double>(b->x, c->x));
350  const double minTY = std::min<double>(a->y, std::min<double>(b->y, c->y));
351  const double maxTX = std::max<double>(a->x, std::max<double>(b->x, c->x));
352  const double maxTY = std::max<double>(a->y, std::max<double>(b->y, c->y));
353 
354  // z-order range for the current triangle bbox;
355  const int32_t minZ = zOrder(minTX, minTY);
356  const int32_t maxZ = zOrder(maxTX, maxTY);
357 
358  // first look for points inside the triangle in increasing z-order
359  Node* p = ear->nextZ;
360 
361  while (p && p->z <= maxZ) {
362  if (p != ear->prev && p != ear->next &&
363  pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
364  area(p->prev, p, p->next) >= 0) return false;
365  p = p->nextZ;
366  }
367 
368  // then look for points in decreasing z-order
369  p = ear->prevZ;
370 
371  while (p && p->z >= minZ) {
372  if (p != ear->prev && p != ear->next &&
373  pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
374  area(p->prev, p, p->next) >= 0) return false;
375  p = p->prevZ;
376  }
377 
378  return true;
379 }
380 
381 // go through all polygon nodes and cure small local self-intersections
382 template <typename N>
383 typename Earcut<N>::Node*
385  Node* p = start;
386  do {
387  Node* a = p->prev;
388  Node* b = p->next->next;
389 
390  // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2])
391  if (!equals(a, b) && intersects(a, p, p->next, b) && locallyInside(a, b) && locallyInside(b, a)) {
392  indices.emplace_back(a->i);
393  indices.emplace_back(p->i);
394  indices.emplace_back(b->i);
395 
396  // remove two nodes involved
397  removeNode(p);
398  removeNode(p->next);
399 
400  p = start = b;
401  }
402  p = p->next;
403  } while (p != start);
404 
405  return p;
406 }
407 
408 // try splitting polygon into two and triangulate them independently
409 template <typename N>
411  // look for a valid diagonal that divides the polygon into two
412  Node* a = start;
413  do {
414  Node* b = a->next->next;
415  while (b != a->prev) {
416  if (a->i != b->i && isValidDiagonal(a, b)) {
417  // split the polygon in two by the diagonal
418  Node* c = splitPolygon(a, b);
419 
420  // filter colinear points around the cuts
421  a = filterPoints(a, a->next);
422  c = filterPoints(c, c->next);
423 
424  // run earcut on each half
425  earcutLinked(a);
426  earcutLinked(c);
427  return;
428  }
429  b = b->next;
430  }
431  a = a->next;
432  } while (a != start);
433 }
434 
435 // link every hole into the outer loop, producing a single-ring polygon without holes
436 template <typename N> template <typename Polygon>
437 typename Earcut<N>::Node*
438 Earcut<N>::eliminateHoles(const Polygon& points, Node* outerNode) {
439  const size_t len = points.size();
440 
441  std::vector<Node*> queue;
442  for (size_t i = 1; i < len; i++) {
443  Node* list = linkedList(points[i], false);
444  if (list) {
445  if (list == list->next) list->steiner = true;
446  queue.push_back(getLeftmost(list));
447  }
448  }
449  std::sort(queue.begin(), queue.end(), [](const Node* a, const Node* b) {
450  return a->x < b->x;
451  });
452 
453  // process holes from left to right
454  for (size_t i = 0; i < queue.size(); i++) {
455  eliminateHole(queue[i], outerNode);
456  outerNode = filterPoints(outerNode, outerNode->next);
457  }
458 
459  return outerNode;
460 }
461 
462 // find a bridge between vertices that connects hole with an outer ring and and link it
463 template <typename N>
464 void Earcut<N>::eliminateHole(Node* hole, Node* outerNode) {
465  outerNode = findHoleBridge(hole, outerNode);
466  if (outerNode) {
467  Node* b = splitPolygon(outerNode, hole);
468  filterPoints(b, b->next);
469  }
470 }
471 
472 // David Eberly's algorithm for finding a bridge between hole and outer polygon
473 template <typename N>
474 typename Earcut<N>::Node*
475 Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
476  Node* p = outerNode;
477  double hx = hole->x;
478  double hy = hole->y;
480  Node* m = nullptr;
481 
482  // find a segment intersected by a ray from the hole's leftmost Vertex to the left;
483  // segment's endpoint with lesser x will be potential connection Vertex
484  do {
485  if (hy <= p->y && hy >= p->next->y && p->next->y != p->y) {
486  double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y);
487  if (x <= hx && x > qx) {
488  qx = x;
489  if (x == hx) {
490  if (hy == p->y) return p;
491  if (hy == p->next->y) return p->next;
492  }
493  m = p->x < p->next->x ? p : p->next;
494  }
495  }
496  p = p->next;
497  } while (p != outerNode);
498 
499  if (!m) return 0;
500 
501  if (hx == qx) return m->prev;
502 
503  // look for points inside the triangle of hole Vertex, segment intersection and endpoint;
504  // if there are no points found, we have a valid connection;
505  // otherwise choose the Vertex of the minimum angle with the ray as connection Vertex
506 
507  const Node* stop = m;
508  double tanMin = std::numeric_limits<double>::infinity();
509  double tanCur = 0;
510 
511  p = m->next;
512  double mx = m->x;
513  double my = m->y;
514 
515  while (p != stop) {
516  if (hx >= p->x && p->x >= mx && hx != p->x &&
517  pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p->x, p->y)) {
518 
519  tanCur = std::abs(hy - p->y) / (hx - p->x); // tangential
520 
521  if ((tanCur < tanMin || (tanCur == tanMin && p->x > m->x)) && locallyInside(p, hole)) {
522  m = p;
523  tanMin = tanCur;
524  }
525  }
526 
527  p = p->next;
528  }
529 
530  return m;
531 }
532 
533 // interlink polygon nodes in z-order
534 template <typename N>
536  assert(start);
537  Node* p = start;
538 
539  do {
540  p->z = p->z ? p->z : zOrder(p->x, p->y);
541  p->prevZ = p->prev;
542  p->nextZ = p->next;
543  p = p->next;
544  } while (p != start);
545 
546  p->prevZ->nextZ = nullptr;
547  p->prevZ = nullptr;
548 
549  sortLinked(p);
550 }
551 
552 // Simon Tatham's linked list merge sort algorithm
553 // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
554 template <typename N>
555 typename Earcut<N>::Node*
557  assert(list);
558  Node* p;
559  Node* q;
560  Node* e;
561  Node* tail;
562  int i, numMerges, pSize, qSize;
563  int inSize = 1;
564 
565  for (;;) {
566  p = list;
567  list = nullptr;
568  tail = nullptr;
569  numMerges = 0;
570 
571  while (p) {
572  numMerges++;
573  q = p;
574  pSize = 0;
575  for (i = 0; i < inSize; i++) {
576  pSize++;
577  q = q->nextZ;
578  if (!q) break;
579  }
580 
581  qSize = inSize;
582 
583  while (pSize > 0 || (qSize > 0 && q)) {
584 
585  if (pSize == 0) {
586  e = q;
587  q = q->nextZ;
588  qSize--;
589  } else if (qSize == 0 || !q) {
590  e = p;
591  p = p->nextZ;
592  pSize--;
593  } else if (p->z <= q->z) {
594  e = p;
595  p = p->nextZ;
596  pSize--;
597  } else {
598  e = q;
599  q = q->nextZ;
600  qSize--;
601  }
602 
603  if (tail) tail->nextZ = e;
604  else list = e;
605 
606  e->prevZ = tail;
607  tail = e;
608  }
609 
610  p = q;
611  }
612 
613  tail->nextZ = nullptr;
614 
615  if (numMerges <= 1) return list;
616 
617  inSize *= 2;
618  }
619 }
620 
621 // z-order of a Vertex given coords and size of the data bounding box
622 template <typename N>
623 int32_t Earcut<N>::zOrder(const double x_, const double y_) {
624  // coords are transformed into non-negative 15-bit integer range
625  int32_t x = static_cast<int32_t>(32767.0 * (x_ - minX) * inv_size);
626  int32_t y = static_cast<int32_t>(32767.0 * (y_ - minY) * inv_size);
627 
628  x = (x | (x << 8)) & 0x00FF00FF;
629  x = (x | (x << 4)) & 0x0F0F0F0F;
630  x = (x | (x << 2)) & 0x33333333;
631  x = (x | (x << 1)) & 0x55555555;
632 
633  y = (y | (y << 8)) & 0x00FF00FF;
634  y = (y | (y << 4)) & 0x0F0F0F0F;
635  y = (y | (y << 2)) & 0x33333333;
636  y = (y | (y << 1)) & 0x55555555;
637 
638  return x | (y << 1);
639 }
640 
641 // find the leftmost node of a polygon ring
642 template <typename N>
643 typename Earcut<N>::Node*
645  Node* p = start;
646  Node* leftmost = start;
647  do {
648  if (p->x < leftmost->x || (p->x == leftmost->x && p->y < leftmost->y))
649  leftmost = p;
650  p = p->next;
651  } while (p != start);
652 
653  return leftmost;
654 }
655 
656 // check if a point lies within a convex triangle
657 template <typename N>
658 bool Earcut<N>::pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const {
659  return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
660  (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
661  (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
662 }
663 
664 // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
665 template <typename N>
667  return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) &&
668  locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b);
669 }
670 
671 // signed area of a triangle
672 template <typename N>
673 double Earcut<N>::area(const Node* p, const Node* q, const Node* r) const {
674  return (q->y - p->y) * (r->x - q->x) - (q->x - p->x) * (r->y - q->y);
675 }
676 
677 // check if two points are equal
678 template <typename N>
679 bool Earcut<N>::equals(const Node* p1, const Node* p2) {
680  return p1->x == p2->x && p1->y == p2->y;
681 }
682 
683 // check if two segments intersect
684 template <typename N>
685 bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) {
686  if ((equals(p1, q1) && equals(p2, q2)) ||
687  (equals(p1, q2) && equals(p2, q1))) return true;
688  return (area(p1, q1, p2) > 0) != (area(p1, q1, q2) > 0) &&
689  (area(p2, q2, p1) > 0) != (area(p2, q2, q1) > 0);
690 }
691 
692 // check if a polygon diagonal intersects any polygon segments
693 template <typename N>
694 bool Earcut<N>::intersectsPolygon(const Node* a, const Node* b) {
695  const Node* p = a;
696  do {
697  if (p->i != a->i && p->next->i != a->i && p->i != b->i && p->next->i != b->i &&
698  intersects(p, p->next, a, b)) return true;
699  p = p->next;
700  } while (p != a);
701 
702  return false;
703 }
704 
705 // check if a polygon diagonal is locally inside the polygon
706 template <typename N>
707 bool Earcut<N>::locallyInside(const Node* a, const Node* b) {
708  return area(a->prev, a, a->next) < 0 ?
709  area(a, b, a->next) >= 0 && area(a, a->prev, b) >= 0 :
710  area(a, b, a->prev) < 0 || area(a, a->next, b) < 0;
711 }
712 
713 // check if the middle Vertex of a polygon diagonal is inside the polygon
714 template <typename N>
715 bool Earcut<N>::middleInside(const Node* a, const Node* b) {
716  const Node* p = a;
717  bool inside = false;
718  double px = (a->x + b->x) / 2;
719  double py = (a->y + b->y) / 2;
720  do {
721  if (((p->y > py) != (p->next->y > py)) && p->next->y != p->y &&
722  (px < (p->next->x - p->x) * (py - p->y) / (p->next->y - p->y) + p->x))
723  inside = !inside;
724  p = p->next;
725  } while (p != a);
726 
727  return inside;
728 }
729 
730 // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits
731 // polygon into two; if one belongs to the outer ring and another to a hole, it merges it into a
732 // single ring
733 template <typename N>
734 typename Earcut<N>::Node*
736  Node* a2 = nodes.construct(a->i, a->x, a->y);
737  Node* b2 = nodes.construct(b->i, b->x, b->y);
738  Node* an = a->next;
739  Node* bp = b->prev;
740 
741  a->next = b;
742  b->prev = a;
743 
744  a2->next = an;
745  an->prev = a2;
746 
747  b2->next = a2;
748  a2->prev = b2;
749 
750  bp->next = b2;
751  b2->prev = bp;
752 
753  return b2;
754 }
755 
756 // create a node and util::optionally link it with previous one (in a circular doubly linked list)
757 template <typename N> template <typename Point>
758 typename Earcut<N>::Node*
759 Earcut<N>::insertNode(std::size_t i, const Point& pt, Node* last) {
760  Node* p = nodes.construct(static_cast<N>(i), util::nth<0, Point>::get(pt), util::nth<1, Point>::get(pt));
761 
762  if (!last) {
763  p->prev = p;
764  p->next = p;
765 
766  } else {
767  assert(last);
768  p->next = last->next;
769  p->prev = last;
770  last->next->prev = p;
771  last->next = p;
772  }
773  return p;
774 }
775 
776 template <typename N>
778  p->next->prev = p->prev;
779  p->prev->next = p->next;
780 
781  if (p->prevZ) p->prevZ->nextZ = p->nextZ;
782  if (p->nextZ) p->nextZ->prevZ = p->prevZ;
783 }
784 }
785 
786 template <typename N = uint32_t, typename Polygon>
787 std::vector<N> earcut(const Polygon& poly) {
789  earcut(poly);
790  return std::move(earcut.indices);
791 }
792 }
793 #pragma GCC visibility pop
mapbox::detail::Earcut::Node
Definition: mapbox_earcut.h:51
mapbox::detail::Earcut::getLeftmost
Node * getLeftmost(Node *start)
Definition: mapbox_earcut.h:644
mapbox::detail::Earcut::minY
double minY
Definition: mapbox_earcut.h:105
mapbox::detail::Earcut::ObjectPool::currentBlock
T * currentBlock
Definition: mapbox_earcut.h:140
mapbox::detail::Earcut::isEar
bool isEar(Node *ear)
Definition: mapbox_earcut.h:321
mapbox::detail::Earcut::Node::nextZ
Node * nextZ
Definition: mapbox_earcut.h:71
ogdf::matching_blossom::infinity
TWeight infinity()
Helper function to get the maximum value for a given weight type.
Definition: utils.h:46
mapbox::detail::Earcut::splitEarcut
void splitEarcut(Node *start)
Definition: mapbox_earcut.h:410
mapbox::detail::Earcut::locallyInside
bool locallyInside(const Node *a, const Node *b)
Definition: mapbox_earcut.h:707
mapbox::detail::Earcut::ObjectPool::ObjectPool
ObjectPool()
Definition: mapbox_earcut.h:111
mapbox::detail::Earcut::earcutLinked
void earcutLinked(Node *ear, int pass=0)
Definition: mapbox_earcut.h:269
mapbox::detail::Earcut::cureLocalIntersections
Node * cureLocalIntersections(Node *start)
Definition: mapbox_earcut.h:384
mapbox::detail::Earcut::equals
bool equals(const Node *p1, const Node *p2)
Definition: mapbox_earcut.h:679
mapbox::detail::Earcut::middleInside
bool middleInside(const Node *a, const Node *b)
Definition: mapbox_earcut.h:715
mapbox::detail::Earcut::maxX
double maxX
Definition: mapbox_earcut.h:104
mapbox::detail::Earcut::ObjectPool::construct
T * construct(Args &&... args)
Definition: mapbox_earcut.h:119
mapbox::detail::Earcut::isValidDiagonal
bool isValidDiagonal(Node *a, Node *b)
Definition: mapbox_earcut.h:666
mapbox::detail::Earcut::pointInTriangle
bool pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const
Definition: mapbox_earcut.h:658
mapbox::detail::Earcut::Node::x
const double x
Definition: mapbox_earcut.h:59
mapbox::detail::Earcut::ObjectPool::reset
void reset(std::size_t newBlockSize)
Definition: mapbox_earcut.h:129
mapbox::detail::Earcut::Node::next
Node * next
Definition: mapbox_earcut.h:64
mapbox::detail::Earcut::eliminateHole
void eliminateHole(Node *hole, Node *outerNode)
Definition: mapbox_earcut.h:464
mapbox::detail::Earcut::findHoleBridge
Node * findHoleBridge(Node *hole, Node *outerNode)
Definition: mapbox_earcut.h:475
mapbox::detail::Earcut::ObjectPool::alloc
Alloc alloc
Definition: mapbox_earcut.h:144
mapbox::detail::Earcut::linkedList
Node * linkedList(const Ring &points, const bool clockwise)
Definition: mapbox_earcut.h:206
Minisat::Internal::sort
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:58
r
int r[]
Definition: hierarchical-ranking.cpp:13
mapbox::detail::Earcut::filterPoints
Node * filterPoints(Node *start, Node *end=nullptr)
Definition: mapbox_earcut.h:244
mapbox::detail::Earcut::eliminateHoles
Node * eliminateHoles(const Polygon &points, Node *outerNode)
Definition: mapbox_earcut.h:438
mapbox::detail::Earcut::insertNode
Node * insertNode(std::size_t i, const Point &p, Node *last)
Definition: mapbox_earcut.h:759
backward::Color::type
type
Definition: backward.hpp:1716
mapbox::detail::Earcut::area
double area(const Node *p, const Node *q, const Node *r) const
Definition: mapbox_earcut.h:673
backward::details::move
const T & move(const T &v)
Definition: backward.hpp:243
mapbox::detail::Earcut::Node::Node
Node(N index, double x_, double y_)
Definition: mapbox_earcut.h:52
mapbox::detail::Earcut::operator()
void operator()(const Polygon &points)
Definition: mapbox_earcut.h:151
mapbox::detail::Earcut::Node::i
const N i
Definition: mapbox_earcut.h:58
mapbox::detail::Earcut::Node::operator=
Node & operator=(const Node &)=delete
mapbox::detail::Earcut::Node::prev
Node * prev
Definition: mapbox_earcut.h:63
mapbox::detail::Earcut::sortLinked
Node * sortLinked(Node *list)
Definition: mapbox_earcut.h:556
mapbox::detail::Earcut::splitPolygon
Node * splitPolygon(Node *a, Node *b)
Definition: mapbox_earcut.h:735
mapbox::detail::Earcut::Node::z
int32_t z
Definition: mapbox_earcut.h:67
mapbox::detail::Earcut::intersects
bool intersects(const Node *p1, const Node *q1, const Node *p2, const Node *q2)
Definition: mapbox_earcut.h:685
mapbox::detail::Earcut::ObjectPool::ObjectPool
ObjectPool(std::size_t blockSize_)
Definition: mapbox_earcut.h:112
mapbox::detail::Earcut::ObjectPool< mapbox::detail::Earcut::Node >::alloc_traits
typename std::allocator_traits< std::allocator< mapbox::detail::Earcut::Node > > alloc_traits
Definition: mapbox_earcut.h:145
mapbox::earcut
std::vector< N > earcut(const Polygon &poly)
Definition: mapbox_earcut.h:787
mapbox::detail::Earcut::inv_size
double inv_size
Definition: mapbox_earcut.h:106
mapbox::detail::Earcut::removeNode
void removeNode(Node *p)
Definition: mapbox_earcut.h:777
mapbox::util::nth::get
static std::tuple_element< I, T >::type get(const T &t)
Definition: mapbox_earcut.h:34
mapbox::detail::Earcut::vertices
std::size_t vertices
Definition: mapbox_earcut.h:45
mapbox::detail::Earcut::nodes
ObjectPool< Node > nodes
Definition: mapbox_earcut.h:147
mapbox::detail::Earcut::minX
double minX
Definition: mapbox_earcut.h:104
mapbox::detail::Earcut::Node::y
const double y
Definition: mapbox_earcut.h:60
mapbox::detail::Earcut
Definition: mapbox_earcut.h:42
ogdf::end
HypergraphRegistry< HypernodeElement >::iterator end(const HypergraphRegistry< HypernodeElement > &self)
mapbox::detail::Earcut::intersectsPolygon
bool intersectsPolygon(const Node *a, const Node *b)
Definition: mapbox_earcut.h:694
mapbox::detail::Earcut::ObjectPool::allocations
std::vector< T * > allocations
Definition: mapbox_earcut.h:143
mapbox
ISC License.
Definition: mapbox_earcut.h:28
mapbox::detail::Earcut::zOrder
int32_t zOrder(const double x_, const double y_)
Definition: mapbox_earcut.h:623
mapbox::detail::Earcut::ObjectPool::clear
void clear()
Definition: mapbox_earcut.h:138
mapbox::detail::Earcut::ObjectPool
Definition: mapbox_earcut.h:109
mapbox::util::nth
Definition: mapbox_earcut.h:32
mapbox::detail::Earcut::ObjectPool::~ObjectPool
~ObjectPool()
Definition: mapbox_earcut.h:115
mapbox::detail::Earcut::Node::prevZ
Node * prevZ
Definition: mapbox_earcut.h:70
mapbox::detail::Earcut::ObjectPool::blockSize
std::size_t blockSize
Definition: mapbox_earcut.h:142
mapbox::detail::Earcut::ObjectPool::currentIndex
std::size_t currentIndex
Definition: mapbox_earcut.h:141
mapbox::detail::Earcut::Node::steiner
bool steiner
Definition: mapbox_earcut.h:74
mapbox::detail::Earcut::hashing
bool hashing
Definition: mapbox_earcut.h:103
mapbox::detail::Earcut::maxY
double maxY
Definition: mapbox_earcut.h:105
mapbox::detail::Earcut::indexCurve
void indexCurve(Node *start)
Definition: mapbox_earcut.h:535
mapbox::detail::Earcut::indices
std::vector< N > indices
Definition: mapbox_earcut.h:44
mapbox::detail::Earcut::isEarHashed
bool isEarHashed(Node *ear)
Definition: mapbox_earcut.h:341