Skip to content

Commit

Permalink
fix steiner points, better tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mourner committed May 11, 2015
1 parent a169519 commit 68da53f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 24 deletions.
17 changes: 10 additions & 7 deletions src/earcut.js
Expand Up @@ -65,14 +65,12 @@ function linkedList(data, start, end, dim, clockwise) {
function filterPoints(data, start, end) {
if (!end) end = start;

if (start.next === start) return start;

var node = start,
again;
do {
again = false;

if (equals(data, node.i, node.next.i) || orient(data, node.prev.i, node.i, node.next.i) === 0) {
if (!node.steiner && (equals(data, node.i, node.next.i) || orient(data, node.prev.i, node.i, node.next.i) === 0)) {

// remove node
node.prev.next = node.next;
Expand Down Expand Up @@ -326,7 +324,9 @@ function eliminateHoles(data, holeIndices, outerNode, dim) {
for (i = 0, len = holeIndices.length; i < len; i++) {
start = holeIndices[i] * dim;
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
list = filterPoints(data, linkedList(data, start, end, dim, false));
list = linkedList(data, start, end, dim, false);
if (list === list.next) list.steiner = true;
list = filterPoints(data, list);
if (list) queue.push(getLeftmost(data, list));
}

Expand All @@ -336,19 +336,19 @@ function eliminateHoles(data, holeIndices, outerNode, dim) {

// process holes from left to right
for (i = 0; i < queue.length; i++) {
eliminateHole(data, queue[i], outerNode, queue[i] === queue[i].next);
eliminateHole(data, queue[i], outerNode);
outerNode = filterPoints(data, outerNode, outerNode.next);
}

return outerNode;
}

// find a bridge between vertices that connects hole with an outer ring and and link it
function eliminateHole(data, holeNode, outerNode, isSteinerPoint) {
function eliminateHole(data, holeNode, outerNode) {
outerNode = findHoleBridge(data, holeNode, outerNode);
if (outerNode) {
var b = splitPolygon(outerNode, holeNode);
if (!isSteinerPoint) filterPoints(data, b, b.next);
filterPoints(data, b, b.next);
}
}

Expand Down Expand Up @@ -656,4 +656,7 @@ function Node(i) {
// previous and next nodes in z-order
this.prevZ = null;
this.nextZ = null;

// indicates whether this is a steiner point
this.steiner = false;
}
7 changes: 7 additions & 0 deletions test/fixtures/steiner.json
@@ -0,0 +1,7 @@
[
[[0,0],[100,0],[100,100],[0,100]],
[[50,50]],
[[30,40]],
[[70,60]],
[[20,70]]
]
38 changes: 21 additions & 17 deletions test/test.js
Expand Up @@ -5,20 +5,21 @@ var test = require('tape'),
fs = require('fs'),
path = require('path');

areaTest('building');
areaTest('dude');
areaTest('water', 0.0019);
areaTest('water2');
areaTest('water3');
areaTest('water3b');
areaTest('water4');
areaTest('water-huge', 0.0015);
areaTest('water-huge2', 0.0020);
areaTest('degenerate');
areaTest('bad-hole', 0.0420);
areaTest('empty-square');
areaTest('issue16');
areaTest('issue17');
areaTest('building', 12);
areaTest('dude', 106);
areaTest('water', 2482, 0.0019);
areaTest('water2', 1211);
areaTest('water3', 197);
areaTest('water3b', 25);
areaTest('water4', 705);
areaTest('water-huge', 5162, 0.0015);
areaTest('water-huge2', 4456, 0.0020);
areaTest('degenerate', 0);
areaTest('bad-hole', 34, 0.0420);
areaTest('empty-square', 0);
areaTest('issue16', 12);
areaTest('issue17', 11);
areaTest('steiner', 9);

test('indices-2d', function (t) {
var indices = earcut([10, 0, 0, 50, 60, 60, 70, 10]);
Expand All @@ -32,13 +33,11 @@ test('indices-3d', function (t) {
t.end();
});

function areaTest(filename, expectedDeviation) {
function areaTest(filename, expectedTriangles, expectedDeviation) {
expectedDeviation = expectedDeviation || 1e-14;

test(filename, function (t) {

console.log(filename);

var data = JSON.parse(fs.readFileSync(path.join(__dirname, '/fixtures/' + filename + '.json'))),
data2 = flattenData(data),
vertices = data2.vertices,
Expand All @@ -60,6 +59,11 @@ function areaTest(filename, expectedDeviation) {
t.ok(deviation < expectedDeviation,
'deviation ' + formatPercent(deviation) + ' is less than ' + formatPercent(expectedDeviation));

if (expectedTriangles) {
t.ok(indices.length / 3 === expectedTriangles, (indices.length / 3) + ' triangles when expected ' +
expectedTriangles);
}

t.end();
});
}
Expand Down

0 comments on commit 68da53f

Please sign in to comment.