From c3c128bab642658195942fdc6d0942540140a2b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Sat, 11 Mar 2023 20:32:26 +0100 Subject: [PATCH] Fix broken polygon (#140) Co-authored-by: Mike Bostock --- src/voronoi.js | 24 ++++++++++++++---------- test/voronoi-test.js | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/voronoi.js b/src/voronoi.js index 200394d..8811bfe 100644 --- a/src/voronoi.js +++ b/src/voronoi.js @@ -193,9 +193,9 @@ export default class Voronoi { if (points === null) return null; const {vectors: V} = this; const v = i * 4; - return V[v] || V[v + 1] + return this._simplify(V[v] || V[v + 1] ? this._clipInfinite(i, points, V[v], V[v + 1], V[v + 2], V[v + 3]) - : this._clipFinite(i, points); + : this._clipFinite(i, points)); } _clipFinite(i, points) { const n = points.length; @@ -286,14 +286,6 @@ export default class Voronoi { P.splice(j, 0, x, y), j += 2; } } - if (P.length > 4) { - for (let i = 0; i < P.length; i+= 2) { - const j = (i + 2) % P.length, k = (i + 4) % P.length; - if (P[i] === P[j] && P[j] === P[k] - || P[i + 1] === P[j + 1] && P[j + 1] === P[k + 1]) - P.splice(j, 2), i -= 2; - } - } return j; } _project(x0, y0, vx, vy) { @@ -326,4 +318,16 @@ export default class Voronoi { | (y < this.ymin ? 0b0100 : y > this.ymax ? 0b1000 : 0b0000); } + _simplify(P) { + if (P && P.length > 4) { + for (let i = 0; i < P.length; i+= 2) { + const j = (i + 2) % P.length, k = (i + 4) % P.length; + if (P[i] === P[j] && P[j] === P[k] || P[i + 1] === P[j + 1] && P[j + 1] === P[k + 1]) { + P.splice(j, 2), i -= 2; + } + } + if (!P.length) P = null; + } + return P; + } } diff --git a/test/voronoi-test.js b/test/voronoi-test.js index c543a98..129c392 100644 --- a/test/voronoi-test.js +++ b/test/voronoi-test.js @@ -79,7 +79,7 @@ it("cellPolygons filter out empty cells and have the cell index as a property", const voronoi = Delaunay.from(pts).voronoi([0, 0, 2, 2]); assert.deepStrictEqual([...voronoi.cellPolygons()], [ Object.assign([[0, 0], [1, 0], [0, 1], [0, 0]], {index:0, }), - Object.assign([[0, 1], [1, 0], [2, 0], [2, 2], [0, 2], [0, 1]], { index: 2 }) + Object.assign([[2, 2], [0, 2], [0, 1], [1, 0], [2, 0], [2, 2]], { index: 2 }) ]); }); @@ -106,3 +106,19 @@ it("voronoi.neighbors returns the correct neighbors, rotated", () => { const voronoi = Delaunay.from(points).voronoi([-100, -90, 0, 0]); assert.deepStrictEqual([0, 1, 2, 3].map(i => [...voronoi.neighbors(i)].sort()), [[1], [0, 2, 3], [1, 3], [1, 2]]); }); + +it("voronoi returns the expected result (#136)", () => { + const points = [ + [447.27981036477433, 698.9400262172304], + [485.27830313288746, 668.9946483670656], + [611.9525697080425, 397.71056371206487], + [491.44637766366105, 692.071157339428], + [697.553622336339, 692.071157339428], + [497.00778156318086, 667.1990851383492], + [691.9922184368191, 667.1990851383492], + [544.9897579870977, 407.0828550310619], + [543.1738215956482, 437.35879519252677] + ]; + const voronoi = Delaunay.from(points).voronoi([0, 0, 1000, 1000]); + assert.strictEqual(voronoi.cellPolygon(3).length, 6); +});