Skip to content

Commit dc894a1

Browse files
akassaeimbostock
andauthored
Make Delaunay.find return -1 instead of NaN for edge cases (#145)
* test: add one unit test that covers the empty points array case * fix: fix NaN cases for delaunay find * fixes for odd-length points --------- Co-authored-by: Mike Bostock <[email protected]>
1 parent 7bf3fd0 commit dc894a1

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

src/delaunay.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export default class Delaunay {
5454

5555
// check for collinear
5656
if (d.hull && d.hull.length > 2 && collinear(d)) {
57-
this.collinear = Int32Array.from({length: points.length/2}, (_,i) => i)
57+
this.collinear = Int32Array.from({length: points.length / 2}, (_, i) => i)
5858
.sort((i, j) => points[2 * i] - points[2 * j] || points[2 * i + 1] - points[2 * j + 1]); // for exact neighbors
5959
const e = this.collinear[0], f = this.collinear[this.collinear.length - 1],
6060
bounds = [ points[2 * e], points[2 * e + 1], points[2 * f], points[2 * f + 1] ],
@@ -137,7 +137,8 @@ export default class Delaunay {
137137
}
138138
_step(i, x, y) {
139139
const {inedges, hull, _hullIndex, halfedges, triangles, points} = this;
140-
if (inedges[i] === -1 || !points.length) return (i + 1) % (points.length >> 1);
140+
if (points.length < 2) return -1;
141+
if (inedges[i] === -1) return (i + 1) % (points.length >> 1);
141142
let c = i;
142143
let dc = pow(x - points[i * 2], 2) + pow(y - points[i * 2 + 1], 2);
143144
const e0 = inedges[i];
@@ -178,7 +179,7 @@ export default class Delaunay {
178179
r = r == undefined ? 2 : +r;
179180
const buffer = context == null ? context = new Path : undefined;
180181
const {points} = this;
181-
for (let i = 0, n = points.length; i < n; i += 2) {
182+
for (let i = 0, n = points.length & ~1; i < n; i += 2) { // round down if points has odd length
182183
const x = points[i], y = points[i + 1];
183184
context.moveTo(x + r, y);
184185
context.arc(x, y, r, 0, tau);

test/delaunay-test.js

+25-5
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,37 @@ it("delaunay.find(x, y) returns the index of the cell that contains the specifie
127127
assert.strictEqual(delaunay.find(51, 51), 4);
128128
});
129129

130-
it("delaunay.find(x, y) works with one or two points", () => {
131-
const points = [[0, 1], [0, 2]];
132-
const delaunay = Delaunay.from(points);
133-
assert.strictEqual(points[delaunay.find(0, -1)][1], 1);
134-
assert.strictEqual(points[delaunay.find(0, 2.2)][1], 2);
130+
it("delaunay.find(x, y) works with one point", () => {
131+
const delaunay = new Delaunay([0, 1]);
132+
assert.strictEqual(delaunay.find(0, -1), 0);
133+
assert.strictEqual(delaunay.find(0, 2.2), 0);
135134
delaunay.points.fill(0);
136135
delaunay.update();
137136
assert.strictEqual(delaunay.find(0, -1), 0);
138137
assert.strictEqual(delaunay.find(0, 1.2), 0);
139138
});
140139

140+
it("delaunay.find(x, y) works with two points", () => {
141+
const delaunay = new Delaunay([0, 1, 0, 2]);
142+
assert.strictEqual(delaunay.find(0, -1), 0);
143+
assert.strictEqual(delaunay.find(0, 2.2), 1);
144+
delaunay.points.fill(0);
145+
delaunay.update();
146+
assert.strictEqual(delaunay.find(0, -1), 0);
147+
assert.strictEqual(delaunay.find(0, 1.2), 0);
148+
});
149+
150+
it("delaunay.find(x, y) returns -1 for empty points array", () => {
151+
const delaunay = new Delaunay([]);
152+
assert.strictEqual(delaunay.find(0, -1), -1);
153+
});
154+
155+
it("delaunay.find(x, y) returns -1 for half a point", () => {
156+
const delaunay = new Delaunay([0]); // invalid; considered empty
157+
assert.strictEqual(delaunay.find(0, -1), -1);
158+
assert.strictEqual(delaunay.find(0, 2.2), -1);
159+
});
160+
141161
it("delaunay.find(x, y) works with collinear points", () => {
142162
const points = [[0, 1], [0, 2], [0, 4], [0, 0], [0, 3], [0, 4], [0, 4]];
143163
const delaunay = Delaunay.from(points);

0 commit comments

Comments
 (0)