Skip to content

Commit da865e9

Browse files
committed
fix a bug when updating to collinear points
as delaunay.update did not go through the collinearity check, it failed when we created a delaunay and then updated it to collinear points live test case https://observablehq.com/d/58b705d93bc8524a
1 parent 049c17d commit da865e9

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

src/delaunay.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,21 @@ function jitter(x, y, r) {
3535

3636
export default class Delaunay {
3737
constructor(points) {
38-
let d = new Delaunator(points),
39-
a = area(d.hull, points);
40-
if (a < 1e-10 && d.hull && d.hull.length > 2) {
38+
this._delaunator = new Delaunator(points);
39+
this.inedges = new Int32Array(points.length / 2);
40+
this._hullIndex = new Int32Array(points.length / 2);
41+
this.points = this._delaunator.coords;
42+
this._init();
43+
}
44+
update() {
45+
this._delaunator.update();
46+
this._init();
47+
}
48+
_init() {
49+
const d = this._delaunator, points = this.points;
50+
51+
// check for collinear
52+
if (d.hull && d.hull.length > 2 && area(d.hull, points) < 1e-10) {
4153
this.collinear = Int32Array.from({length: points.length/2}, (_,i) => i)
4254
.sort((i, j) => points[2 * i] - points[2 * j] || points[2 * i + 1] - points[2 * j + 1]); // for exact neighbors
4355
const e = this.collinear[0], f = this.collinear[this.collinear.length - 1],
@@ -48,19 +60,11 @@ export default class Delaunay {
4860
points[2 * i] = p[0];
4961
points[2 * i + 1] = p[1];
5062
}
51-
d = new Delaunator(points);
63+
this._delaunator = new Delaunator(points);
64+
} else {
65+
delete this.collinear;
5266
}
53-
this._delaunator = d;
54-
this.inedges = new Int32Array(points.length / 2);
55-
this._hullIndex = new Int32Array(points.length / 2);
56-
this.points = this._delaunator.coords;
57-
this._init();
58-
}
59-
update() {
60-
this._delaunator.update();
61-
this._init();
62-
}
63-
_init() {
67+
6468
const halfedges = this.halfedges = this._delaunator.halfedges;
6569
const hull = this.hull = this._delaunator.hull;
6670
const triangles = this.triangles = this._delaunator.triangles;

test/delaunay-test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,27 @@ tape("delaunay.update() allows fast updates", test => {
125125
test.deepEqual(circumcenters2, Float64Array.from([ -150, 50, -250, -150, 50, -150, -150, -250 ]));
126126
});
127127

128+
tape("delaunay.update() updates collinear points", test => {
129+
const delaunay = new Delaunay(Array.from({ length: 250 }).fill(0));
130+
test.equal(delaunay.collinear, undefined);
131+
for (let i = 0; i < delaunay.points.length; i++)
132+
delaunay.points[i] = (i % 2) ? i : 0;
133+
delaunay.update();
134+
test.equal(delaunay.collinear.length, 125);
135+
for (let i = 0; i < delaunay.points.length; i++)
136+
delaunay.points[i] = Math.sin(i);
137+
delaunay.update();
138+
test.equal(delaunay.collinear, undefined);
139+
for (let i = 0; i < delaunay.points.length; i++)
140+
delaunay.points[i] = (i % 2) ? i : 0;
141+
delaunay.update();
142+
test.equal(delaunay.collinear.length, 125);
143+
for (let i = 0; i < delaunay.points.length; i++)
144+
delaunay.points[i] = 0;
145+
delaunay.update();
146+
test.equal(delaunay.collinear, undefined);
147+
});
148+
128149
tape("delaunay.find(x, y) with coincident point", test => {
129150
let delaunay = Delaunay.from([[0, 0], [0, 0], [10,10], [10, -10]]);
130151
test.equal(delaunay.find(100,100), 2);

0 commit comments

Comments
 (0)