diff --git a/include/earcut.hpp b/include/earcut.hpp index 8abfbf2..f4967cd 100644 --- a/include/earcut.hpp +++ b/include/earcut.hpp @@ -22,7 +22,7 @@ template struct nth { } -template +template class Earcut { public: std::vector indices; @@ -33,15 +33,15 @@ class Earcut { private: struct Node { - Node(N index, Coord x_, Coord y_) : i(index), x(x_), y(y_) {} + Node(N index, double x_, double y_) : i(index), x(x_), y(y_) {} Node(const Node&) = delete; Node& operator=(const Node&) = delete; Node(Node&&) = delete; Node& operator=(Node&&) = delete; const N i; - const Coord x; - const Coord y; + const double x; + const double y; // previous and next vertice nodes in a polygon ring Node* prev = nullptr; @@ -82,15 +82,15 @@ class Earcut { void removeNode(Node* p); bool hashing; - Coord minX, maxX; - Coord minY, maxY; + double minX, maxX; + double minY, maxY; double size; std::unique_ptr> nodes; }; -template template -void Earcut::operator()(const Polygon& points) { +template template +void Earcut::operator()(const Polygon& points) { // reset indices.clear(); vertices = 0; @@ -98,11 +98,11 @@ void Earcut::operator()(const Polygon& points) { if (points.empty()) return; - auto outerNode = filterPoints(linkedList(points[0], true)); + Node* outerNode = filterPoints(linkedList(points[0], true)); if (!outerNode) return; - Coord x; - Coord y; + double x; + double y; size = 0; int threshold = 80; @@ -136,10 +136,9 @@ void Earcut::operator()(const Polygon& points) { } // create a circular doubly linked list from polygon points in the specified winding order -template template -typename Earcut::Node* -Earcut::linkedList(const Ring& points, - const bool clockwise) { +template template +typename Earcut::Node* +Earcut::linkedList(const Ring& points, const bool clockwise) { using Point = typename Ring::value_type; double sum = 0; const int len = points.size(); @@ -151,10 +150,10 @@ Earcut::linkedList(const Ring& points, for (i = 0, j = len - 1; i < len; j = i++) { p1 = points[i]; p2 = points[j]; - const auto p20 = util::nth<0, Point>::get(p2); - const auto p10 = util::nth<0, Point>::get(p1); - const auto p11 = util::nth<1, Point>::get(p1); - const auto p21 = util::nth<1, Point>::get(p2); + const double p20 = util::nth<0, Point>::get(p2); + const double p10 = util::nth<0, Point>::get(p1); + const double p11 = util::nth<1, Point>::get(p1); + const double p21 = util::nth<1, Point>::get(p2); sum += (p20 - p10) * (p11 + p21); } @@ -171,12 +170,12 @@ Earcut::linkedList(const Ring& points, } // eliminate colinear or duplicate points -template -typename Earcut::Node* -Earcut::filterPoints(Node* start, Node* end) { +template +typename Earcut::Node* +Earcut::filterPoints(Node* start, Node* end) { if (!end) end = start; - auto p = start; + Node* p = start; bool again; do { again = false; @@ -198,8 +197,8 @@ Earcut::filterPoints(Node* start, Node* end) { } // main ear slicing loop which triangulates a polygon (given as a linked list) -template -void Earcut::earcutLinked(Node* ear, int pass) { +template +void Earcut::earcutLinked(Node* ear, int pass) { if (!ear) return; // interlink polygon nodes in z-order @@ -253,8 +252,8 @@ void Earcut::earcutLinked(Node* ear, int pass) { } // check whether a polygon node forms a valid ear with adjacent nodes -template -bool Earcut::isEar(Node* ear) { +template +bool Earcut::isEar(Node* ear) { const Node* a = ear->prev; const Node* b = ear; const Node* c = ear->next; @@ -262,7 +261,7 @@ bool Earcut::isEar(Node* ear) { if (area(a, b, c) >= 0) return false; // reflex, can't be an ear // now make sure we don't have other points inside the potential ear - auto p = ear->next->next; + Node* p = ear->next->next; while (p != ear->prev) { if (pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) && @@ -273,8 +272,8 @@ bool Earcut::isEar(Node* ear) { return true; } -template -bool Earcut::isEarHashed(Node* ear) { +template +bool Earcut::isEarHashed(Node* ear) { const Node* a = ear->prev; const Node* b = ear; const Node* c = ear->next; @@ -282,17 +281,17 @@ bool Earcut::isEarHashed(Node* ear) { if (area(a, b, c) >= 0) return false; // reflex, can't be an ear // triangle bbox; min & max are calculated like this for speed - auto const minTX = a->x < b->x ? (a->x < c->x ? a->x : c->x) : (b->x < c->x ? b->x : c->x); - auto const minTY = a->y < b->y ? (a->y < c->y ? a->y : c->y) : (b->y < c->y ? b->y : c->y); - auto const maxTX = a->x > b->x ? (a->x > c->x ? a->x : c->x) : (b->x > c->x ? b->x : c->x); - auto const maxTY = a->y > b->y ? (a->y > c->y ? a->y : c->y) : (b->y > c->y ? b->y : c->y); + const double minTX = a->x < b->x ? (a->x < c->x ? a->x : c->x) : (b->x < c->x ? b->x : c->x); + const double minTY = a->y < b->y ? (a->y < c->y ? a->y : c->y) : (b->y < c->y ? b->y : c->y); + const double maxTX = a->x > b->x ? (a->x > c->x ? a->x : c->x) : (b->x > c->x ? b->x : c->x); + const double maxTY = a->y > b->y ? (a->y > c->y ? a->y : c->y) : (b->y > c->y ? b->y : c->y); // z-order range for the current triangle bbox; - auto const minZ = zOrder(minTX, minTY); - auto const maxZ = zOrder(maxTX, maxTY); + const int32_t minZ = zOrder(minTX, minTY); + const int32_t maxZ = zOrder(maxTX, maxTY); // first look for points inside the triangle in increasing z-order - auto p = ear->nextZ; + Node* p = ear->nextZ; while (p && p->z <= maxZ) { if (p != ear->prev && p != ear->next && @@ -315,9 +314,9 @@ bool Earcut::isEarHashed(Node* ear) { } // go through all polygon nodes and cure small local self-intersections -template -typename Earcut::Node* -Earcut::cureLocalIntersections(Node* start) { +template +typename Earcut::Node* +Earcut::cureLocalIntersections(Node* start) { Node* p = start; do { Node* a = p->prev; @@ -342,8 +341,8 @@ Earcut::cureLocalIntersections(Node* start) { } // try splitting polygon into two and triangulate them independently -template -void Earcut::splitEarcut(Node* start) { +template +void Earcut::splitEarcut(Node* start) { // look for a valid diagonal that divides the polygon into two Node* a = start; do { @@ -351,7 +350,7 @@ void Earcut::splitEarcut(Node* start) { while (b != a->prev) { if (a->i != b->i && isValidDiagonal(a, b)) { // split the polygon in two by the diagonal - auto c = splitPolygon(a, b); + Node* c = splitPolygon(a, b); // filter colinear points around the cuts a = filterPoints(a, a->next); @@ -369,13 +368,14 @@ void Earcut::splitEarcut(Node* start) { } // link every hole into the outer loop, producing a single-ring polygon without holes -template template -typename Earcut::Node* -Earcut::eliminateHoles(const Polygon& points, Node* outerNode) {const auto len = points.size(); +template template +typename Earcut::Node* +Earcut::eliminateHoles(const Polygon& points, Node* outerNode) { + const size_t len = points.size(); std::vector queue; for (size_t i = 1; i < len; i++) { - auto list = filterPoints(linkedList(points[i], false)); + Node* list = filterPoints(linkedList(points[i], false)); if (list) { queue.push_back(getLeftmost(list)); } @@ -394,8 +394,8 @@ Earcut::eliminateHoles(const Polygon& points, Node* outerNode) {const } // find a bridge between vertices that connects hole with an outer ring and and link it -template -void Earcut::eliminateHole(Node* hole, Node* outerNode) { +template +void Earcut::eliminateHole(Node* hole, Node* outerNode) { outerNode = findHoleBridge(hole, outerNode); if (outerNode) { Node* b = splitPolygon(outerNode, hole); @@ -404,9 +404,9 @@ void Earcut::eliminateHole(Node* hole, Node* outerNode) { } // David Eberly's algorithm for finding a bridge between hole and outer polygon -template -typename Earcut::Node* -Earcut::findHoleBridge(Node* hole, Node* outerNode) { +template +typename Earcut::Node* +Earcut::findHoleBridge(Node* hole, Node* outerNode) { Node* p = outerNode; double hx = hole->x; double hy = hole->y; @@ -417,7 +417,7 @@ Earcut::findHoleBridge(Node* hole, Node* outerNode) { // segment's endpoint with lesser x will be potential connection Vertex do { if (hy <= p->y && hy >= p->next->y) { - auto x = double(p->x) + double(hy - p->y) * double(p->next->x - p->x) / double(p->next->y - p->y); + double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y); if (x <= hx && x > qx) { qx = x; m = p->x < p->next->x ? p : p->next; @@ -456,8 +456,8 @@ Earcut::findHoleBridge(Node* hole, Node* outerNode) { } // interlink polygon nodes in z-order -template -void Earcut::indexCurve(Node* start) { +template +void Earcut::indexCurve(Node* start) { Node* p = start; do { @@ -475,9 +475,9 @@ void Earcut::indexCurve(Node* start) { // Simon Tatham's linked list merge sort algorithm // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html -template -typename Earcut::Node* -Earcut::sortLinked(Node* list) { +template +typename Earcut::Node* +Earcut::sortLinked(Node* list) { Node* p; Node* q; Node* e; @@ -542,11 +542,11 @@ Earcut::sortLinked(Node* list) { } // z-order of a Vertex given coords and size of the data bounding box -template -int32_t Earcut::zOrder(const double x_, const double y_) { +template +int32_t Earcut::zOrder(const double x_, const double y_) { // coords are transformed into non-negative 15-bit integer range - int32_t x = 32767 * double(x_ - double(minX)) / size; - int32_t y = 32767 * double(y_ - double(minY)) / size; + int32_t x = 32767 * (x_ - minX) / size; + int32_t y = 32767 * (y_ - minY) / size; x = (x | (x << 8)) & 0x00FF00FF; x = (x | (x << 4)) & 0x0F0F0F0F; @@ -562,9 +562,9 @@ int32_t Earcut::zOrder(const double x_, const double y_) { } // find the leftmost node of a polygon ring -template -typename Earcut::Node* -Earcut::getLeftmost(Node* start) { +template +typename Earcut::Node* +Earcut::getLeftmost(Node* start) { Node* p = start; Node* leftmost = start; do { @@ -576,42 +576,42 @@ Earcut::getLeftmost(Node* start) { } // check if a point lies within a convex triangle -template -bool Earcut::pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const { +template +bool Earcut::pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const { return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; } // check if a diagonal between two polygon nodes is valid (lies in polygon interior) -template -bool Earcut::isValidDiagonal(Node* a, Node* b) { +template +bool Earcut::isValidDiagonal(Node* a, Node* b) { return equals(a, b) || (a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) && locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b)); } // signed area of a triangle -template -double Earcut::area(const Node* p, const Node* q, const Node* r) const { +template +double Earcut::area(const Node* p, const Node* q, const Node* r) const { return (q->y - p->y) * (r->x - q->x) - (q->x - p->x) * (r->y - q->y); } // check if two points are equal -template -bool Earcut::equals(const Node* p1, const Node* p2) { +template +bool Earcut::equals(const Node* p1, const Node* p2) { return p1->x == p2->x && p1->y == p2->y; } // check if two segments intersect -template -bool Earcut::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) { +template +bool Earcut::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) { return area(p1, q1, p2) > 0 != area(p1, q1, q2) > 0 && area(p2, q2, p1) > 0 != area(p2, q2, q1) > 0; } // check if a polygon diagonal intersects any polygon segments -template -bool Earcut::intersectsPolygon(const Node* a, const Node* b) { +template +bool Earcut::intersectsPolygon(const Node* a, const Node* b) { const Node* p = a; do { if (p->i != a->i && p->next->i != a->i && p->i != b->i && p->next->i != b->i && @@ -623,20 +623,20 @@ bool Earcut::intersectsPolygon(const Node* a, const Node* b) { } // check if a polygon diagonal is locally inside the polygon -template -bool Earcut::locallyInside(const Node* a, const Node* b) { +template +bool Earcut::locallyInside(const Node* a, const Node* b) { return area(a->prev, a, a->next) < 0 ? area(a, b, a->next) >= 0 && area(a, a->prev, b) >= 0 : area(a, b, a->prev) < 0 || area(a, a->next, b) < 0; } // check if the middle Vertex of a polygon diagonal is inside the polygon -template -bool Earcut::middleInside(const Node* a, const Node* b) { +template +bool Earcut::middleInside(const Node* a, const Node* b) { const Node* p = a; bool inside = false; - auto px = double(a->x + b->x) / 2; - auto py = double(a->y + b->y) / 2; + double px = (a->x + b->x) / 2; + double py = (a->y + b->y) / 2; do { if (((p->y > py) != (p->next->y > py)) && (px < (p->next->x - p->x) * (py - p->y) / (p->next->y - p->y) + p->x)) inside = !inside; @@ -649,13 +649,13 @@ bool Earcut::middleInside(const Node* a, const Node* b) { // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits // polygon into two; if one belongs to the outer ring and another to a hole, it merges it into a // single ring -template -typename Earcut::Node* -Earcut::splitPolygon(Node* a, Node* b) { - const auto a2 = new (nodes->malloc()) Node(a->i, a->x, a->y); - const auto b2 = new (nodes->malloc()) Node(b->i, b->x, b->y); - const auto an = a->next; - const auto bp = b->prev; +template +typename Earcut::Node* +Earcut::splitPolygon(Node* a, Node* b) { + Node* a2 = new (nodes->malloc()) Node(a->i, a->x, a->y); + Node* b2 = new (nodes->malloc()) Node(b->i, b->x, b->y); + Node* an = a->next; + Node* bp = b->prev; a->next = b; b->prev = a; @@ -673,10 +673,10 @@ Earcut::splitPolygon(Node* a, Node* b) { } // create a node and util::optionally link it with previous one (in a circular doubly linked list) -template template -typename Earcut::Node* -Earcut::insertNode(N i, const Point& pt, Node* last) { - auto p = new (nodes->malloc()) Node(i, +template template +typename Earcut::Node* +Earcut::insertNode(N i, const Point& pt, Node* last) { + Node* p = new (nodes->malloc()) Node(i, util::nth<0, Point>::get(pt), util::nth<1, Point>::get(pt)); @@ -694,8 +694,8 @@ Earcut::insertNode(N i, const Point& pt, Node* last) { return p; } -template -void Earcut::removeNode(Node* p) { +template +void Earcut::removeNode(Node* p) { p->next->prev = p->prev; p->prev->next = p->next;