From 3a2e5afa57d36e40ea75aaf66560fb272bec54cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Sat, 25 Mar 2023 15:21:52 +0100 Subject: [PATCH 1/2] fix #141 --- src/voronoi.js | 21 ++++++++++----------- test/voronoi-test.js | 6 ++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/voronoi.js b/src/voronoi.js index 8811bfe..fcd7e0c 100644 --- a/src/voronoi.js +++ b/src/voronoi.js @@ -18,6 +18,7 @@ export default class Voronoi { } _init() { const {delaunay: {points, hull, triangles}, vectors} = this; + let b; // lazily computed barycenter of the hull // Compute circumcenters. const circumcenters = this.circumcenters = this._circumcenters.subarray(0, triangles.length / 3 * 2); @@ -39,17 +40,15 @@ export default class Voronoi { const ab = (dx * ey - dy * ex) * 2; if (Math.abs(ab) < 1e-9) { - // degenerate case (collinear diagram) - // almost equal points (degenerate triangle) - // the circumcenter is at the infinity, in a - // direction that is: - // 1. orthogonal to the halfedge. - let a = 1e9; - // 2. points away from the center; since the list of triangles starts - // in the center, the first point of the first triangle - // will be our reference - const r = triangles[0] * 2; - a *= Math.sign((points[r] - x1) * ey - (points[r + 1] - y1) * ex); + // For a degenerate triangle, the circumcenter is at the infinity, in a + // direction orthogonal to the halfedge and away from the “center” of + // the diagram , defined as the hull’s barycenter. + if (!b) { + b = {x: 0, y: 0}; + for (const i of hull) b.x += points[i * 2], b.y += points[i * 2 + 1]; + b.x /= hull.length, b.y /= hull.length; + } + const a = 1e9 * Math.sign((b.x - x1) * ey - (b.y - y1) * ex); x = (x1 + x3) / 2 - a * ey; y = (y1 + y3) / 2 + a * ex; } else { diff --git a/test/voronoi-test.js b/test/voronoi-test.js index 129c392..dcf0f09 100644 --- a/test/voronoi-test.js +++ b/test/voronoi-test.js @@ -122,3 +122,9 @@ it("voronoi returns the expected result (#136)", () => { const voronoi = Delaunay.from(points).voronoi([0, 0, 1000, 1000]); assert.strictEqual(voronoi.cellPolygon(3).length, 6); }); + +it("voronoi returns the expected result (#141)", () => { + const points = [[10, 190]].concat(Array.from({ length: 7 }, (d, i) => [i * 80, (i * 50) / 7])); + const voronoi = Delaunay.from(points).voronoi([1, 1, 499, 199]); + assert.deepEqual(Array.from(voronoi.cellPolygons(), (d) => d.length), [7, 5, 5, 5, 6, 5, 5, 5]); +}); From e11a0cd7320a0bad638c283851f29a06c39b37a8 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 31 Mar 2023 19:38:00 -0700 Subject: [PATCH 2/2] bx, by --- src/voronoi.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/voronoi.js b/src/voronoi.js index fcd7e0c..4918036 100644 --- a/src/voronoi.js +++ b/src/voronoi.js @@ -18,7 +18,7 @@ export default class Voronoi { } _init() { const {delaunay: {points, hull, triangles}, vectors} = this; - let b; // lazily computed barycenter of the hull + let bx, by; // lazily computed barycenter of the hull // Compute circumcenters. const circumcenters = this.circumcenters = this._circumcenters.subarray(0, triangles.length / 3 * 2); @@ -43,12 +43,12 @@ export default class Voronoi { // For a degenerate triangle, the circumcenter is at the infinity, in a // direction orthogonal to the halfedge and away from the “center” of // the diagram , defined as the hull’s barycenter. - if (!b) { - b = {x: 0, y: 0}; - for (const i of hull) b.x += points[i * 2], b.y += points[i * 2 + 1]; - b.x /= hull.length, b.y /= hull.length; + if (bx === undefined) { + bx = by = 0; + for (const i of hull) bx += points[i * 2], by += points[i * 2 + 1]; + bx /= hull.length, by /= hull.length; } - const a = 1e9 * Math.sign((b.x - x1) * ey - (b.y - y1) * ex); + const a = 1e9 * Math.sign((bx - x1) * ey - (by - y1) * ex); x = (x1 + x3) / 2 - a * ey; y = (y1 + y3) / 2 + a * ex; } else {