Skip to content

Commit

Permalink
fix incorrect voronoi diagram for 5 collinear points (#147)
Browse files Browse the repository at this point in the history
closes #146
  • Loading branch information
Fil authored Jul 14, 2024
1 parent dc894a1 commit c1f5b52
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 12 deletions.
15 changes: 3 additions & 12 deletions src/delaunay.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ function collinear(d) {
return true;
}

function jitter(x, y, r) {
return [x + Math.sin(x + y) * r, y + Math.cos(x - y) * r];
}

export default class Delaunay {
static from(points, fx = pointX, fy = pointY, that) {
return new Delaunay("length" in points
Expand All @@ -56,14 +52,9 @@ export default class Delaunay {
if (d.hull && d.hull.length > 2 && collinear(d)) {
this.collinear = Int32Array.from({length: points.length / 2}, (_, i) => i)
.sort((i, j) => points[2 * i] - points[2 * j] || points[2 * i + 1] - points[2 * j + 1]); // for exact neighbors
const e = this.collinear[0], f = this.collinear[this.collinear.length - 1],
bounds = [ points[2 * e], points[2 * e + 1], points[2 * f], points[2 * f + 1] ],
r = 1e-8 * Math.hypot(bounds[3] - bounds[1], bounds[2] - bounds[0]);
for (let i = 0, n = points.length / 2; i < n; ++i) {
const p = jitter(points[2 * i], points[2 * i + 1], r);
points[2 * i] = p[0];
points[2 * i + 1] = p[1];
}
const e = this.collinear[0] << 1, f = this.collinear[this.collinear.length - 1] << 1;
const r = 1e-9 * Math.hypot(points[f] - points[e], points[f + 1] - points[e + 1]);
for (let i = 0; i < points.length; ++i) points[i] += r * Math.sin(i + 0.5);
this._delaunator = new Delaunator(points);
} else {
delete this.collinear;
Expand Down
6 changes: 6 additions & 0 deletions test/voronoi-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,9 @@ it("voronoi returns the expected result (#141)", () => {
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]);
});

it("voronoi returns the expected result for collinear points (#146)", () => {
const points = [[25,20], [75,20], [125,20], [175,20], [225,20]];
const voronoi = Delaunay.from(points).voronoi([0, 0, 250, 40]);
assert.deepStrictEqual(Array.from(voronoi.cellPolygons(), (d) => d.map((u) => u.map((d) => Math.round(d)))), [[[0,40],[0,0],[50,0],[50,40],[0,40]],[[100,0],[100,40],[50,40],[50,0],[100,0]],[[150,0],[150,40],[100,40],[100,0],[150,0]],[[150,40],[150,0],[200,0],[200,40],[150,40]],[[250,0],[250,40],[200,40],[200,0],[250,0]]]);
});

0 comments on commit c1f5b52

Please sign in to comment.