@mui/x-charts-vendor 8.12.0 → 8.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -7
- package/package.json +5 -8
- package/d3-delaunay.d.ts +0 -5
- package/d3-delaunay.js +0 -7
- package/delaunator.d.ts +0 -5
- package/delaunator.js +0 -7
- package/es/d3-delaunay.mjs +0 -6
- package/es/delaunator.mjs +0 -6
- package/es/robust-predicates.mjs +0 -6
- package/lib/d3-delaunay.js +0 -6
- package/lib/delaunator.js +0 -6
- package/lib/robust-predicates.js +0 -6
- package/lib-vendor/d3-delaunay/LICENSE +0 -14
- package/lib-vendor/d3-delaunay/dist/d3-delaunay.js +0 -1398
- package/lib-vendor/d3-delaunay/dist/d3-delaunay.min.js +0 -853
- package/lib-vendor/d3-delaunay/src/delaunay.js +0 -282
- package/lib-vendor/d3-delaunay/src/index.js +0 -20
- package/lib-vendor/d3-delaunay/src/path.js +0 -43
- package/lib-vendor/d3-delaunay/src/polygon.js +0 -24
- package/lib-vendor/d3-delaunay/src/voronoi.js +0 -390
- package/lib-vendor/delaunator/LICENSE +0 -15
- package/lib-vendor/delaunator/delaunator.js +0 -688
- package/lib-vendor/delaunator/delaunator.min.js +0 -316
- package/lib-vendor/delaunator/index.js +0 -440
- package/lib-vendor/robust-predicates/LICENSE +0 -24
- package/lib-vendor/robust-predicates/esm/incircle.js +0 -667
- package/lib-vendor/robust-predicates/esm/insphere.js +0 -693
- package/lib-vendor/robust-predicates/esm/orient2d.js +0 -174
- package/lib-vendor/robust-predicates/esm/orient3d.js +0 -422
- package/lib-vendor/robust-predicates/esm/util.js +0 -147
- package/lib-vendor/robust-predicates/index.js +0 -57
- package/lib-vendor/robust-predicates/umd/incircle.js +0 -798
- package/lib-vendor/robust-predicates/umd/incircle.min.js +0 -170
- package/lib-vendor/robust-predicates/umd/insphere.js +0 -828
- package/lib-vendor/robust-predicates/umd/insphere.min.js +0 -223
- package/lib-vendor/robust-predicates/umd/orient2d.js +0 -260
- package/lib-vendor/robust-predicates/umd/orient2d.min.js +0 -69
- package/lib-vendor/robust-predicates/umd/orient3d.js +0 -550
- package/lib-vendor/robust-predicates/umd/orient3d.min.js +0 -133
- package/lib-vendor/robust-predicates/umd/predicates.js +0 -2073
- package/lib-vendor/robust-predicates/umd/predicates.min.js +0 -468
- package/robust-predicates.d.ts +0 -5
- package/robust-predicates.js +0 -7
|
@@ -1,1398 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
// https://github.com/d3/d3-delaunay v6.0.4 Copyright 2018-2021 Observable, Inc., 2021 Mapbox
|
|
4
|
-
(function (global, factory) {
|
|
5
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}));
|
|
6
|
-
})(this, function (exports) {
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
const epsilon$1 = 1.1102230246251565e-16;
|
|
10
|
-
const splitter = 134217729;
|
|
11
|
-
const resulterrbound = (3 + 8 * epsilon$1) * epsilon$1;
|
|
12
|
-
|
|
13
|
-
// fast_expansion_sum_zeroelim routine from oritinal code
|
|
14
|
-
function sum(elen, e, flen, f, h) {
|
|
15
|
-
let Q, Qnew, hh, bvirt;
|
|
16
|
-
let enow = e[0];
|
|
17
|
-
let fnow = f[0];
|
|
18
|
-
let eindex = 0;
|
|
19
|
-
let findex = 0;
|
|
20
|
-
if (fnow > enow === fnow > -enow) {
|
|
21
|
-
Q = enow;
|
|
22
|
-
enow = e[++eindex];
|
|
23
|
-
} else {
|
|
24
|
-
Q = fnow;
|
|
25
|
-
fnow = f[++findex];
|
|
26
|
-
}
|
|
27
|
-
let hindex = 0;
|
|
28
|
-
if (eindex < elen && findex < flen) {
|
|
29
|
-
if (fnow > enow === fnow > -enow) {
|
|
30
|
-
Qnew = enow + Q;
|
|
31
|
-
hh = Q - (Qnew - enow);
|
|
32
|
-
enow = e[++eindex];
|
|
33
|
-
} else {
|
|
34
|
-
Qnew = fnow + Q;
|
|
35
|
-
hh = Q - (Qnew - fnow);
|
|
36
|
-
fnow = f[++findex];
|
|
37
|
-
}
|
|
38
|
-
Q = Qnew;
|
|
39
|
-
if (hh !== 0) {
|
|
40
|
-
h[hindex++] = hh;
|
|
41
|
-
}
|
|
42
|
-
while (eindex < elen && findex < flen) {
|
|
43
|
-
if (fnow > enow === fnow > -enow) {
|
|
44
|
-
Qnew = Q + enow;
|
|
45
|
-
bvirt = Qnew - Q;
|
|
46
|
-
hh = Q - (Qnew - bvirt) + (enow - bvirt);
|
|
47
|
-
enow = e[++eindex];
|
|
48
|
-
} else {
|
|
49
|
-
Qnew = Q + fnow;
|
|
50
|
-
bvirt = Qnew - Q;
|
|
51
|
-
hh = Q - (Qnew - bvirt) + (fnow - bvirt);
|
|
52
|
-
fnow = f[++findex];
|
|
53
|
-
}
|
|
54
|
-
Q = Qnew;
|
|
55
|
-
if (hh !== 0) {
|
|
56
|
-
h[hindex++] = hh;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
while (eindex < elen) {
|
|
61
|
-
Qnew = Q + enow;
|
|
62
|
-
bvirt = Qnew - Q;
|
|
63
|
-
hh = Q - (Qnew - bvirt) + (enow - bvirt);
|
|
64
|
-
enow = e[++eindex];
|
|
65
|
-
Q = Qnew;
|
|
66
|
-
if (hh !== 0) {
|
|
67
|
-
h[hindex++] = hh;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
while (findex < flen) {
|
|
71
|
-
Qnew = Q + fnow;
|
|
72
|
-
bvirt = Qnew - Q;
|
|
73
|
-
hh = Q - (Qnew - bvirt) + (fnow - bvirt);
|
|
74
|
-
fnow = f[++findex];
|
|
75
|
-
Q = Qnew;
|
|
76
|
-
if (hh !== 0) {
|
|
77
|
-
h[hindex++] = hh;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (Q !== 0 || hindex === 0) {
|
|
81
|
-
h[hindex++] = Q;
|
|
82
|
-
}
|
|
83
|
-
return hindex;
|
|
84
|
-
}
|
|
85
|
-
function estimate(elen, e) {
|
|
86
|
-
let Q = e[0];
|
|
87
|
-
for (let i = 1; i < elen; i++) Q += e[i];
|
|
88
|
-
return Q;
|
|
89
|
-
}
|
|
90
|
-
function vec(n) {
|
|
91
|
-
return new Float64Array(n);
|
|
92
|
-
}
|
|
93
|
-
const ccwerrboundA = (3 + 16 * epsilon$1) * epsilon$1;
|
|
94
|
-
const ccwerrboundB = (2 + 12 * epsilon$1) * epsilon$1;
|
|
95
|
-
const ccwerrboundC = (9 + 64 * epsilon$1) * epsilon$1 * epsilon$1;
|
|
96
|
-
const B = vec(4);
|
|
97
|
-
const C1 = vec(8);
|
|
98
|
-
const C2 = vec(12);
|
|
99
|
-
const D = vec(16);
|
|
100
|
-
const u = vec(4);
|
|
101
|
-
function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {
|
|
102
|
-
let acxtail, acytail, bcxtail, bcytail;
|
|
103
|
-
let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;
|
|
104
|
-
const acx = ax - cx;
|
|
105
|
-
const bcx = bx - cx;
|
|
106
|
-
const acy = ay - cy;
|
|
107
|
-
const bcy = by - cy;
|
|
108
|
-
s1 = acx * bcy;
|
|
109
|
-
c = splitter * acx;
|
|
110
|
-
ahi = c - (c - acx);
|
|
111
|
-
alo = acx - ahi;
|
|
112
|
-
c = splitter * bcy;
|
|
113
|
-
bhi = c - (c - bcy);
|
|
114
|
-
blo = bcy - bhi;
|
|
115
|
-
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
116
|
-
t1 = acy * bcx;
|
|
117
|
-
c = splitter * acy;
|
|
118
|
-
ahi = c - (c - acy);
|
|
119
|
-
alo = acy - ahi;
|
|
120
|
-
c = splitter * bcx;
|
|
121
|
-
bhi = c - (c - bcx);
|
|
122
|
-
blo = bcx - bhi;
|
|
123
|
-
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
124
|
-
_i = s0 - t0;
|
|
125
|
-
bvirt = s0 - _i;
|
|
126
|
-
B[0] = s0 - (_i + bvirt) + (bvirt - t0);
|
|
127
|
-
_j = s1 + _i;
|
|
128
|
-
bvirt = _j - s1;
|
|
129
|
-
_0 = s1 - (_j - bvirt) + (_i - bvirt);
|
|
130
|
-
_i = _0 - t1;
|
|
131
|
-
bvirt = _0 - _i;
|
|
132
|
-
B[1] = _0 - (_i + bvirt) + (bvirt - t1);
|
|
133
|
-
u3 = _j + _i;
|
|
134
|
-
bvirt = u3 - _j;
|
|
135
|
-
B[2] = _j - (u3 - bvirt) + (_i - bvirt);
|
|
136
|
-
B[3] = u3;
|
|
137
|
-
let det = estimate(4, B);
|
|
138
|
-
let errbound = ccwerrboundB * detsum;
|
|
139
|
-
if (det >= errbound || -det >= errbound) {
|
|
140
|
-
return det;
|
|
141
|
-
}
|
|
142
|
-
bvirt = ax - acx;
|
|
143
|
-
acxtail = ax - (acx + bvirt) + (bvirt - cx);
|
|
144
|
-
bvirt = bx - bcx;
|
|
145
|
-
bcxtail = bx - (bcx + bvirt) + (bvirt - cx);
|
|
146
|
-
bvirt = ay - acy;
|
|
147
|
-
acytail = ay - (acy + bvirt) + (bvirt - cy);
|
|
148
|
-
bvirt = by - bcy;
|
|
149
|
-
bcytail = by - (bcy + bvirt) + (bvirt - cy);
|
|
150
|
-
if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {
|
|
151
|
-
return det;
|
|
152
|
-
}
|
|
153
|
-
errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);
|
|
154
|
-
det += acx * bcytail + bcy * acxtail - (acy * bcxtail + bcx * acytail);
|
|
155
|
-
if (det >= errbound || -det >= errbound) return det;
|
|
156
|
-
s1 = acxtail * bcy;
|
|
157
|
-
c = splitter * acxtail;
|
|
158
|
-
ahi = c - (c - acxtail);
|
|
159
|
-
alo = acxtail - ahi;
|
|
160
|
-
c = splitter * bcy;
|
|
161
|
-
bhi = c - (c - bcy);
|
|
162
|
-
blo = bcy - bhi;
|
|
163
|
-
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
164
|
-
t1 = acytail * bcx;
|
|
165
|
-
c = splitter * acytail;
|
|
166
|
-
ahi = c - (c - acytail);
|
|
167
|
-
alo = acytail - ahi;
|
|
168
|
-
c = splitter * bcx;
|
|
169
|
-
bhi = c - (c - bcx);
|
|
170
|
-
blo = bcx - bhi;
|
|
171
|
-
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
172
|
-
_i = s0 - t0;
|
|
173
|
-
bvirt = s0 - _i;
|
|
174
|
-
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
|
|
175
|
-
_j = s1 + _i;
|
|
176
|
-
bvirt = _j - s1;
|
|
177
|
-
_0 = s1 - (_j - bvirt) + (_i - bvirt);
|
|
178
|
-
_i = _0 - t1;
|
|
179
|
-
bvirt = _0 - _i;
|
|
180
|
-
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
|
|
181
|
-
u3 = _j + _i;
|
|
182
|
-
bvirt = u3 - _j;
|
|
183
|
-
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
|
|
184
|
-
u[3] = u3;
|
|
185
|
-
const C1len = sum(4, B, 4, u, C1);
|
|
186
|
-
s1 = acx * bcytail;
|
|
187
|
-
c = splitter * acx;
|
|
188
|
-
ahi = c - (c - acx);
|
|
189
|
-
alo = acx - ahi;
|
|
190
|
-
c = splitter * bcytail;
|
|
191
|
-
bhi = c - (c - bcytail);
|
|
192
|
-
blo = bcytail - bhi;
|
|
193
|
-
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
194
|
-
t1 = acy * bcxtail;
|
|
195
|
-
c = splitter * acy;
|
|
196
|
-
ahi = c - (c - acy);
|
|
197
|
-
alo = acy - ahi;
|
|
198
|
-
c = splitter * bcxtail;
|
|
199
|
-
bhi = c - (c - bcxtail);
|
|
200
|
-
blo = bcxtail - bhi;
|
|
201
|
-
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
202
|
-
_i = s0 - t0;
|
|
203
|
-
bvirt = s0 - _i;
|
|
204
|
-
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
|
|
205
|
-
_j = s1 + _i;
|
|
206
|
-
bvirt = _j - s1;
|
|
207
|
-
_0 = s1 - (_j - bvirt) + (_i - bvirt);
|
|
208
|
-
_i = _0 - t1;
|
|
209
|
-
bvirt = _0 - _i;
|
|
210
|
-
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
|
|
211
|
-
u3 = _j + _i;
|
|
212
|
-
bvirt = u3 - _j;
|
|
213
|
-
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
|
|
214
|
-
u[3] = u3;
|
|
215
|
-
const C2len = sum(C1len, C1, 4, u, C2);
|
|
216
|
-
s1 = acxtail * bcytail;
|
|
217
|
-
c = splitter * acxtail;
|
|
218
|
-
ahi = c - (c - acxtail);
|
|
219
|
-
alo = acxtail - ahi;
|
|
220
|
-
c = splitter * bcytail;
|
|
221
|
-
bhi = c - (c - bcytail);
|
|
222
|
-
blo = bcytail - bhi;
|
|
223
|
-
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
224
|
-
t1 = acytail * bcxtail;
|
|
225
|
-
c = splitter * acytail;
|
|
226
|
-
ahi = c - (c - acytail);
|
|
227
|
-
alo = acytail - ahi;
|
|
228
|
-
c = splitter * bcxtail;
|
|
229
|
-
bhi = c - (c - bcxtail);
|
|
230
|
-
blo = bcxtail - bhi;
|
|
231
|
-
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
232
|
-
_i = s0 - t0;
|
|
233
|
-
bvirt = s0 - _i;
|
|
234
|
-
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
|
|
235
|
-
_j = s1 + _i;
|
|
236
|
-
bvirt = _j - s1;
|
|
237
|
-
_0 = s1 - (_j - bvirt) + (_i - bvirt);
|
|
238
|
-
_i = _0 - t1;
|
|
239
|
-
bvirt = _0 - _i;
|
|
240
|
-
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
|
|
241
|
-
u3 = _j + _i;
|
|
242
|
-
bvirt = u3 - _j;
|
|
243
|
-
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
|
|
244
|
-
u[3] = u3;
|
|
245
|
-
const Dlen = sum(C2len, C2, 4, u, D);
|
|
246
|
-
return D[Dlen - 1];
|
|
247
|
-
}
|
|
248
|
-
function orient2d(ax, ay, bx, by, cx, cy) {
|
|
249
|
-
const detleft = (ay - cy) * (bx - cx);
|
|
250
|
-
const detright = (ax - cx) * (by - cy);
|
|
251
|
-
const det = detleft - detright;
|
|
252
|
-
if (detleft === 0 || detright === 0 || detleft > 0 !== detright > 0) return det;
|
|
253
|
-
const detsum = Math.abs(detleft + detright);
|
|
254
|
-
if (Math.abs(det) >= ccwerrboundA * detsum) return det;
|
|
255
|
-
return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);
|
|
256
|
-
}
|
|
257
|
-
const EPSILON = Math.pow(2, -52);
|
|
258
|
-
const EDGE_STACK = new Uint32Array(512);
|
|
259
|
-
class Delaunator {
|
|
260
|
-
static from(points, getX = defaultGetX, getY = defaultGetY) {
|
|
261
|
-
const n = points.length;
|
|
262
|
-
const coords = new Float64Array(n * 2);
|
|
263
|
-
for (let i = 0; i < n; i++) {
|
|
264
|
-
const p = points[i];
|
|
265
|
-
coords[2 * i] = getX(p);
|
|
266
|
-
coords[2 * i + 1] = getY(p);
|
|
267
|
-
}
|
|
268
|
-
return new Delaunator(coords);
|
|
269
|
-
}
|
|
270
|
-
constructor(coords) {
|
|
271
|
-
const n = coords.length >> 1;
|
|
272
|
-
if (n > 0 && typeof coords[0] !== 'number') throw new Error('Expected coords to contain numbers.');
|
|
273
|
-
this.coords = coords;
|
|
274
|
-
|
|
275
|
-
// arrays that will store the triangulation graph
|
|
276
|
-
const maxTriangles = Math.max(2 * n - 5, 0);
|
|
277
|
-
this._triangles = new Uint32Array(maxTriangles * 3);
|
|
278
|
-
this._halfedges = new Int32Array(maxTriangles * 3);
|
|
279
|
-
|
|
280
|
-
// temporary arrays for tracking the edges of the advancing convex hull
|
|
281
|
-
this._hashSize = Math.ceil(Math.sqrt(n));
|
|
282
|
-
this._hullPrev = new Uint32Array(n); // edge to prev edge
|
|
283
|
-
this._hullNext = new Uint32Array(n); // edge to next edge
|
|
284
|
-
this._hullTri = new Uint32Array(n); // edge to adjacent triangle
|
|
285
|
-
this._hullHash = new Int32Array(this._hashSize).fill(-1); // angular edge hash
|
|
286
|
-
|
|
287
|
-
// temporary arrays for sorting points
|
|
288
|
-
this._ids = new Uint32Array(n);
|
|
289
|
-
this._dists = new Float64Array(n);
|
|
290
|
-
this.update();
|
|
291
|
-
}
|
|
292
|
-
update() {
|
|
293
|
-
const {
|
|
294
|
-
coords,
|
|
295
|
-
_hullPrev: hullPrev,
|
|
296
|
-
_hullNext: hullNext,
|
|
297
|
-
_hullTri: hullTri,
|
|
298
|
-
_hullHash: hullHash
|
|
299
|
-
} = this;
|
|
300
|
-
const n = coords.length >> 1;
|
|
301
|
-
|
|
302
|
-
// populate an array of point indices; calculate input data bbox
|
|
303
|
-
let minX = Infinity;
|
|
304
|
-
let minY = Infinity;
|
|
305
|
-
let maxX = -Infinity;
|
|
306
|
-
let maxY = -Infinity;
|
|
307
|
-
for (let i = 0; i < n; i++) {
|
|
308
|
-
const x = coords[2 * i];
|
|
309
|
-
const y = coords[2 * i + 1];
|
|
310
|
-
if (x < minX) minX = x;
|
|
311
|
-
if (y < minY) minY = y;
|
|
312
|
-
if (x > maxX) maxX = x;
|
|
313
|
-
if (y > maxY) maxY = y;
|
|
314
|
-
this._ids[i] = i;
|
|
315
|
-
}
|
|
316
|
-
const cx = (minX + maxX) / 2;
|
|
317
|
-
const cy = (minY + maxY) / 2;
|
|
318
|
-
let minDist = Infinity;
|
|
319
|
-
let i0, i1, i2;
|
|
320
|
-
|
|
321
|
-
// pick a seed point close to the center
|
|
322
|
-
for (let i = 0; i < n; i++) {
|
|
323
|
-
const d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]);
|
|
324
|
-
if (d < minDist) {
|
|
325
|
-
i0 = i;
|
|
326
|
-
minDist = d;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
const i0x = coords[2 * i0];
|
|
330
|
-
const i0y = coords[2 * i0 + 1];
|
|
331
|
-
minDist = Infinity;
|
|
332
|
-
|
|
333
|
-
// find the point closest to the seed
|
|
334
|
-
for (let i = 0; i < n; i++) {
|
|
335
|
-
if (i === i0) continue;
|
|
336
|
-
const d = dist(i0x, i0y, coords[2 * i], coords[2 * i + 1]);
|
|
337
|
-
if (d < minDist && d > 0) {
|
|
338
|
-
i1 = i;
|
|
339
|
-
minDist = d;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
let i1x = coords[2 * i1];
|
|
343
|
-
let i1y = coords[2 * i1 + 1];
|
|
344
|
-
let minRadius = Infinity;
|
|
345
|
-
|
|
346
|
-
// find the third point which forms the smallest circumcircle with the first two
|
|
347
|
-
for (let i = 0; i < n; i++) {
|
|
348
|
-
if (i === i0 || i === i1) continue;
|
|
349
|
-
const r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i], coords[2 * i + 1]);
|
|
350
|
-
if (r < minRadius) {
|
|
351
|
-
i2 = i;
|
|
352
|
-
minRadius = r;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
let i2x = coords[2 * i2];
|
|
356
|
-
let i2y = coords[2 * i2 + 1];
|
|
357
|
-
if (minRadius === Infinity) {
|
|
358
|
-
// order collinear points by dx (or dy if all x are identical)
|
|
359
|
-
// and return the list as a hull
|
|
360
|
-
for (let i = 0; i < n; i++) {
|
|
361
|
-
this._dists[i] = coords[2 * i] - coords[0] || coords[2 * i + 1] - coords[1];
|
|
362
|
-
}
|
|
363
|
-
quicksort(this._ids, this._dists, 0, n - 1);
|
|
364
|
-
const hull = new Uint32Array(n);
|
|
365
|
-
let j = 0;
|
|
366
|
-
for (let i = 0, d0 = -Infinity; i < n; i++) {
|
|
367
|
-
const id = this._ids[i];
|
|
368
|
-
if (this._dists[id] > d0) {
|
|
369
|
-
hull[j++] = id;
|
|
370
|
-
d0 = this._dists[id];
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
this.hull = hull.subarray(0, j);
|
|
374
|
-
this.triangles = new Uint32Array(0);
|
|
375
|
-
this.halfedges = new Uint32Array(0);
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// swap the order of the seed points for counter-clockwise orientation
|
|
380
|
-
if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) {
|
|
381
|
-
const i = i1;
|
|
382
|
-
const x = i1x;
|
|
383
|
-
const y = i1y;
|
|
384
|
-
i1 = i2;
|
|
385
|
-
i1x = i2x;
|
|
386
|
-
i1y = i2y;
|
|
387
|
-
i2 = i;
|
|
388
|
-
i2x = x;
|
|
389
|
-
i2y = y;
|
|
390
|
-
}
|
|
391
|
-
const center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
|
|
392
|
-
this._cx = center.x;
|
|
393
|
-
this._cy = center.y;
|
|
394
|
-
for (let i = 0; i < n; i++) {
|
|
395
|
-
this._dists[i] = dist(coords[2 * i], coords[2 * i + 1], center.x, center.y);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// sort the points by distance from the seed triangle circumcenter
|
|
399
|
-
quicksort(this._ids, this._dists, 0, n - 1);
|
|
400
|
-
|
|
401
|
-
// set up the seed triangle as the starting hull
|
|
402
|
-
this._hullStart = i0;
|
|
403
|
-
let hullSize = 3;
|
|
404
|
-
hullNext[i0] = hullPrev[i2] = i1;
|
|
405
|
-
hullNext[i1] = hullPrev[i0] = i2;
|
|
406
|
-
hullNext[i2] = hullPrev[i1] = i0;
|
|
407
|
-
hullTri[i0] = 0;
|
|
408
|
-
hullTri[i1] = 1;
|
|
409
|
-
hullTri[i2] = 2;
|
|
410
|
-
hullHash.fill(-1);
|
|
411
|
-
hullHash[this._hashKey(i0x, i0y)] = i0;
|
|
412
|
-
hullHash[this._hashKey(i1x, i1y)] = i1;
|
|
413
|
-
hullHash[this._hashKey(i2x, i2y)] = i2;
|
|
414
|
-
this.trianglesLen = 0;
|
|
415
|
-
this._addTriangle(i0, i1, i2, -1, -1, -1);
|
|
416
|
-
for (let k = 0, xp, yp; k < this._ids.length; k++) {
|
|
417
|
-
const i = this._ids[k];
|
|
418
|
-
const x = coords[2 * i];
|
|
419
|
-
const y = coords[2 * i + 1];
|
|
420
|
-
|
|
421
|
-
// skip near-duplicate points
|
|
422
|
-
if (k > 0 && Math.abs(x - xp) <= EPSILON && Math.abs(y - yp) <= EPSILON) continue;
|
|
423
|
-
xp = x;
|
|
424
|
-
yp = y;
|
|
425
|
-
|
|
426
|
-
// skip seed triangle points
|
|
427
|
-
if (i === i0 || i === i1 || i === i2) continue;
|
|
428
|
-
|
|
429
|
-
// find a visible edge on the convex hull using edge hash
|
|
430
|
-
let start = 0;
|
|
431
|
-
for (let j = 0, key = this._hashKey(x, y); j < this._hashSize; j++) {
|
|
432
|
-
start = hullHash[(key + j) % this._hashSize];
|
|
433
|
-
if (start !== -1 && start !== hullNext[start]) break;
|
|
434
|
-
}
|
|
435
|
-
start = hullPrev[start];
|
|
436
|
-
let e = start,
|
|
437
|
-
q;
|
|
438
|
-
while (q = hullNext[e], orient2d(x, y, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1]) >= 0) {
|
|
439
|
-
e = q;
|
|
440
|
-
if (e === start) {
|
|
441
|
-
e = -1;
|
|
442
|
-
break;
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
if (e === -1) continue; // likely a near-duplicate point; skip it
|
|
446
|
-
|
|
447
|
-
// add the first triangle from the point
|
|
448
|
-
let t = this._addTriangle(e, i, hullNext[e], -1, -1, hullTri[e]);
|
|
449
|
-
|
|
450
|
-
// recursively flip triangles from the point until they satisfy the Delaunay condition
|
|
451
|
-
hullTri[i] = this._legalize(t + 2);
|
|
452
|
-
hullTri[e] = t; // keep track of boundary triangles on the hull
|
|
453
|
-
hullSize++;
|
|
454
|
-
|
|
455
|
-
// walk forward through the hull, adding more triangles and flipping recursively
|
|
456
|
-
let n = hullNext[e];
|
|
457
|
-
while (q = hullNext[n], orient2d(x, y, coords[2 * n], coords[2 * n + 1], coords[2 * q], coords[2 * q + 1]) < 0) {
|
|
458
|
-
t = this._addTriangle(n, i, q, hullTri[i], -1, hullTri[n]);
|
|
459
|
-
hullTri[i] = this._legalize(t + 2);
|
|
460
|
-
hullNext[n] = n; // mark as removed
|
|
461
|
-
hullSize--;
|
|
462
|
-
n = q;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// walk backward from the other side, adding more triangles and flipping
|
|
466
|
-
if (e === start) {
|
|
467
|
-
while (q = hullPrev[e], orient2d(x, y, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1]) < 0) {
|
|
468
|
-
t = this._addTriangle(q, i, e, -1, hullTri[e], hullTri[q]);
|
|
469
|
-
this._legalize(t + 2);
|
|
470
|
-
hullTri[q] = t;
|
|
471
|
-
hullNext[e] = e; // mark as removed
|
|
472
|
-
hullSize--;
|
|
473
|
-
e = q;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// update the hull indices
|
|
478
|
-
this._hullStart = hullPrev[i] = e;
|
|
479
|
-
hullNext[e] = hullPrev[n] = i;
|
|
480
|
-
hullNext[i] = n;
|
|
481
|
-
|
|
482
|
-
// save the two new edges in the hash table
|
|
483
|
-
hullHash[this._hashKey(x, y)] = i;
|
|
484
|
-
hullHash[this._hashKey(coords[2 * e], coords[2 * e + 1])] = e;
|
|
485
|
-
}
|
|
486
|
-
this.hull = new Uint32Array(hullSize);
|
|
487
|
-
for (let i = 0, e = this._hullStart; i < hullSize; i++) {
|
|
488
|
-
this.hull[i] = e;
|
|
489
|
-
e = hullNext[e];
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// trim typed triangle mesh arrays
|
|
493
|
-
this.triangles = this._triangles.subarray(0, this.trianglesLen);
|
|
494
|
-
this.halfedges = this._halfedges.subarray(0, this.trianglesLen);
|
|
495
|
-
}
|
|
496
|
-
_hashKey(x, y) {
|
|
497
|
-
return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize;
|
|
498
|
-
}
|
|
499
|
-
_legalize(a) {
|
|
500
|
-
const {
|
|
501
|
-
_triangles: triangles,
|
|
502
|
-
_halfedges: halfedges,
|
|
503
|
-
coords
|
|
504
|
-
} = this;
|
|
505
|
-
let i = 0;
|
|
506
|
-
let ar = 0;
|
|
507
|
-
|
|
508
|
-
// recursion eliminated with a fixed-size stack
|
|
509
|
-
while (true) {
|
|
510
|
-
const b = halfedges[a];
|
|
511
|
-
|
|
512
|
-
/* if the pair of triangles doesn't satisfy the Delaunay condition
|
|
513
|
-
* (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
|
|
514
|
-
* then do the same check/flip recursively for the new pair of triangles
|
|
515
|
-
*
|
|
516
|
-
* pl pl
|
|
517
|
-
* /||\ / \
|
|
518
|
-
* al/ || \bl al/ \a
|
|
519
|
-
* / || \ / \
|
|
520
|
-
* / a||b \ flip /___ar___\
|
|
521
|
-
* p0\ || /p1 => p0\---bl---/p1
|
|
522
|
-
* \ || / \ /
|
|
523
|
-
* ar\ || /br b\ /br
|
|
524
|
-
* \||/ \ /
|
|
525
|
-
* pr pr
|
|
526
|
-
*/
|
|
527
|
-
const a0 = a - a % 3;
|
|
528
|
-
ar = a0 + (a + 2) % 3;
|
|
529
|
-
if (b === -1) {
|
|
530
|
-
// convex hull edge
|
|
531
|
-
if (i === 0) break;
|
|
532
|
-
a = EDGE_STACK[--i];
|
|
533
|
-
continue;
|
|
534
|
-
}
|
|
535
|
-
const b0 = b - b % 3;
|
|
536
|
-
const al = a0 + (a + 1) % 3;
|
|
537
|
-
const bl = b0 + (b + 2) % 3;
|
|
538
|
-
const p0 = triangles[ar];
|
|
539
|
-
const pr = triangles[a];
|
|
540
|
-
const pl = triangles[al];
|
|
541
|
-
const p1 = triangles[bl];
|
|
542
|
-
const illegal = inCircle(coords[2 * p0], coords[2 * p0 + 1], coords[2 * pr], coords[2 * pr + 1], coords[2 * pl], coords[2 * pl + 1], coords[2 * p1], coords[2 * p1 + 1]);
|
|
543
|
-
if (illegal) {
|
|
544
|
-
triangles[a] = p1;
|
|
545
|
-
triangles[b] = p0;
|
|
546
|
-
const hbl = halfedges[bl];
|
|
547
|
-
|
|
548
|
-
// edge swapped on the other side of the hull (rare); fix the halfedge reference
|
|
549
|
-
if (hbl === -1) {
|
|
550
|
-
let e = this._hullStart;
|
|
551
|
-
do {
|
|
552
|
-
if (this._hullTri[e] === bl) {
|
|
553
|
-
this._hullTri[e] = a;
|
|
554
|
-
break;
|
|
555
|
-
}
|
|
556
|
-
e = this._hullPrev[e];
|
|
557
|
-
} while (e !== this._hullStart);
|
|
558
|
-
}
|
|
559
|
-
this._link(a, hbl);
|
|
560
|
-
this._link(b, halfedges[ar]);
|
|
561
|
-
this._link(ar, bl);
|
|
562
|
-
const br = b0 + (b + 1) % 3;
|
|
563
|
-
|
|
564
|
-
// don't worry about hitting the cap: it can only happen on extremely degenerate input
|
|
565
|
-
if (i < EDGE_STACK.length) {
|
|
566
|
-
EDGE_STACK[i++] = br;
|
|
567
|
-
}
|
|
568
|
-
} else {
|
|
569
|
-
if (i === 0) break;
|
|
570
|
-
a = EDGE_STACK[--i];
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
return ar;
|
|
574
|
-
}
|
|
575
|
-
_link(a, b) {
|
|
576
|
-
this._halfedges[a] = b;
|
|
577
|
-
if (b !== -1) this._halfedges[b] = a;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// add a new triangle given vertex indices and adjacent half-edge ids
|
|
581
|
-
_addTriangle(i0, i1, i2, a, b, c) {
|
|
582
|
-
const t = this.trianglesLen;
|
|
583
|
-
this._triangles[t] = i0;
|
|
584
|
-
this._triangles[t + 1] = i1;
|
|
585
|
-
this._triangles[t + 2] = i2;
|
|
586
|
-
this._link(t, a);
|
|
587
|
-
this._link(t + 1, b);
|
|
588
|
-
this._link(t + 2, c);
|
|
589
|
-
this.trianglesLen += 3;
|
|
590
|
-
return t;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
// monotonically increases with real angle, but doesn't need expensive trigonometry
|
|
595
|
-
function pseudoAngle(dx, dy) {
|
|
596
|
-
const p = dx / (Math.abs(dx) + Math.abs(dy));
|
|
597
|
-
return (dy > 0 ? 3 - p : 1 + p) / 4; // [0..1]
|
|
598
|
-
}
|
|
599
|
-
function dist(ax, ay, bx, by) {
|
|
600
|
-
const dx = ax - bx;
|
|
601
|
-
const dy = ay - by;
|
|
602
|
-
return dx * dx + dy * dy;
|
|
603
|
-
}
|
|
604
|
-
function inCircle(ax, ay, bx, by, cx, cy, px, py) {
|
|
605
|
-
const dx = ax - px;
|
|
606
|
-
const dy = ay - py;
|
|
607
|
-
const ex = bx - px;
|
|
608
|
-
const ey = by - py;
|
|
609
|
-
const fx = cx - px;
|
|
610
|
-
const fy = cy - py;
|
|
611
|
-
const ap = dx * dx + dy * dy;
|
|
612
|
-
const bp = ex * ex + ey * ey;
|
|
613
|
-
const cp = fx * fx + fy * fy;
|
|
614
|
-
return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0;
|
|
615
|
-
}
|
|
616
|
-
function circumradius(ax, ay, bx, by, cx, cy) {
|
|
617
|
-
const dx = bx - ax;
|
|
618
|
-
const dy = by - ay;
|
|
619
|
-
const ex = cx - ax;
|
|
620
|
-
const ey = cy - ay;
|
|
621
|
-
const bl = dx * dx + dy * dy;
|
|
622
|
-
const cl = ex * ex + ey * ey;
|
|
623
|
-
const d = 0.5 / (dx * ey - dy * ex);
|
|
624
|
-
const x = (ey * bl - dy * cl) * d;
|
|
625
|
-
const y = (dx * cl - ex * bl) * d;
|
|
626
|
-
return x * x + y * y;
|
|
627
|
-
}
|
|
628
|
-
function circumcenter(ax, ay, bx, by, cx, cy) {
|
|
629
|
-
const dx = bx - ax;
|
|
630
|
-
const dy = by - ay;
|
|
631
|
-
const ex = cx - ax;
|
|
632
|
-
const ey = cy - ay;
|
|
633
|
-
const bl = dx * dx + dy * dy;
|
|
634
|
-
const cl = ex * ex + ey * ey;
|
|
635
|
-
const d = 0.5 / (dx * ey - dy * ex);
|
|
636
|
-
const x = ax + (ey * bl - dy * cl) * d;
|
|
637
|
-
const y = ay + (dx * cl - ex * bl) * d;
|
|
638
|
-
return {
|
|
639
|
-
x,
|
|
640
|
-
y
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
function quicksort(ids, dists, left, right) {
|
|
644
|
-
if (right - left <= 20) {
|
|
645
|
-
for (let i = left + 1; i <= right; i++) {
|
|
646
|
-
const temp = ids[i];
|
|
647
|
-
const tempDist = dists[temp];
|
|
648
|
-
let j = i - 1;
|
|
649
|
-
while (j >= left && dists[ids[j]] > tempDist) ids[j + 1] = ids[j--];
|
|
650
|
-
ids[j + 1] = temp;
|
|
651
|
-
}
|
|
652
|
-
} else {
|
|
653
|
-
const median = left + right >> 1;
|
|
654
|
-
let i = left + 1;
|
|
655
|
-
let j = right;
|
|
656
|
-
swap(ids, median, i);
|
|
657
|
-
if (dists[ids[left]] > dists[ids[right]]) swap(ids, left, right);
|
|
658
|
-
if (dists[ids[i]] > dists[ids[right]]) swap(ids, i, right);
|
|
659
|
-
if (dists[ids[left]] > dists[ids[i]]) swap(ids, left, i);
|
|
660
|
-
const temp = ids[i];
|
|
661
|
-
const tempDist = dists[temp];
|
|
662
|
-
while (true) {
|
|
663
|
-
do i++; while (dists[ids[i]] < tempDist);
|
|
664
|
-
do j--; while (dists[ids[j]] > tempDist);
|
|
665
|
-
if (j < i) break;
|
|
666
|
-
swap(ids, i, j);
|
|
667
|
-
}
|
|
668
|
-
ids[left + 1] = ids[j];
|
|
669
|
-
ids[j] = temp;
|
|
670
|
-
if (right - i + 1 >= j - left) {
|
|
671
|
-
quicksort(ids, dists, i, right);
|
|
672
|
-
quicksort(ids, dists, left, j - 1);
|
|
673
|
-
} else {
|
|
674
|
-
quicksort(ids, dists, left, j - 1);
|
|
675
|
-
quicksort(ids, dists, i, right);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
function swap(arr, i, j) {
|
|
680
|
-
const tmp = arr[i];
|
|
681
|
-
arr[i] = arr[j];
|
|
682
|
-
arr[j] = tmp;
|
|
683
|
-
}
|
|
684
|
-
function defaultGetX(p) {
|
|
685
|
-
return p[0];
|
|
686
|
-
}
|
|
687
|
-
function defaultGetY(p) {
|
|
688
|
-
return p[1];
|
|
689
|
-
}
|
|
690
|
-
const epsilon = 1e-6;
|
|
691
|
-
class Path {
|
|
692
|
-
constructor() {
|
|
693
|
-
this._x0 = this._y0 =
|
|
694
|
-
// start of current subpath
|
|
695
|
-
this._x1 = this._y1 = null; // end of current subpath
|
|
696
|
-
this._ = "";
|
|
697
|
-
}
|
|
698
|
-
moveTo(x, y) {
|
|
699
|
-
this._ += `M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}`;
|
|
700
|
-
}
|
|
701
|
-
closePath() {
|
|
702
|
-
if (this._x1 !== null) {
|
|
703
|
-
this._x1 = this._x0, this._y1 = this._y0;
|
|
704
|
-
this._ += "Z";
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
lineTo(x, y) {
|
|
708
|
-
this._ += `L${this._x1 = +x},${this._y1 = +y}`;
|
|
709
|
-
}
|
|
710
|
-
arc(x, y, r) {
|
|
711
|
-
x = +x, y = +y, r = +r;
|
|
712
|
-
const x0 = x + r;
|
|
713
|
-
const y0 = y;
|
|
714
|
-
if (r < 0) throw new Error("negative radius");
|
|
715
|
-
if (this._x1 === null) this._ += `M${x0},${y0}`;else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) this._ += "L" + x0 + "," + y0;
|
|
716
|
-
if (!r) return;
|
|
717
|
-
this._ += `A${r},${r},0,1,1,${x - r},${y}A${r},${r},0,1,1,${this._x1 = x0},${this._y1 = y0}`;
|
|
718
|
-
}
|
|
719
|
-
rect(x, y, w, h) {
|
|
720
|
-
this._ += `M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}h${+w}v${+h}h${-w}Z`;
|
|
721
|
-
}
|
|
722
|
-
value() {
|
|
723
|
-
return this._ || null;
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
class Polygon {
|
|
727
|
-
constructor() {
|
|
728
|
-
this._ = [];
|
|
729
|
-
}
|
|
730
|
-
moveTo(x, y) {
|
|
731
|
-
this._.push([x, y]);
|
|
732
|
-
}
|
|
733
|
-
closePath() {
|
|
734
|
-
this._.push(this._[0].slice());
|
|
735
|
-
}
|
|
736
|
-
lineTo(x, y) {
|
|
737
|
-
this._.push([x, y]);
|
|
738
|
-
}
|
|
739
|
-
value() {
|
|
740
|
-
return this._.length ? this._ : null;
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
class Voronoi {
|
|
744
|
-
constructor(delaunay, [xmin, ymin, xmax, ymax] = [0, 0, 960, 500]) {
|
|
745
|
-
if (!((xmax = +xmax) >= (xmin = +xmin)) || !((ymax = +ymax) >= (ymin = +ymin))) throw new Error("invalid bounds");
|
|
746
|
-
this.delaunay = delaunay;
|
|
747
|
-
this._circumcenters = new Float64Array(delaunay.points.length * 2);
|
|
748
|
-
this.vectors = new Float64Array(delaunay.points.length * 2);
|
|
749
|
-
this.xmax = xmax, this.xmin = xmin;
|
|
750
|
-
this.ymax = ymax, this.ymin = ymin;
|
|
751
|
-
this._init();
|
|
752
|
-
}
|
|
753
|
-
update() {
|
|
754
|
-
this.delaunay.update();
|
|
755
|
-
this._init();
|
|
756
|
-
return this;
|
|
757
|
-
}
|
|
758
|
-
_init() {
|
|
759
|
-
const {
|
|
760
|
-
delaunay: {
|
|
761
|
-
points,
|
|
762
|
-
hull,
|
|
763
|
-
triangles
|
|
764
|
-
},
|
|
765
|
-
vectors
|
|
766
|
-
} = this;
|
|
767
|
-
let bx, by; // lazily computed barycenter of the hull
|
|
768
|
-
|
|
769
|
-
// Compute circumcenters.
|
|
770
|
-
const circumcenters = this.circumcenters = this._circumcenters.subarray(0, triangles.length / 3 * 2);
|
|
771
|
-
for (let i = 0, j = 0, n = triangles.length, x, y; i < n; i += 3, j += 2) {
|
|
772
|
-
const t1 = triangles[i] * 2;
|
|
773
|
-
const t2 = triangles[i + 1] * 2;
|
|
774
|
-
const t3 = triangles[i + 2] * 2;
|
|
775
|
-
const x1 = points[t1];
|
|
776
|
-
const y1 = points[t1 + 1];
|
|
777
|
-
const x2 = points[t2];
|
|
778
|
-
const y2 = points[t2 + 1];
|
|
779
|
-
const x3 = points[t3];
|
|
780
|
-
const y3 = points[t3 + 1];
|
|
781
|
-
const dx = x2 - x1;
|
|
782
|
-
const dy = y2 - y1;
|
|
783
|
-
const ex = x3 - x1;
|
|
784
|
-
const ey = y3 - y1;
|
|
785
|
-
const ab = (dx * ey - dy * ex) * 2;
|
|
786
|
-
if (Math.abs(ab) < 1e-9) {
|
|
787
|
-
// For a degenerate triangle, the circumcenter is at the infinity, in a
|
|
788
|
-
// direction orthogonal to the halfedge and away from the “center” of
|
|
789
|
-
// the diagram <bx, by>, defined as the hull’s barycenter.
|
|
790
|
-
if (bx === undefined) {
|
|
791
|
-
bx = by = 0;
|
|
792
|
-
for (const i of hull) bx += points[i * 2], by += points[i * 2 + 1];
|
|
793
|
-
bx /= hull.length, by /= hull.length;
|
|
794
|
-
}
|
|
795
|
-
const a = 1e9 * Math.sign((bx - x1) * ey - (by - y1) * ex);
|
|
796
|
-
x = (x1 + x3) / 2 - a * ey;
|
|
797
|
-
y = (y1 + y3) / 2 + a * ex;
|
|
798
|
-
} else {
|
|
799
|
-
const d = 1 / ab;
|
|
800
|
-
const bl = dx * dx + dy * dy;
|
|
801
|
-
const cl = ex * ex + ey * ey;
|
|
802
|
-
x = x1 + (ey * bl - dy * cl) * d;
|
|
803
|
-
y = y1 + (dx * cl - ex * bl) * d;
|
|
804
|
-
}
|
|
805
|
-
circumcenters[j] = x;
|
|
806
|
-
circumcenters[j + 1] = y;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
// Compute exterior cell rays.
|
|
810
|
-
let h = hull[hull.length - 1];
|
|
811
|
-
let p0,
|
|
812
|
-
p1 = h * 4;
|
|
813
|
-
let x0,
|
|
814
|
-
x1 = points[2 * h];
|
|
815
|
-
let y0,
|
|
816
|
-
y1 = points[2 * h + 1];
|
|
817
|
-
vectors.fill(0);
|
|
818
|
-
for (let i = 0; i < hull.length; ++i) {
|
|
819
|
-
h = hull[i];
|
|
820
|
-
p0 = p1, x0 = x1, y0 = y1;
|
|
821
|
-
p1 = h * 4, x1 = points[2 * h], y1 = points[2 * h + 1];
|
|
822
|
-
vectors[p0 + 2] = vectors[p1] = y0 - y1;
|
|
823
|
-
vectors[p0 + 3] = vectors[p1 + 1] = x1 - x0;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
render(context) {
|
|
827
|
-
const buffer = context == null ? context = new Path() : undefined;
|
|
828
|
-
const {
|
|
829
|
-
delaunay: {
|
|
830
|
-
halfedges,
|
|
831
|
-
inedges,
|
|
832
|
-
hull
|
|
833
|
-
},
|
|
834
|
-
circumcenters,
|
|
835
|
-
vectors
|
|
836
|
-
} = this;
|
|
837
|
-
if (hull.length <= 1) return null;
|
|
838
|
-
for (let i = 0, n = halfedges.length; i < n; ++i) {
|
|
839
|
-
const j = halfedges[i];
|
|
840
|
-
if (j < i) continue;
|
|
841
|
-
const ti = Math.floor(i / 3) * 2;
|
|
842
|
-
const tj = Math.floor(j / 3) * 2;
|
|
843
|
-
const xi = circumcenters[ti];
|
|
844
|
-
const yi = circumcenters[ti + 1];
|
|
845
|
-
const xj = circumcenters[tj];
|
|
846
|
-
const yj = circumcenters[tj + 1];
|
|
847
|
-
this._renderSegment(xi, yi, xj, yj, context);
|
|
848
|
-
}
|
|
849
|
-
let h0,
|
|
850
|
-
h1 = hull[hull.length - 1];
|
|
851
|
-
for (let i = 0; i < hull.length; ++i) {
|
|
852
|
-
h0 = h1, h1 = hull[i];
|
|
853
|
-
const t = Math.floor(inedges[h1] / 3) * 2;
|
|
854
|
-
const x = circumcenters[t];
|
|
855
|
-
const y = circumcenters[t + 1];
|
|
856
|
-
const v = h0 * 4;
|
|
857
|
-
const p = this._project(x, y, vectors[v + 2], vectors[v + 3]);
|
|
858
|
-
if (p) this._renderSegment(x, y, p[0], p[1], context);
|
|
859
|
-
}
|
|
860
|
-
return buffer && buffer.value();
|
|
861
|
-
}
|
|
862
|
-
renderBounds(context) {
|
|
863
|
-
const buffer = context == null ? context = new Path() : undefined;
|
|
864
|
-
context.rect(this.xmin, this.ymin, this.xmax - this.xmin, this.ymax - this.ymin);
|
|
865
|
-
return buffer && buffer.value();
|
|
866
|
-
}
|
|
867
|
-
renderCell(i, context) {
|
|
868
|
-
const buffer = context == null ? context = new Path() : undefined;
|
|
869
|
-
const points = this._clip(i);
|
|
870
|
-
if (points === null || !points.length) return;
|
|
871
|
-
context.moveTo(points[0], points[1]);
|
|
872
|
-
let n = points.length;
|
|
873
|
-
while (points[0] === points[n - 2] && points[1] === points[n - 1] && n > 1) n -= 2;
|
|
874
|
-
for (let i = 2; i < n; i += 2) {
|
|
875
|
-
if (points[i] !== points[i - 2] || points[i + 1] !== points[i - 1]) context.lineTo(points[i], points[i + 1]);
|
|
876
|
-
}
|
|
877
|
-
context.closePath();
|
|
878
|
-
return buffer && buffer.value();
|
|
879
|
-
}
|
|
880
|
-
*cellPolygons() {
|
|
881
|
-
const {
|
|
882
|
-
delaunay: {
|
|
883
|
-
points
|
|
884
|
-
}
|
|
885
|
-
} = this;
|
|
886
|
-
for (let i = 0, n = points.length / 2; i < n; ++i) {
|
|
887
|
-
const cell = this.cellPolygon(i);
|
|
888
|
-
if (cell) cell.index = i, yield cell;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
cellPolygon(i) {
|
|
892
|
-
const polygon = new Polygon();
|
|
893
|
-
this.renderCell(i, polygon);
|
|
894
|
-
return polygon.value();
|
|
895
|
-
}
|
|
896
|
-
_renderSegment(x0, y0, x1, y1, context) {
|
|
897
|
-
let S;
|
|
898
|
-
const c0 = this._regioncode(x0, y0);
|
|
899
|
-
const c1 = this._regioncode(x1, y1);
|
|
900
|
-
if (c0 === 0 && c1 === 0) {
|
|
901
|
-
context.moveTo(x0, y0);
|
|
902
|
-
context.lineTo(x1, y1);
|
|
903
|
-
} else if (S = this._clipSegment(x0, y0, x1, y1, c0, c1)) {
|
|
904
|
-
context.moveTo(S[0], S[1]);
|
|
905
|
-
context.lineTo(S[2], S[3]);
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
contains(i, x, y) {
|
|
909
|
-
if ((x = +x, x !== x) || (y = +y, y !== y)) return false;
|
|
910
|
-
return this.delaunay._step(i, x, y) === i;
|
|
911
|
-
}
|
|
912
|
-
*neighbors(i) {
|
|
913
|
-
const ci = this._clip(i);
|
|
914
|
-
if (ci) for (const j of this.delaunay.neighbors(i)) {
|
|
915
|
-
const cj = this._clip(j);
|
|
916
|
-
// find the common edge
|
|
917
|
-
if (cj) loop: for (let ai = 0, li = ci.length; ai < li; ai += 2) {
|
|
918
|
-
for (let aj = 0, lj = cj.length; aj < lj; aj += 2) {
|
|
919
|
-
if (ci[ai] === cj[aj] && ci[ai + 1] === cj[aj + 1] && ci[(ai + 2) % li] === cj[(aj + lj - 2) % lj] && ci[(ai + 3) % li] === cj[(aj + lj - 1) % lj]) {
|
|
920
|
-
yield j;
|
|
921
|
-
break loop;
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
_cell(i) {
|
|
928
|
-
const {
|
|
929
|
-
circumcenters,
|
|
930
|
-
delaunay: {
|
|
931
|
-
inedges,
|
|
932
|
-
halfedges,
|
|
933
|
-
triangles
|
|
934
|
-
}
|
|
935
|
-
} = this;
|
|
936
|
-
const e0 = inedges[i];
|
|
937
|
-
if (e0 === -1) return null; // coincident point
|
|
938
|
-
const points = [];
|
|
939
|
-
let e = e0;
|
|
940
|
-
do {
|
|
941
|
-
const t = Math.floor(e / 3);
|
|
942
|
-
points.push(circumcenters[t * 2], circumcenters[t * 2 + 1]);
|
|
943
|
-
e = e % 3 === 2 ? e - 2 : e + 1;
|
|
944
|
-
if (triangles[e] !== i) break; // bad triangulation
|
|
945
|
-
e = halfedges[e];
|
|
946
|
-
} while (e !== e0 && e !== -1);
|
|
947
|
-
return points;
|
|
948
|
-
}
|
|
949
|
-
_clip(i) {
|
|
950
|
-
// degenerate case (1 valid point: return the box)
|
|
951
|
-
if (i === 0 && this.delaunay.hull.length === 1) {
|
|
952
|
-
return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin];
|
|
953
|
-
}
|
|
954
|
-
const points = this._cell(i);
|
|
955
|
-
if (points === null) return null;
|
|
956
|
-
const {
|
|
957
|
-
vectors: V
|
|
958
|
-
} = this;
|
|
959
|
-
const v = i * 4;
|
|
960
|
-
return this._simplify(V[v] || V[v + 1] ? this._clipInfinite(i, points, V[v], V[v + 1], V[v + 2], V[v + 3]) : this._clipFinite(i, points));
|
|
961
|
-
}
|
|
962
|
-
_clipFinite(i, points) {
|
|
963
|
-
const n = points.length;
|
|
964
|
-
let P = null;
|
|
965
|
-
let x0,
|
|
966
|
-
y0,
|
|
967
|
-
x1 = points[n - 2],
|
|
968
|
-
y1 = points[n - 1];
|
|
969
|
-
let c0,
|
|
970
|
-
c1 = this._regioncode(x1, y1);
|
|
971
|
-
let e0,
|
|
972
|
-
e1 = 0;
|
|
973
|
-
for (let j = 0; j < n; j += 2) {
|
|
974
|
-
x0 = x1, y0 = y1, x1 = points[j], y1 = points[j + 1];
|
|
975
|
-
c0 = c1, c1 = this._regioncode(x1, y1);
|
|
976
|
-
if (c0 === 0 && c1 === 0) {
|
|
977
|
-
e0 = e1, e1 = 0;
|
|
978
|
-
if (P) P.push(x1, y1);else P = [x1, y1];
|
|
979
|
-
} else {
|
|
980
|
-
let S, sx0, sy0, sx1, sy1;
|
|
981
|
-
if (c0 === 0) {
|
|
982
|
-
if ((S = this._clipSegment(x0, y0, x1, y1, c0, c1)) === null) continue;
|
|
983
|
-
[sx0, sy0, sx1, sy1] = S;
|
|
984
|
-
} else {
|
|
985
|
-
if ((S = this._clipSegment(x1, y1, x0, y0, c1, c0)) === null) continue;
|
|
986
|
-
[sx1, sy1, sx0, sy0] = S;
|
|
987
|
-
e0 = e1, e1 = this._edgecode(sx0, sy0);
|
|
988
|
-
if (e0 && e1) this._edge(i, e0, e1, P, P.length);
|
|
989
|
-
if (P) P.push(sx0, sy0);else P = [sx0, sy0];
|
|
990
|
-
}
|
|
991
|
-
e0 = e1, e1 = this._edgecode(sx1, sy1);
|
|
992
|
-
if (e0 && e1) this._edge(i, e0, e1, P, P.length);
|
|
993
|
-
if (P) P.push(sx1, sy1);else P = [sx1, sy1];
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
if (P) {
|
|
997
|
-
e0 = e1, e1 = this._edgecode(P[0], P[1]);
|
|
998
|
-
if (e0 && e1) this._edge(i, e0, e1, P, P.length);
|
|
999
|
-
} else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) {
|
|
1000
|
-
return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin];
|
|
1001
|
-
}
|
|
1002
|
-
return P;
|
|
1003
|
-
}
|
|
1004
|
-
_clipSegment(x0, y0, x1, y1, c0, c1) {
|
|
1005
|
-
// for more robustness, always consider the segment in the same order
|
|
1006
|
-
const flip = c0 < c1;
|
|
1007
|
-
if (flip) [x0, y0, x1, y1, c0, c1] = [x1, y1, x0, y0, c1, c0];
|
|
1008
|
-
while (true) {
|
|
1009
|
-
if (c0 === 0 && c1 === 0) return flip ? [x1, y1, x0, y0] : [x0, y0, x1, y1];
|
|
1010
|
-
if (c0 & c1) return null;
|
|
1011
|
-
let x,
|
|
1012
|
-
y,
|
|
1013
|
-
c = c0 || c1;
|
|
1014
|
-
if (c & 0b1000) x = x0 + (x1 - x0) * (this.ymax - y0) / (y1 - y0), y = this.ymax;else if (c & 0b0100) x = x0 + (x1 - x0) * (this.ymin - y0) / (y1 - y0), y = this.ymin;else if (c & 0b0010) y = y0 + (y1 - y0) * (this.xmax - x0) / (x1 - x0), x = this.xmax;else y = y0 + (y1 - y0) * (this.xmin - x0) / (x1 - x0), x = this.xmin;
|
|
1015
|
-
if (c0) x0 = x, y0 = y, c0 = this._regioncode(x0, y0);else x1 = x, y1 = y, c1 = this._regioncode(x1, y1);
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
_clipInfinite(i, points, vx0, vy0, vxn, vyn) {
|
|
1019
|
-
let P = Array.from(points),
|
|
1020
|
-
p;
|
|
1021
|
-
if (p = this._project(P[0], P[1], vx0, vy0)) P.unshift(p[0], p[1]);
|
|
1022
|
-
if (p = this._project(P[P.length - 2], P[P.length - 1], vxn, vyn)) P.push(p[0], p[1]);
|
|
1023
|
-
if (P = this._clipFinite(i, P)) {
|
|
1024
|
-
for (let j = 0, n = P.length, c0, c1 = this._edgecode(P[n - 2], P[n - 1]); j < n; j += 2) {
|
|
1025
|
-
c0 = c1, c1 = this._edgecode(P[j], P[j + 1]);
|
|
1026
|
-
if (c0 && c1) j = this._edge(i, c0, c1, P, j), n = P.length;
|
|
1027
|
-
}
|
|
1028
|
-
} else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) {
|
|
1029
|
-
P = [this.xmin, this.ymin, this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax];
|
|
1030
|
-
}
|
|
1031
|
-
return P;
|
|
1032
|
-
}
|
|
1033
|
-
_edge(i, e0, e1, P, j) {
|
|
1034
|
-
while (e0 !== e1) {
|
|
1035
|
-
let x, y;
|
|
1036
|
-
switch (e0) {
|
|
1037
|
-
case 0b0101:
|
|
1038
|
-
e0 = 0b0100;
|
|
1039
|
-
continue;
|
|
1040
|
-
// top-left
|
|
1041
|
-
case 0b0100:
|
|
1042
|
-
e0 = 0b0110, x = this.xmax, y = this.ymin;
|
|
1043
|
-
break;
|
|
1044
|
-
// top
|
|
1045
|
-
case 0b0110:
|
|
1046
|
-
e0 = 0b0010;
|
|
1047
|
-
continue;
|
|
1048
|
-
// top-right
|
|
1049
|
-
case 0b0010:
|
|
1050
|
-
e0 = 0b1010, x = this.xmax, y = this.ymax;
|
|
1051
|
-
break;
|
|
1052
|
-
// right
|
|
1053
|
-
case 0b1010:
|
|
1054
|
-
e0 = 0b1000;
|
|
1055
|
-
continue;
|
|
1056
|
-
// bottom-right
|
|
1057
|
-
case 0b1000:
|
|
1058
|
-
e0 = 0b1001, x = this.xmin, y = this.ymax;
|
|
1059
|
-
break;
|
|
1060
|
-
// bottom
|
|
1061
|
-
case 0b1001:
|
|
1062
|
-
e0 = 0b0001;
|
|
1063
|
-
continue;
|
|
1064
|
-
// bottom-left
|
|
1065
|
-
case 0b0001:
|
|
1066
|
-
e0 = 0b0101, x = this.xmin, y = this.ymin;
|
|
1067
|
-
break;
|
|
1068
|
-
// left
|
|
1069
|
-
}
|
|
1070
|
-
// Note: this implicitly checks for out of bounds: if P[j] or P[j+1] are
|
|
1071
|
-
// undefined, the conditional statement will be executed.
|
|
1072
|
-
if ((P[j] !== x || P[j + 1] !== y) && this.contains(i, x, y)) {
|
|
1073
|
-
P.splice(j, 0, x, y), j += 2;
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
return j;
|
|
1077
|
-
}
|
|
1078
|
-
_project(x0, y0, vx, vy) {
|
|
1079
|
-
let t = Infinity,
|
|
1080
|
-
c,
|
|
1081
|
-
x,
|
|
1082
|
-
y;
|
|
1083
|
-
if (vy < 0) {
|
|
1084
|
-
// top
|
|
1085
|
-
if (y0 <= this.ymin) return null;
|
|
1086
|
-
if ((c = (this.ymin - y0) / vy) < t) y = this.ymin, x = x0 + (t = c) * vx;
|
|
1087
|
-
} else if (vy > 0) {
|
|
1088
|
-
// bottom
|
|
1089
|
-
if (y0 >= this.ymax) return null;
|
|
1090
|
-
if ((c = (this.ymax - y0) / vy) < t) y = this.ymax, x = x0 + (t = c) * vx;
|
|
1091
|
-
}
|
|
1092
|
-
if (vx > 0) {
|
|
1093
|
-
// right
|
|
1094
|
-
if (x0 >= this.xmax) return null;
|
|
1095
|
-
if ((c = (this.xmax - x0) / vx) < t) x = this.xmax, y = y0 + (t = c) * vy;
|
|
1096
|
-
} else if (vx < 0) {
|
|
1097
|
-
// left
|
|
1098
|
-
if (x0 <= this.xmin) return null;
|
|
1099
|
-
if ((c = (this.xmin - x0) / vx) < t) x = this.xmin, y = y0 + (t = c) * vy;
|
|
1100
|
-
}
|
|
1101
|
-
return [x, y];
|
|
1102
|
-
}
|
|
1103
|
-
_edgecode(x, y) {
|
|
1104
|
-
return (x === this.xmin ? 0b0001 : x === this.xmax ? 0b0010 : 0b0000) | (y === this.ymin ? 0b0100 : y === this.ymax ? 0b1000 : 0b0000);
|
|
1105
|
-
}
|
|
1106
|
-
_regioncode(x, y) {
|
|
1107
|
-
return (x < this.xmin ? 0b0001 : x > this.xmax ? 0b0010 : 0b0000) | (y < this.ymin ? 0b0100 : y > this.ymax ? 0b1000 : 0b0000);
|
|
1108
|
-
}
|
|
1109
|
-
_simplify(P) {
|
|
1110
|
-
if (P && P.length > 4) {
|
|
1111
|
-
for (let i = 0; i < P.length; i += 2) {
|
|
1112
|
-
const j = (i + 2) % P.length,
|
|
1113
|
-
k = (i + 4) % P.length;
|
|
1114
|
-
if (P[i] === P[j] && P[j] === P[k] || P[i + 1] === P[j + 1] && P[j + 1] === P[k + 1]) {
|
|
1115
|
-
P.splice(j, 2), i -= 2;
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
if (!P.length) P = null;
|
|
1119
|
-
}
|
|
1120
|
-
return P;
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
const tau = 2 * Math.PI,
|
|
1124
|
-
pow = Math.pow;
|
|
1125
|
-
function pointX(p) {
|
|
1126
|
-
return p[0];
|
|
1127
|
-
}
|
|
1128
|
-
function pointY(p) {
|
|
1129
|
-
return p[1];
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
// A triangulation is collinear if all its triangles have a non-null area
|
|
1133
|
-
function collinear(d) {
|
|
1134
|
-
const {
|
|
1135
|
-
triangles,
|
|
1136
|
-
coords
|
|
1137
|
-
} = d;
|
|
1138
|
-
for (let i = 0; i < triangles.length; i += 3) {
|
|
1139
|
-
const a = 2 * triangles[i],
|
|
1140
|
-
b = 2 * triangles[i + 1],
|
|
1141
|
-
c = 2 * triangles[i + 2],
|
|
1142
|
-
cross = (coords[c] - coords[a]) * (coords[b + 1] - coords[a + 1]) - (coords[b] - coords[a]) * (coords[c + 1] - coords[a + 1]);
|
|
1143
|
-
if (cross > 1e-10) return false;
|
|
1144
|
-
}
|
|
1145
|
-
return true;
|
|
1146
|
-
}
|
|
1147
|
-
function jitter(x, y, r) {
|
|
1148
|
-
return [x + Math.sin(x + y) * r, y + Math.cos(x - y) * r];
|
|
1149
|
-
}
|
|
1150
|
-
class Delaunay {
|
|
1151
|
-
static from(points, fx = pointX, fy = pointY, that) {
|
|
1152
|
-
return new Delaunay("length" in points ? flatArray(points, fx, fy, that) : Float64Array.from(flatIterable(points, fx, fy, that)));
|
|
1153
|
-
}
|
|
1154
|
-
constructor(points) {
|
|
1155
|
-
this._delaunator = new Delaunator(points);
|
|
1156
|
-
this.inedges = new Int32Array(points.length / 2);
|
|
1157
|
-
this._hullIndex = new Int32Array(points.length / 2);
|
|
1158
|
-
this.points = this._delaunator.coords;
|
|
1159
|
-
this._init();
|
|
1160
|
-
}
|
|
1161
|
-
update() {
|
|
1162
|
-
this._delaunator.update();
|
|
1163
|
-
this._init();
|
|
1164
|
-
return this;
|
|
1165
|
-
}
|
|
1166
|
-
_init() {
|
|
1167
|
-
const d = this._delaunator,
|
|
1168
|
-
points = this.points;
|
|
1169
|
-
|
|
1170
|
-
// check for collinear
|
|
1171
|
-
if (d.hull && d.hull.length > 2 && collinear(d)) {
|
|
1172
|
-
this.collinear = Int32Array.from({
|
|
1173
|
-
length: points.length / 2
|
|
1174
|
-
}, (_, i) => i).sort((i, j) => points[2 * i] - points[2 * j] || points[2 * i + 1] - points[2 * j + 1]); // for exact neighbors
|
|
1175
|
-
const e = this.collinear[0],
|
|
1176
|
-
f = this.collinear[this.collinear.length - 1],
|
|
1177
|
-
bounds = [points[2 * e], points[2 * e + 1], points[2 * f], points[2 * f + 1]],
|
|
1178
|
-
r = 1e-8 * Math.hypot(bounds[3] - bounds[1], bounds[2] - bounds[0]);
|
|
1179
|
-
for (let i = 0, n = points.length / 2; i < n; ++i) {
|
|
1180
|
-
const p = jitter(points[2 * i], points[2 * i + 1], r);
|
|
1181
|
-
points[2 * i] = p[0];
|
|
1182
|
-
points[2 * i + 1] = p[1];
|
|
1183
|
-
}
|
|
1184
|
-
this._delaunator = new Delaunator(points);
|
|
1185
|
-
} else {
|
|
1186
|
-
delete this.collinear;
|
|
1187
|
-
}
|
|
1188
|
-
const halfedges = this.halfedges = this._delaunator.halfedges;
|
|
1189
|
-
const hull = this.hull = this._delaunator.hull;
|
|
1190
|
-
const triangles = this.triangles = this._delaunator.triangles;
|
|
1191
|
-
const inedges = this.inedges.fill(-1);
|
|
1192
|
-
const hullIndex = this._hullIndex.fill(-1);
|
|
1193
|
-
|
|
1194
|
-
// Compute an index from each point to an (arbitrary) incoming halfedge
|
|
1195
|
-
// Used to give the first neighbor of each point; for this reason,
|
|
1196
|
-
// on the hull we give priority to exterior halfedges
|
|
1197
|
-
for (let e = 0, n = halfedges.length; e < n; ++e) {
|
|
1198
|
-
const p = triangles[e % 3 === 2 ? e - 2 : e + 1];
|
|
1199
|
-
if (halfedges[e] === -1 || inedges[p] === -1) inedges[p] = e;
|
|
1200
|
-
}
|
|
1201
|
-
for (let i = 0, n = hull.length; i < n; ++i) {
|
|
1202
|
-
hullIndex[hull[i]] = i;
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
// degenerate case: 1 or 2 (distinct) points
|
|
1206
|
-
if (hull.length <= 2 && hull.length > 0) {
|
|
1207
|
-
this.triangles = new Int32Array(3).fill(-1);
|
|
1208
|
-
this.halfedges = new Int32Array(3).fill(-1);
|
|
1209
|
-
this.triangles[0] = hull[0];
|
|
1210
|
-
inedges[hull[0]] = 1;
|
|
1211
|
-
if (hull.length === 2) {
|
|
1212
|
-
inedges[hull[1]] = 0;
|
|
1213
|
-
this.triangles[1] = hull[1];
|
|
1214
|
-
this.triangles[2] = hull[1];
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
voronoi(bounds) {
|
|
1219
|
-
return new Voronoi(this, bounds);
|
|
1220
|
-
}
|
|
1221
|
-
*neighbors(i) {
|
|
1222
|
-
const {
|
|
1223
|
-
inedges,
|
|
1224
|
-
hull,
|
|
1225
|
-
_hullIndex,
|
|
1226
|
-
halfedges,
|
|
1227
|
-
triangles,
|
|
1228
|
-
collinear
|
|
1229
|
-
} = this;
|
|
1230
|
-
|
|
1231
|
-
// degenerate case with several collinear points
|
|
1232
|
-
if (collinear) {
|
|
1233
|
-
const l = collinear.indexOf(i);
|
|
1234
|
-
if (l > 0) yield collinear[l - 1];
|
|
1235
|
-
if (l < collinear.length - 1) yield collinear[l + 1];
|
|
1236
|
-
return;
|
|
1237
|
-
}
|
|
1238
|
-
const e0 = inedges[i];
|
|
1239
|
-
if (e0 === -1) return; // coincident point
|
|
1240
|
-
let e = e0,
|
|
1241
|
-
p0 = -1;
|
|
1242
|
-
do {
|
|
1243
|
-
yield p0 = triangles[e];
|
|
1244
|
-
e = e % 3 === 2 ? e - 2 : e + 1;
|
|
1245
|
-
if (triangles[e] !== i) return; // bad triangulation
|
|
1246
|
-
e = halfedges[e];
|
|
1247
|
-
if (e === -1) {
|
|
1248
|
-
const p = hull[(_hullIndex[i] + 1) % hull.length];
|
|
1249
|
-
if (p !== p0) yield p;
|
|
1250
|
-
return;
|
|
1251
|
-
}
|
|
1252
|
-
} while (e !== e0);
|
|
1253
|
-
}
|
|
1254
|
-
find(x, y, i = 0) {
|
|
1255
|
-
if ((x = +x, x !== x) || (y = +y, y !== y)) return -1;
|
|
1256
|
-
const i0 = i;
|
|
1257
|
-
let c;
|
|
1258
|
-
while ((c = this._step(i, x, y)) >= 0 && c !== i && c !== i0) i = c;
|
|
1259
|
-
return c;
|
|
1260
|
-
}
|
|
1261
|
-
_step(i, x, y) {
|
|
1262
|
-
const {
|
|
1263
|
-
inedges,
|
|
1264
|
-
hull,
|
|
1265
|
-
_hullIndex,
|
|
1266
|
-
halfedges,
|
|
1267
|
-
triangles,
|
|
1268
|
-
points
|
|
1269
|
-
} = this;
|
|
1270
|
-
if (inedges[i] === -1 || !points.length) return (i + 1) % (points.length >> 1);
|
|
1271
|
-
let c = i;
|
|
1272
|
-
let dc = pow(x - points[i * 2], 2) + pow(y - points[i * 2 + 1], 2);
|
|
1273
|
-
const e0 = inedges[i];
|
|
1274
|
-
let e = e0;
|
|
1275
|
-
do {
|
|
1276
|
-
let t = triangles[e];
|
|
1277
|
-
const dt = pow(x - points[t * 2], 2) + pow(y - points[t * 2 + 1], 2);
|
|
1278
|
-
if (dt < dc) dc = dt, c = t;
|
|
1279
|
-
e = e % 3 === 2 ? e - 2 : e + 1;
|
|
1280
|
-
if (triangles[e] !== i) break; // bad triangulation
|
|
1281
|
-
e = halfedges[e];
|
|
1282
|
-
if (e === -1) {
|
|
1283
|
-
e = hull[(_hullIndex[i] + 1) % hull.length];
|
|
1284
|
-
if (e !== t) {
|
|
1285
|
-
if (pow(x - points[e * 2], 2) + pow(y - points[e * 2 + 1], 2) < dc) return e;
|
|
1286
|
-
}
|
|
1287
|
-
break;
|
|
1288
|
-
}
|
|
1289
|
-
} while (e !== e0);
|
|
1290
|
-
return c;
|
|
1291
|
-
}
|
|
1292
|
-
render(context) {
|
|
1293
|
-
const buffer = context == null ? context = new Path() : undefined;
|
|
1294
|
-
const {
|
|
1295
|
-
points,
|
|
1296
|
-
halfedges,
|
|
1297
|
-
triangles
|
|
1298
|
-
} = this;
|
|
1299
|
-
for (let i = 0, n = halfedges.length; i < n; ++i) {
|
|
1300
|
-
const j = halfedges[i];
|
|
1301
|
-
if (j < i) continue;
|
|
1302
|
-
const ti = triangles[i] * 2;
|
|
1303
|
-
const tj = triangles[j] * 2;
|
|
1304
|
-
context.moveTo(points[ti], points[ti + 1]);
|
|
1305
|
-
context.lineTo(points[tj], points[tj + 1]);
|
|
1306
|
-
}
|
|
1307
|
-
this.renderHull(context);
|
|
1308
|
-
return buffer && buffer.value();
|
|
1309
|
-
}
|
|
1310
|
-
renderPoints(context, r) {
|
|
1311
|
-
if (r === undefined && (!context || typeof context.moveTo !== "function")) r = context, context = null;
|
|
1312
|
-
r = r == undefined ? 2 : +r;
|
|
1313
|
-
const buffer = context == null ? context = new Path() : undefined;
|
|
1314
|
-
const {
|
|
1315
|
-
points
|
|
1316
|
-
} = this;
|
|
1317
|
-
for (let i = 0, n = points.length; i < n; i += 2) {
|
|
1318
|
-
const x = points[i],
|
|
1319
|
-
y = points[i + 1];
|
|
1320
|
-
context.moveTo(x + r, y);
|
|
1321
|
-
context.arc(x, y, r, 0, tau);
|
|
1322
|
-
}
|
|
1323
|
-
return buffer && buffer.value();
|
|
1324
|
-
}
|
|
1325
|
-
renderHull(context) {
|
|
1326
|
-
const buffer = context == null ? context = new Path() : undefined;
|
|
1327
|
-
const {
|
|
1328
|
-
hull,
|
|
1329
|
-
points
|
|
1330
|
-
} = this;
|
|
1331
|
-
const h = hull[0] * 2,
|
|
1332
|
-
n = hull.length;
|
|
1333
|
-
context.moveTo(points[h], points[h + 1]);
|
|
1334
|
-
for (let i = 1; i < n; ++i) {
|
|
1335
|
-
const h = 2 * hull[i];
|
|
1336
|
-
context.lineTo(points[h], points[h + 1]);
|
|
1337
|
-
}
|
|
1338
|
-
context.closePath();
|
|
1339
|
-
return buffer && buffer.value();
|
|
1340
|
-
}
|
|
1341
|
-
hullPolygon() {
|
|
1342
|
-
const polygon = new Polygon();
|
|
1343
|
-
this.renderHull(polygon);
|
|
1344
|
-
return polygon.value();
|
|
1345
|
-
}
|
|
1346
|
-
renderTriangle(i, context) {
|
|
1347
|
-
const buffer = context == null ? context = new Path() : undefined;
|
|
1348
|
-
const {
|
|
1349
|
-
points,
|
|
1350
|
-
triangles
|
|
1351
|
-
} = this;
|
|
1352
|
-
const t0 = triangles[i *= 3] * 2;
|
|
1353
|
-
const t1 = triangles[i + 1] * 2;
|
|
1354
|
-
const t2 = triangles[i + 2] * 2;
|
|
1355
|
-
context.moveTo(points[t0], points[t0 + 1]);
|
|
1356
|
-
context.lineTo(points[t1], points[t1 + 1]);
|
|
1357
|
-
context.lineTo(points[t2], points[t2 + 1]);
|
|
1358
|
-
context.closePath();
|
|
1359
|
-
return buffer && buffer.value();
|
|
1360
|
-
}
|
|
1361
|
-
*trianglePolygons() {
|
|
1362
|
-
const {
|
|
1363
|
-
triangles
|
|
1364
|
-
} = this;
|
|
1365
|
-
for (let i = 0, n = triangles.length / 3; i < n; ++i) {
|
|
1366
|
-
yield this.trianglePolygon(i);
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
trianglePolygon(i) {
|
|
1370
|
-
const polygon = new Polygon();
|
|
1371
|
-
this.renderTriangle(i, polygon);
|
|
1372
|
-
return polygon.value();
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
function flatArray(points, fx, fy, that) {
|
|
1376
|
-
const n = points.length;
|
|
1377
|
-
const array = new Float64Array(n * 2);
|
|
1378
|
-
for (let i = 0; i < n; ++i) {
|
|
1379
|
-
const p = points[i];
|
|
1380
|
-
array[i * 2] = fx.call(that, p, i, points);
|
|
1381
|
-
array[i * 2 + 1] = fy.call(that, p, i, points);
|
|
1382
|
-
}
|
|
1383
|
-
return array;
|
|
1384
|
-
}
|
|
1385
|
-
function* flatIterable(points, fx, fy, that) {
|
|
1386
|
-
let i = 0;
|
|
1387
|
-
for (const p of points) {
|
|
1388
|
-
yield fx.call(that, p, i, points);
|
|
1389
|
-
yield fy.call(that, p, i, points);
|
|
1390
|
-
++i;
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
exports.Delaunay = Delaunay;
|
|
1394
|
-
exports.Voronoi = Voronoi;
|
|
1395
|
-
Object.defineProperty(exports, '__esModule', {
|
|
1396
|
-
value: true
|
|
1397
|
-
});
|
|
1398
|
-
});
|