31 template <std::
size_t I,
typename T>
struct nth {
33 get(
const T& t) {
return std::get<I>(t); };
40 template <
typename N = u
int32_t>
46 template <
typename Polygon>
51 Node(N index,
double x_,
double y_) :
i(index),
x(x_),
y(y_) {}
76 template <
typename Ring>
Node*
linkedList(
const Ring& points,
const bool clockwise);
88 int32_t
zOrder(
const double x_,
const double y_);
90 bool pointInTriangle(
double ax,
double ay,
double bx,
double by,
double cx,
double cy,
double px,
double py)
const;
107 template <
typename T,
typename Alloc = std::allocator<T>>
117 template <
typename... Args>
125 alloc_traits::construct(
alloc,
object, std::forward<Args>(args)...);
128 void reset(std::size_t newBlockSize) {
133 blockSize = std::max<std::size_t>(1, newBlockSize);
149 template <
typename N>
template <
typename Polygon>
155 if (points.empty())
return;
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();
168 nodes.reset(len * 3 / 2);
169 indices.reserve(len + points[0].size());
171 Node* outerNode = linkedList(points[0],
true);
172 if (!outerNode || outerNode->
prev == outerNode->
next)
return;
174 if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
177 hashing = threshold < 0;
180 minX = maxX = outerNode->
x;
181 minY = maxY = outerNode->
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);
190 }
while (p != outerNode);
193 inv_size = std::max<double>(maxX - minX, maxY - minY);
194 inv_size = inv_size != .0 ? (1. / inv_size) : .0;
197 earcutLinked(outerNode);
203 template <
typename N>
template <
typename Ring>
206 using Point =
typename Ring::value_type;
208 const std::size_t len = points.size();
210 Node* last =
nullptr;
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];
220 sum += (p20 - p10) * (p11 + p21);
224 if (clockwise == (sum > 0)) {
225 for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last);
227 for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last);
230 if (last && equals(last, last->
next)) {
241 template <
typename N>
255 if (p == p->
next)
break;
261 }
while (again || p !=
end);
267 template <
typename N>
272 if (!pass && hashing) indexCurve(ear);
283 if (hashing ? isEarHashed(ear) : isEar(ear)) {
285 indices.emplace_back(prev->
i);
286 indices.emplace_back(ear->
i);
287 indices.emplace_back(next->
i);
303 if (!pass) earcutLinked(filterPoints(ear), 1);
306 else if (pass == 1) {
307 ear = cureLocalIntersections(ear);
308 earcutLinked(ear, 2);
311 }
else if (pass == 2) splitEarcut(ear);
319 template <
typename N>
325 if (area(a, b, c) >= 0)
return false;
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;
339 template <
typename N>
345 if (area(a, b, c) >= 0)
return false;
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));
354 const int32_t minZ = zOrder(minTX, minTY);
355 const int32_t maxZ = zOrder(maxTX, maxTY);
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;
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;
381 template <
typename N>
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);
402 }
while (p != start);
408 template <
typename N>
414 while (b != a->
prev) {
415 if (a->
i != b->
i && isValidDiagonal(a, b)) {
417 Node* c = splitPolygon(a, b);
420 a = filterPoints(a, a->
next);
421 c = filterPoints(c, c->
next);
431 }
while (a != start);
435 template <
typename N>
template <
typename Polygon>
438 const size_t len = points.size();
440 std::vector<Node*> queue;
441 for (
size_t i = 1; i < len; i++) {
442 Node* list = linkedList(points[i],
false);
445 queue.push_back(getLeftmost(list));
453 for (
size_t i = 0; i < queue.size(); i++) {
454 eliminateHole(queue[i], outerNode);
455 outerNode = filterPoints(outerNode, outerNode->
next);
462 template <
typename N>
464 outerNode = findHoleBridge(hole, outerNode);
466 Node* b = splitPolygon(outerNode, hole);
467 filterPoints(b, b->
next);
472 template <
typename N>
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) {
489 if (hy == p->
y)
return p;
496 }
while (p != outerNode);
500 if (hx == qx)
return m->
prev;
506 const Node* stop = m;
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)) {
518 tanCur = std::abs(hy - p->
y) / (hx - p->
x);
520 if ((tanCur < tanMin || (tanCur == tanMin && p->
x > m->
x)) && locallyInside(p, hole)) {
533 template <
typename N>
539 p->
z = p->
z ? p->
z : zOrder(p->
x, p->
y);
543 }
while (p != start);
553 template <
typename N>
561 int i, numMerges, pSize, qSize;
574 for (i = 0; i < inSize; i++) {
582 while (pSize > 0 || (qSize > 0 && q)) {
588 }
else if (qSize == 0 || !q) {
592 }
else if (p->
z <= q->
z) {
602 if (tail) tail->
nextZ = e;
612 tail->
nextZ =
nullptr;
614 if (numMerges <= 1)
return list;
621 template <
typename N>
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);
627 x = (x | (x << 8)) & 0x00FF00FF;
628 x = (x | (x << 4)) & 0x0F0F0F0F;
629 x = (x | (x << 2)) & 0x33333333;
630 x = (x | (x << 1)) & 0x55555555;
632 y = (y | (y << 8)) & 0x00FF00FF;
633 y = (y | (y << 4)) & 0x0F0F0F0F;
634 y = (y | (y << 2)) & 0x33333333;
635 y = (y | (y << 1)) & 0x55555555;
641 template <
typename N>
645 Node* leftmost = start;
647 if (p->
x < leftmost->
x || (p->
x == leftmost->
x && p->
y < leftmost->
y))
650 }
while (p != start);
656 template <
typename N>
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;
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);
671 template <
typename N>
673 return (q->
y - p->
y) * (
r->x - q->
x) - (q->
x - p->
x) * (
r->y - q->
y);
677 template <
typename N>
679 return p1->
x == p2->
x && p1->
y == p2->
y;
683 template <
typename N>
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);
692 template <
typename N>
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;
705 template <
typename N>
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;
713 template <
typename N>
717 double px = (a->
x + b->
x) / 2;
718 double py = (a->
y + b->
y) / 2;
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))
732 template <
typename N>
735 Node* a2 = nodes.construct(a->
i, a->
x, a->
y);
736 Node* b2 = nodes.construct(b->
i, b->
x, b->
y);
756 template <
typename N>
template <
typename Po
int>
775 template <
typename N>
785 template <
typename N = u
int32_t,
typename Polygon>
786 std::vector<N>
earcut(
const Polygon& poly) {