Skip to content

Commit 4811a2b

Browse files
kkaeferJuhaLaukala
andauthored
Port bugfixes 2.2.4 (#102)
* more microoptimizations * one more microoptimization * fix infinite loops, simplify hole elimination Co-Authored-By: Juha Laukala <104564021+JuhaLaukala@users.noreply.github.com> * minor cleanup in findHoleBridge Co-authored-by: Juha Laukala <104564021+JuhaLaukala@users.noreply.github.com>
1 parent 9124df4 commit 4811a2b

File tree

5 files changed

+68
-16
lines changed

5 files changed

+68
-16
lines changed

include/mapbox/earcut.hpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ void Earcut<N>::operator()(const Polygon& points) {
177177
p = p->next;
178178
} while (p != outerNode);
179179

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

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

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

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

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

471469
// David Eberly's algorithm for finding a bridge between hole and outer polygon
@@ -485,20 +483,15 @@ Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
485483
double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y);
486484
if (x <= hx && x > qx) {
487485
qx = x;
488-
if (x == hx) {
489-
if (hy == p->y) return p;
490-
if (hy == p->next->y) return p->next;
491-
}
492486
m = p->x < p->next->x ? p : p->next;
487+
if (x == hx) return m; // hole touches outer segment; pick leftmost endpoint
493488
}
494489
}
495490
p = p->next;
496491
} while (p != outerNode);
497492

498493
if (!m) return 0;
499494

500-
if (hx == qx) return m; // hole touches outer segment; pick leftmost endpoint
501-
502495
// look for points inside the triangle of hole Vertex, segment intersection and endpoint;
503496
// if there are no points found, we have a valid connection;
504497
// otherwise choose the Vertex of the minimum angle with the ray as connection Vertex
@@ -628,8 +621,8 @@ Earcut<N>::sortLinked(Node* list) {
628621
template <typename N>
629622
int32_t Earcut<N>::zOrder(const double x_, const double y_) {
630623
// coords are transformed into non-negative 15-bit integer range
631-
int32_t x = static_cast<int32_t>(32767.0 * (x_ - minX) * inv_size);
632-
int32_t y = static_cast<int32_t>(32767.0 * (y_ - minY) * inv_size);
624+
int32_t x = static_cast<int32_t>((x_ - minX) * inv_size);
625+
int32_t y = static_cast<int32_t>((y_ - minY) * inv_size);
633626

634627
x = (x | (x << 8)) & 0x00FF00FF;
635628
x = (x | (x << 4)) & 0x0F0F0F0F;
@@ -662,9 +655,9 @@ Earcut<N>::getLeftmost(Node* start) {
662655
// check if a point lies within a convex triangle
663656
template <typename N>
664657
bool Earcut<N>::pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const {
665-
return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
666-
(ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
667-
(bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
658+
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
659+
(ax - px) * (by - py) >= (bx - px) * (ay - py) &&
660+
(bx - px) * (cy - py) >= (cx - px) * (by - py);
668661
}
669662

670663
// check if a diagonal between two polygon nodes is valid (lies in polygon interior)

test/fixtures/filtered_bridge_jhl.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// This file is auto-generated, manual changes will be lost if the code is regenerated.
2+
3+
#include "geometries.hpp"
4+
5+
namespace mapbox {
6+
namespace fixtures {
7+
8+
static const Fixture<short> filtered_bridge_jhl("filtered_bridge_jhl", 25, 1e-14, 0.000001, {
9+
{{22,14},{17,12},{5,12},{0,12},{0,0},{22,0}},
10+
{{9,4},{10,4},{10,3},{9,3}},
11+
{{6,9},{7,9},{7,8},{6,8}},
12+
{{7,10},{17,10},{17,5},{8,5}},
13+
{{13,4},{14,4},{14,3},{13,3}},
14+
});
15+
16+
}
17+
}

test/fixtures/infinite_loop_jhl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// This file is auto-generated, manual changes will be lost if the code is regenerated.
2+
3+
#include "geometries.hpp"
4+
5+
namespace mapbox {
6+
namespace fixtures {
7+
8+
static const Fixture<double> infinite_loop_jhl("infinite_loop_jhl", 0, 1e-14, Infinity, {
9+
{{-1,2},{0,0},{2,-1}},
10+
{{2,-1},{0,1e-28},{-1,2}},
11+
});
12+
13+
}
14+
}

test/fixtures/issue142.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// This file is auto-generated, manual changes will be lost if the code is regenerated.
2+
3+
#include "geometries.hpp"
4+
5+
namespace mapbox {
6+
namespace fixtures {
7+
8+
static const Fixture<double> issue142("issue142", 4, 0.12754968037146489, 8.53067013, {
9+
{{5.62675358811389,31.94879819160804},{-16.369709114391867,28.341954255099814},{-10.786562672455382,-1.2779295357476745},{10.819423740334923,2.069348113719755}},
10+
{{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}},
11+
});
12+
13+
}
14+
}

test/fixtures/issue149.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// This file is auto-generated, manual changes will be lost if the code is regenerated.
2+
3+
#include "geometries.hpp"
4+
5+
namespace mapbox {
6+
namespace fixtures {
7+
8+
static const Fixture<short> issue149("issue149", 2, 1e-14, 0.000001, {
9+
{{1888,5504},{1872,5504},{1872,5536},{1856,5536},{1856,5520},{1840,5520},{1840,5504},{1856,5504},{1856,5520},{1872,5520},{1872,5504},{1888,5504}},
10+
{{1856,5520},{1856,5536},{1872,5536},{1872,5520}},
11+
});
12+
13+
}
14+
}

0 commit comments

Comments
 (0)