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