27 #pragma GCC visibility push(default)
32 template <std::
size_t I,
typename T>
struct nth {
34 get(
const T& t) {
return std::get<I>(t); };
41 template <
typename N = u
int32_t>
47 template <
typename Polygon>
52 Node(N index,
double x_,
double y_) :
i(index),
x(x_),
y(y_) {}
77 template <
typename Ring>
Node*
linkedList(
const Ring& points,
const bool clockwise);
89 int32_t
zOrder(
const double x_,
const double y_);
91 bool pointInTriangle(
double ax,
double ay,
double bx,
double by,
double cx,
double cy,
double px,
double py)
const;
100 template <
typename Po
int>
Node*
insertNode(std::size_t i,
const Point& p,
Node* last);
108 template <
typename T,
typename Alloc = std::allocator<T>>
118 template <
typename... Args>
126 alloc_traits::construct(
alloc,
object, std::forward<Args>(args)...);
129 void reset(std::size_t newBlockSize) {
134 blockSize = std::max<std::size_t>(1, newBlockSize);
150 template <
typename N>
template <
typename Polygon>
156 if (points.empty())
return;
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();
169 nodes.reset(len * 3 / 2);
170 indices.reserve(len + points[0].size());
172 Node* outerNode = linkedList(points[0],
true);
173 if (!outerNode || outerNode->
prev == outerNode->
next)
return;
175 if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
178 hashing = threshold < 0;
181 minX = maxX = outerNode->
x;
182 minY = maxY = outerNode->
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);
191 }
while (p != outerNode);
194 inv_size = std::max<double>(maxX - minX, maxY - minY);
195 inv_size = inv_size != .0 ? (1. / inv_size) : .0;
198 earcutLinked(outerNode);
204 template <
typename N>
template <
typename Ring>
207 using Point =
typename Ring::value_type;
209 const std::size_t len = points.size();
211 Node* last =
nullptr;
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];
221 sum += (p20 - p10) * (p11 + p21);
225 if (clockwise == (sum > 0)) {
226 for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last);
228 for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last);
231 if (last && equals(last, last->
next)) {
242 template <
typename N>
256 if (p == p->
next)
break;
262 }
while (again || p !=
end);
268 template <
typename N>
273 if (!pass && hashing) indexCurve(ear);
284 if (hashing ? isEarHashed(ear) : isEar(ear)) {
286 indices.emplace_back(prev->
i);
287 indices.emplace_back(ear->
i);
288 indices.emplace_back(next->
i);
304 if (!pass) earcutLinked(filterPoints(ear), 1);
307 else if (pass == 1) {
308 ear = cureLocalIntersections(ear);
309 earcutLinked(ear, 2);
312 }
else if (pass == 2) splitEarcut(ear);
320 template <
typename N>
326 if (area(a, b, c) >= 0)
return false;
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;
340 template <
typename N>
346 if (area(a, b, c) >= 0)
return false;
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));
355 const int32_t minZ = zOrder(minTX, minTY);
356 const int32_t maxZ = zOrder(maxTX, maxTY);
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;
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;
382 template <
typename N>
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);
403 }
while (p != start);
409 template <
typename N>
415 while (b != a->
prev) {
416 if (a->
i != b->
i && isValidDiagonal(a, b)) {
418 Node* c = splitPolygon(a, b);
421 a = filterPoints(a, a->
next);
422 c = filterPoints(c, c->
next);
432 }
while (a != start);
436 template <
typename N>
template <
typename Polygon>
439 const size_t len = points.size();
441 std::vector<Node*> queue;
442 for (
size_t i = 1; i < len; i++) {
443 Node* list = linkedList(points[i],
false);
446 queue.push_back(getLeftmost(list));
454 for (
size_t i = 0; i < queue.size(); i++) {
455 eliminateHole(queue[i], outerNode);
456 outerNode = filterPoints(outerNode, outerNode->
next);
463 template <
typename N>
465 outerNode = findHoleBridge(hole, outerNode);
467 Node* b = splitPolygon(outerNode, hole);
468 filterPoints(b, b->
next);
473 template <
typename N>
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) {
490 if (hy == p->
y)
return p;
497 }
while (p != outerNode);
501 if (hx == qx)
return m->
prev;
507 const Node* stop = m;
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)) {
519 tanCur = std::abs(hy - p->
y) / (hx - p->
x);
521 if ((tanCur < tanMin || (tanCur == tanMin && p->
x > m->
x)) && locallyInside(p, hole)) {
534 template <
typename N>
540 p->
z = p->
z ? p->
z : zOrder(p->
x, p->
y);
544 }
while (p != start);
554 template <
typename N>
562 int i, numMerges, pSize, qSize;
575 for (i = 0; i < inSize; i++) {
583 while (pSize > 0 || (qSize > 0 && q)) {
589 }
else if (qSize == 0 || !q) {
593 }
else if (p->
z <= q->
z) {
603 if (tail) tail->
nextZ = e;
613 tail->
nextZ =
nullptr;
615 if (numMerges <= 1)
return list;
622 template <
typename N>
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);
628 x = (x | (x << 8)) & 0x00FF00FF;
629 x = (x | (x << 4)) & 0x0F0F0F0F;
630 x = (x | (x << 2)) & 0x33333333;
631 x = (x | (x << 1)) & 0x55555555;
633 y = (y | (y << 8)) & 0x00FF00FF;
634 y = (y | (y << 4)) & 0x0F0F0F0F;
635 y = (y | (y << 2)) & 0x33333333;
636 y = (y | (y << 1)) & 0x55555555;
642 template <
typename N>
646 Node* leftmost = start;
648 if (p->
x < leftmost->
x || (p->
x == leftmost->
x && p->
y < leftmost->
y))
651 }
while (p != start);
657 template <
typename N>
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;
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);
672 template <
typename N>
674 return (q->
y - p->
y) * (
r->x - q->
x) - (q->
x - p->
x) * (
r->y - q->
y);
678 template <
typename N>
680 return p1->
x == p2->
x && p1->
y == p2->
y;
684 template <
typename N>
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);
693 template <
typename N>
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;
706 template <
typename N>
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;
714 template <
typename N>
718 double px = (a->
x + b->
x) / 2;
719 double py = (a->
y + b->
y) / 2;
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))
733 template <
typename N>
736 Node* a2 = nodes.construct(a->
i, a->
x, a->
y);
737 Node* b2 = nodes.construct(b->
i, b->
x, b->
y);
757 template <
typename N>
template <
typename Po
int>
776 template <
typename N>
786 template <
typename N = u
int32_t,
typename Polygon>
787 std::vector<N>
earcut(
const Polygon& poly) {
793 #pragma GCC visibility pop