Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions src/earcut.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ function earcut(points) {

if (points.length > 1) outerNode = eliminateHoles(points, outerNode);

var triangles = [];
if (outerNode) earcutLinked(outerNode, triangles, minX, minY, size);
var result = {vertices: [], indices: []};
if (outerNode) earcutLinked(outerNode, result, minX, minY, size);

return triangles;
return result;
}

// create a circular doubly linked list from polygon points in the specified winding order
Expand Down Expand Up @@ -89,7 +89,7 @@ function filterPoints(start) {
return start;
}

function earcutLinked(ear, triangles, minX, minY, size, secondPass) {
function earcutLinked(ear, result, minX, minY, size, secondPass) {
ear = filterPoints(ear);
if (!ear) return;

Expand All @@ -104,7 +104,9 @@ function earcutLinked(ear, triangles, minX, minY, size, secondPass) {
next = ear.next;

if (isEar(ear, minX, minY, size)) {
triangles.push(prev.p, ear.p, next.p);
addVertex(result, prev);
addVertex(result, ear);
addVertex(result, next);

next.prev = prev;
prev.next = next;
Expand All @@ -122,14 +124,25 @@ function earcutLinked(ear, triangles, minX, minY, size, secondPass) {

if (ear === stop) {
// if we can't find any more ears, try filtering points and cutting again
if (!secondPass) earcutLinked(ear, triangles, minX, minY, size, true);
if (!secondPass) earcutLinked(ear, result, minX, minY, size, true);
// if this didn't work, try splitting the remaining polygon into two
else splitEarcut(ear, triangles, minX, minY, size);
else splitEarcut(ear, result, minX, minY, size);
break;
}
}
}

function addVertex(result, node) {
node = node.source || node;
var i = node.index;
if (i === null) {
var vertices = result.vertices;
node.index = i = vertices.length;
vertices.push(node.p[0], node.p[1]);
}
result.indices.push(i);
}

function isEar(ear, minX, minY, size) {

var a = ear.prev.p,
Expand Down Expand Up @@ -234,7 +247,7 @@ function isEar(ear, minX, minY, size) {
return true;
}

function splitEarcut(start, triangles, minX, minY, size) {
function splitEarcut(start, result, minX, minY, size) {
// find a valid diagonal that divides the polygon into two
var a = start;
do {
Expand All @@ -245,8 +258,8 @@ function splitEarcut(start, triangles, minX, minY, size) {
var c = splitPolygon(a, b);

// run earcut on each half
earcutLinked(a, triangles, minX, minY, size);
earcutLinked(c, triangles, minX, minY, size);
earcutLinked(a, result, minX, minY, size);
earcutLinked(c, result, minX, minY, size);
return;
}
b = b.next;
Expand Down Expand Up @@ -535,6 +548,9 @@ function splitPolygon(a, b) {
an = a.next,
bp = b.prev;

a2.source = a;
b2.source = b;

a.next = b;
b.prev = a;

Expand Down Expand Up @@ -574,4 +590,7 @@ function Node(p) {
this.z = null;
this.prevZ = null;
this.nextZ = null;

this.source = null;
this.index = null;
}
11 changes: 8 additions & 3 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@ function areaTest(filename, expectedDeviation) {
test(filename, function (t) {

var data = JSON.parse(fs.readFileSync(__dirname + '/fixtures/' + filename + '.json')),
triangles = earcut(data),
result = earcut(data),
vertices = result.vertices,
indices = result.indices,
expectedArea = polygonArea(data),
area = 0;

for (var i = 0; i < triangles.length; i += 3) {
area += triangleArea(triangles[i], triangles[i + 1], triangles[i + 2]);
for (var i = 0; i < indices.length; i += 3) {
area += triangleArea(
[vertices[indices[i]], vertices[indices[i] + 1]],
[vertices[indices[i + 1]], vertices[indices[i + 1] + 1]],
[vertices[indices[i + 2]], vertices[indices[i + 2] + 1]]);
}

var deviation = expectedArea === 0 && area === 0 ? 0 : Math.abs(area - expectedArea) / expectedArea;
Expand Down
8 changes: 7 additions & 1 deletion viz/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,16 @@

console.time('earcut');
// for (var i = 0; i < 1000; i++) {
var triangles = earcut(testPoints);
var result = earcut(testPoints);
// }
console.timeEnd('earcut');

var triangles = [];
for (var i = 0; i < result.indices.length; i++) {
var index = result.indices[i];
triangles.push([result.vertices[index], result.vertices[index + 1]]);
}

ctx.lineJoin = 'round';

for (var i = 0; triangles && i < triangles.length; i += 3) {
Expand Down