Skip to content

Commit

Permalink
Port bugfixes 2.2.4 (#102)
Browse files Browse the repository at this point in the history
* more microoptimizations

* one more microoptimization

* fix infinite loops, simplify hole elimination

Co-Authored-By: Juha Laukala <[email protected]>

* minor cleanup in findHoleBridge

Co-authored-by: Juha Laukala <[email protected]>
  • Loading branch information
kkaefer and JuhaLaukala authored Sep 6, 2022
1 parent 9124df4 commit 4811a2b
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 16 deletions.
25 changes: 9 additions & 16 deletions include/mapbox/earcut.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ void Earcut<N>::operator()(const Polygon& points) {
p = p->next;
} while (p != outerNode);

// minX, minY and size are later used to transform coords into integers for z-order calculation
// minX, minY and inv_size are later used to transform coords into integers for z-order calculation
inv_size = std::max<double>(maxX - minX, maxY - minY);
inv_size = inv_size != .0 ? (1. / inv_size) : .0;
inv_size = inv_size != .0 ? (32767. / inv_size) : .0;
}

earcutLinked(outerNode);
Expand Down Expand Up @@ -443,7 +443,6 @@ Earcut<N>::eliminateHoles(const Polygon& points, Node* outerNode) {
// process holes from left to right
for (size_t i = 0; i < queue.size(); i++) {
outerNode = eliminateHole(queue[i], outerNode);
outerNode = filterPoints(outerNode, outerNode->next);
}

return outerNode;
Expand All @@ -461,11 +460,10 @@ Earcut<N>::eliminateHole(Node* hole, Node* outerNode) {
Node* bridgeReverse = splitPolygon(bridge, hole);

// filter collinear points around the cuts
Node* filteredBridge = filterPoints(bridge, bridge->next);
filterPoints(bridgeReverse, bridgeReverse->next);

// Check if input node was removed by the filtering
return outerNode == bridge ? filteredBridge : outerNode;
return filterPoints(bridge, bridge->next);
}

// David Eberly's algorithm for finding a bridge between hole and outer polygon
Expand All @@ -485,20 +483,15 @@ Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y);
if (x <= hx && x > qx) {
qx = x;
if (x == hx) {
if (hy == p->y) return p;
if (hy == p->next->y) return p->next;
}
m = p->x < p->next->x ? p : p->next;
if (x == hx) return m; // hole touches outer segment; pick leftmost endpoint
}
}
p = p->next;
} while (p != outerNode);

if (!m) return 0;

if (hx == qx) return m; // hole touches outer segment; pick leftmost endpoint

// look for points inside the triangle of hole Vertex, segment intersection and endpoint;
// if there are no points found, we have a valid connection;
// otherwise choose the Vertex of the minimum angle with the ray as connection Vertex
Expand Down Expand Up @@ -628,8 +621,8 @@ Earcut<N>::sortLinked(Node* list) {
template <typename N>
int32_t Earcut<N>::zOrder(const double x_, const double y_) {
// coords are transformed into non-negative 15-bit integer range
int32_t x = static_cast<int32_t>(32767.0 * (x_ - minX) * inv_size);
int32_t y = static_cast<int32_t>(32767.0 * (y_ - minY) * inv_size);
int32_t x = static_cast<int32_t>((x_ - minX) * inv_size);
int32_t y = static_cast<int32_t>((y_ - minY) * inv_size);

x = (x | (x << 8)) & 0x00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F;
Expand Down Expand Up @@ -662,9 +655,9 @@ Earcut<N>::getLeftmost(Node* start) {
// check if a point lies within a convex triangle
template <typename N>
bool Earcut<N>::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;
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
(ax - px) * (by - py) >= (bx - px) * (ay - py) &&
(bx - px) * (cy - py) >= (cx - px) * (by - py);
}

// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
Expand Down
17 changes: 17 additions & 0 deletions test/fixtures/filtered_bridge_jhl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This file is auto-generated, manual changes will be lost if the code is regenerated.

#include "geometries.hpp"

namespace mapbox {
namespace fixtures {

static const Fixture<short> filtered_bridge_jhl("filtered_bridge_jhl", 25, 1e-14, 0.000001, {
{{22,14},{17,12},{5,12},{0,12},{0,0},{22,0}},
{{9,4},{10,4},{10,3},{9,3}},
{{6,9},{7,9},{7,8},{6,8}},
{{7,10},{17,10},{17,5},{8,5}},
{{13,4},{14,4},{14,3},{13,3}},
});

}
}
14 changes: 14 additions & 0 deletions test/fixtures/infinite_loop_jhl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// This file is auto-generated, manual changes will be lost if the code is regenerated.

#include "geometries.hpp"

namespace mapbox {
namespace fixtures {

static const Fixture<double> infinite_loop_jhl("infinite_loop_jhl", 0, 1e-14, Infinity, {
{{-1,2},{0,0},{2,-1}},
{{2,-1},{0,1e-28},{-1,2}},
});

}
}
14 changes: 14 additions & 0 deletions test/fixtures/issue142.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// This file is auto-generated, manual changes will be lost if the code is regenerated.

#include "geometries.hpp"

namespace mapbox {
namespace fixtures {

static const Fixture<double> issue142("issue142", 4, 0.12754968037146489, 8.53067013, {
{{5.62675358811389,31.94879819160804},{-16.369709114391867,28.341954255099814},{-10.786562672455382,-1.2779295357476745},{10.819423740334923,2.069348113719755}},
{{3.220439475288522,4.197526331591453},{5.024815373142793,1.1716264034331543},{10.819423740334923,2.069348113719755},{5.62675358811389,31.94879819160804},{-16.369709114391867,28.341954255099814},{-10.786562672455382,-1.2779295357476745},{-6.833718161055838,-0.6655405509524673},{-8.602352370111433,2.142874784407777},{-5.34630560403934,6.768689248602321},{-1.4053749889060216,7.453573097663546}},
});

}
}
14 changes: 14 additions & 0 deletions test/fixtures/issue149.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// This file is auto-generated, manual changes will be lost if the code is regenerated.

#include "geometries.hpp"

namespace mapbox {
namespace fixtures {

static const Fixture<short> issue149("issue149", 2, 1e-14, 0.000001, {
{{1888,5504},{1872,5504},{1872,5536},{1856,5536},{1856,5520},{1840,5520},{1840,5504},{1856,5504},{1856,5520},{1872,5520},{1872,5504},{1888,5504}},
{{1856,5520},{1856,5536},{1872,5536},{1872,5520}},
});

}
}

0 comments on commit 4811a2b

Please sign in to comment.