From 1d0b47dc3d0e83ac89f3ff352981623def2072a0 Mon Sep 17 00:00:00 2001 From: finscn Date: Thu, 15 Dec 2016 21:52:05 +0800 Subject: [PATCH] Don't filter points belong to different polygons To fix https://github.com/mapbox/earcut/issues/74 Because the algorithm has been changed , the `expectedTriangles` & `expectedDeviation` in the test cases will have to changed. So the current test case will not valid for this PR. --- src/earcut.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/earcut.js b/src/earcut.js index b605478..f6ead3b 100644 --- a/src/earcut.js +++ b/src/earcut.js @@ -40,19 +40,26 @@ function earcut(data, holeIndices, dim) { return triangles; } -// create a circular doubly linked list from polygon points in the specified winding order -function linkedList(data, start, end, dim, clockwise) { +// Create a circular doubly linked list from polygon points in the specified winding order. +// parentId is used to identify which polygons(holes)the points belong to. +function linkedList(data, start, end, dim, clockwise, parentId) { var i, last; if (clockwise === (signedArea(data, start, end, dim) > 0)) { - for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); + for (i = start; i < end; i += dim) { + last = insertNode(i, data[i], data[i + 1], last); + last.parentId = parentId; + } } else { - for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); + for (i = end - dim; i >= start; i -= dim) { + last = insertNode(i, data[i], data[i + 1], last); + last.parentId = parentId; + } } - if (last && equals(last, last.next)) { removeNode(last); last = last.next; + last.parentId = parentId; } return last; @@ -68,7 +75,14 @@ function filterPoints(start, end) { do { again = false; - if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { + // Don't remove p , if `p.prev, p & p.next` don't belong to the same polygon(hole). + var toRemove = false; + if (area(p.prev, p, p.next) === 0) { + if (p.prev.parentId === p.parentId && p.next.parentId === p.parentId && p.prev.parentId === p.next.parentId) { + toRemove = true; + } + } + if (!p.steiner && equals(p, p.next) || toRemove) { removeNode(p); p = end = p.prev; if (p === p.next) return null; @@ -254,7 +268,7 @@ 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 = linkedList(data, start, end, dim, false); + list = linkedList(data, start, end, dim, false, 'hole-' + i); if (list === list.next) list.steiner = true; queue.push(getLeftmost(list)); } @@ -524,6 +538,9 @@ function splitPolygon(a, b) { an = a.next, bp = b.prev; + a2.parentId = a.parentId; + b2.parentId = b.parentId; + a.next = b; b.prev = a;