31template <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); };
40template <
typename N = u
int32_t>
46 template <
typename Polygon>
107 template <
typename T,
typename Alloc = std::allocator<T>>
117 template <
typename...
Args>
125 alloc_traits::construct(
alloc,
object, std::forward<Args>(
args)...);
149template <
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());
168 nodes.reset(len * 3 / 2);
169 indices.reserve(len +
points[0].size());
177 hashing = threshold < 0;
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);
193 inv_size = std::max<double>(maxX - minX, maxY - minY);
194 inv_size = inv_size != .0 ? (1. / inv_size) : .0;
203template <
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];
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)) {
244 if (!end) end = start;
255 if (p == p->
next)
break;
261 }
while (
again || p != end);
272 if (!pass && hashing) indexCurve(
ear);
279 while (
ear->prev !=
ear->next) {
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);
325 if (area(a, b, c) >= 0)
return false;
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;
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));
360 while (p && p->
z <=
maxZ) {
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) {
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;
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);
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);
435template <
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++) {
445 queue.push_back(getLeftmost(list));
453 for (
size_t i = 0; i <
queue.size(); i++) {
467 filterPoints(b, b->
next);
478 double qx = -std::numeric_limits<double>::infinity();
489 if (
hy == p->
y)
return p;
506 const Node* stop = m;
507 double tanMin = std::numeric_limits<double>::infinity();
515 if (
hx >= p->
x && p->
x >=
mx &&
hx != p->
x &&
539 p->
z = p->
z ? p->
z : zOrder(p->
x, p->
y);
543 }
while (p != start);
574 for (i = 0; i <
inSize; i++) {
588 }
else if (
qSize == 0 || !
q) {
592 }
else if (p->
z <=
q->z) {
602 if (tail) tail->
nextZ = e;
612 tail->
nextZ =
nullptr;
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;
650 }
while (p != start);
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);
673 return (
q->y - p->
y) * (
r->x -
q->x) - (
q->x - p->
x) * (
r->y -
q->y);
679 return p1->
x == p2->
x && p1->
y == p2->
y;
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);
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;
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;
717 double px = (a->
x + b->
x) / 2;
718 double py = (a->
y + b->
y) / 2;
735 Node*
a2 = nodes.construct(a->
i, a->
x, a->
y);
736 Node*
b2 = nodes.construct(b->
i, b->
x, b->
y);
756template <
typename N>
template <
typename Po
int>
785template <
typename N = u
int32_t,
typename Polygon>
789 return std::move(
earcut.indices);
T * construct(Args &&... args)
void reset(std::size_t newBlockSize)
typename std::allocator_traits< Alloc > alloc_traits
ObjectPool(std::size_t blockSize_)
std::vector< T * > allocations
bool isEarHashed(Node *ear)
Node * cureLocalIntersections(Node *start)
Node * eliminateHoles(const Polygon &points, Node *outerNode)
Node * splitPolygon(Node *a, Node *b)
bool middleInside(const Node *a, const Node *b)
double area(const Node *p, const Node *q, const Node *r) const
bool intersectsPolygon(const Node *a, const Node *b)
void eliminateHole(Node *hole, Node *outerNode)
void splitEarcut(Node *start)
Node * sortLinked(Node *list)
void indexCurve(Node *start)
bool isValidDiagonal(Node *a, Node *b)
bool pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const
bool locallyInside(const Node *a, const Node *b)
void operator()(const Polygon &points)
Node * findHoleBridge(Node *hole, Node *outerNode)
Node * getLeftmost(Node *start)
void earcutLinked(Node *ear, int pass=0)
Node * insertNode(std::size_t i, const Point &p, Node *last)
bool equals(const Node *p1, const Node *p2)
int32_t zOrder(const double x_, const double y_)
bool intersects(const Node *p1, const Node *q1, const Node *p2, const Node *q2)
Node * filterPoints(Node *start, Node *end=nullptr)
Node * linkedList(const Ring &points, const bool clockwise)
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
std::vector< N > earcut(const Polygon &poly)
Node(const Node &)=delete
Node & operator=(const Node &)=delete
Node & operator=(Node &&)=delete
Node(N index, double x_, double y_)
static std::tuple_element< I, T >::type get(const T &t)