Skip to content

Commit c1f5b52

Browse files
authored
fix incorrect voronoi diagram for 5 collinear points (#147)
closes #146
1 parent dc894a1 commit c1f5b52

File tree

2 files changed

+9
-12
lines changed

2 files changed

+9
-12
lines changed

src/delaunay.js

+3-12
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ function collinear(d) {
2727
return true;
2828
}
2929

30-
function jitter(x, y, r) {
31-
return [x + Math.sin(x + y) * r, y + Math.cos(x - y) * r];
32-
}
33-
3430
export default class Delaunay {
3531
static from(points, fx = pointX, fy = pointY, that) {
3632
return new Delaunay("length" in points
@@ -56,14 +52,9 @@ export default class Delaunay {
5652
if (d.hull && d.hull.length > 2 && collinear(d)) {
5753
this.collinear = Int32Array.from({length: points.length / 2}, (_, i) => i)
5854
.sort((i, j) => points[2 * i] - points[2 * j] || points[2 * i + 1] - points[2 * j + 1]); // for exact neighbors
59-
const e = this.collinear[0], f = this.collinear[this.collinear.length - 1],
60-
bounds = [ points[2 * e], points[2 * e + 1], points[2 * f], points[2 * f + 1] ],
61-
r = 1e-8 * Math.hypot(bounds[3] - bounds[1], bounds[2] - bounds[0]);
62-
for (let i = 0, n = points.length / 2; i < n; ++i) {
63-
const p = jitter(points[2 * i], points[2 * i + 1], r);
64-
points[2 * i] = p[0];
65-
points[2 * i + 1] = p[1];
66-
}
55+
const e = this.collinear[0] << 1, f = this.collinear[this.collinear.length - 1] << 1;
56+
const r = 1e-9 * Math.hypot(points[f] - points[e], points[f + 1] - points[e + 1]);
57+
for (let i = 0; i < points.length; ++i) points[i] += r * Math.sin(i + 0.5);
6758
this._delaunator = new Delaunator(points);
6859
} else {
6960
delete this.collinear;

test/voronoi-test.js

+6
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,9 @@ it("voronoi returns the expected result (#141)", () => {
128128
const voronoi = Delaunay.from(points).voronoi([1, 1, 499, 199]);
129129
assert.deepEqual(Array.from(voronoi.cellPolygons(), (d) => d.length), [7, 5, 5, 5, 6, 5, 5, 5]);
130130
});
131+
132+
it("voronoi returns the expected result for collinear points (#146)", () => {
133+
const points = [[25,20], [75,20], [125,20], [175,20], [225,20]];
134+
const voronoi = Delaunay.from(points).voronoi([0, 0, 250, 40]);
135+
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]]]);
136+
});

0 commit comments

Comments
 (0)