source: node_modules/delaunator/delaunator.js@ e4c61dd

Last change on this file since e4c61dd was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 22.7 KB
Line 
1(function (global, factory) {
2typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3typeof define === 'function' && define.amd ? define(factory) :
4(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Delaunator = factory());
5})(this, (function () { 'use strict';
6
7const epsilon = 1.1102230246251565e-16;
8const splitter = 134217729;
9const resulterrbound = (3 + 8 * epsilon) * epsilon;
10
11// fast_expansion_sum_zeroelim routine from oritinal code
12function sum(elen, e, flen, f, h) {
13 let Q, Qnew, hh, bvirt;
14 let enow = e[0];
15 let fnow = f[0];
16 let eindex = 0;
17 let findex = 0;
18 if ((fnow > enow) === (fnow > -enow)) {
19 Q = enow;
20 enow = e[++eindex];
21 } else {
22 Q = fnow;
23 fnow = f[++findex];
24 }
25 let hindex = 0;
26 if (eindex < elen && findex < flen) {
27 if ((fnow > enow) === (fnow > -enow)) {
28 Qnew = enow + Q;
29 hh = Q - (Qnew - enow);
30 enow = e[++eindex];
31 } else {
32 Qnew = fnow + Q;
33 hh = Q - (Qnew - fnow);
34 fnow = f[++findex];
35 }
36 Q = Qnew;
37 if (hh !== 0) {
38 h[hindex++] = hh;
39 }
40 while (eindex < elen && findex < flen) {
41 if ((fnow > enow) === (fnow > -enow)) {
42 Qnew = Q + enow;
43 bvirt = Qnew - Q;
44 hh = Q - (Qnew - bvirt) + (enow - bvirt);
45 enow = e[++eindex];
46 } else {
47 Qnew = Q + fnow;
48 bvirt = Qnew - Q;
49 hh = Q - (Qnew - bvirt) + (fnow - bvirt);
50 fnow = f[++findex];
51 }
52 Q = Qnew;
53 if (hh !== 0) {
54 h[hindex++] = hh;
55 }
56 }
57 }
58 while (eindex < elen) {
59 Qnew = Q + enow;
60 bvirt = Qnew - Q;
61 hh = Q - (Qnew - bvirt) + (enow - bvirt);
62 enow = e[++eindex];
63 Q = Qnew;
64 if (hh !== 0) {
65 h[hindex++] = hh;
66 }
67 }
68 while (findex < flen) {
69 Qnew = Q + fnow;
70 bvirt = Qnew - Q;
71 hh = Q - (Qnew - bvirt) + (fnow - bvirt);
72 fnow = f[++findex];
73 Q = Qnew;
74 if (hh !== 0) {
75 h[hindex++] = hh;
76 }
77 }
78 if (Q !== 0 || hindex === 0) {
79 h[hindex++] = Q;
80 }
81 return hindex;
82}
83
84function estimate(elen, e) {
85 let Q = e[0];
86 for (let i = 1; i < elen; i++) Q += e[i];
87 return Q;
88}
89
90function vec(n) {
91 return new Float64Array(n);
92}
93
94const ccwerrboundA = (3 + 16 * epsilon) * epsilon;
95const ccwerrboundB = (2 + 12 * epsilon) * epsilon;
96const ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;
97
98const B = vec(4);
99const C1 = vec(8);
100const C2 = vec(12);
101const D = vec(16);
102const u = vec(4);
103
104function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {
105 let acxtail, acytail, bcxtail, bcytail;
106 let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;
107
108 const acx = ax - cx;
109 const bcx = bx - cx;
110 const acy = ay - cy;
111 const bcy = by - cy;
112
113 s1 = acx * bcy;
114 c = splitter * acx;
115 ahi = c - (c - acx);
116 alo = acx - ahi;
117 c = splitter * bcy;
118 bhi = c - (c - bcy);
119 blo = bcy - bhi;
120 s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
121 t1 = acy * bcx;
122 c = splitter * acy;
123 ahi = c - (c - acy);
124 alo = acy - ahi;
125 c = splitter * bcx;
126 bhi = c - (c - bcx);
127 blo = bcx - bhi;
128 t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
129 _i = s0 - t0;
130 bvirt = s0 - _i;
131 B[0] = s0 - (_i + bvirt) + (bvirt - t0);
132 _j = s1 + _i;
133 bvirt = _j - s1;
134 _0 = s1 - (_j - bvirt) + (_i - bvirt);
135 _i = _0 - t1;
136 bvirt = _0 - _i;
137 B[1] = _0 - (_i + bvirt) + (bvirt - t1);
138 u3 = _j + _i;
139 bvirt = u3 - _j;
140 B[2] = _j - (u3 - bvirt) + (_i - bvirt);
141 B[3] = u3;
142
143 let det = estimate(4, B);
144 let errbound = ccwerrboundB * detsum;
145 if (det >= errbound || -det >= errbound) {
146 return det;
147 }
148
149 bvirt = ax - acx;
150 acxtail = ax - (acx + bvirt) + (bvirt - cx);
151 bvirt = bx - bcx;
152 bcxtail = bx - (bcx + bvirt) + (bvirt - cx);
153 bvirt = ay - acy;
154 acytail = ay - (acy + bvirt) + (bvirt - cy);
155 bvirt = by - bcy;
156 bcytail = by - (bcy + bvirt) + (bvirt - cy);
157
158 if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {
159 return det;
160 }
161
162 errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);
163 det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
164 if (det >= errbound || -det >= errbound) return det;
165
166 s1 = acxtail * bcy;
167 c = splitter * acxtail;
168 ahi = c - (c - acxtail);
169 alo = acxtail - ahi;
170 c = splitter * bcy;
171 bhi = c - (c - bcy);
172 blo = bcy - bhi;
173 s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
174 t1 = acytail * bcx;
175 c = splitter * acytail;
176 ahi = c - (c - acytail);
177 alo = acytail - ahi;
178 c = splitter * bcx;
179 bhi = c - (c - bcx);
180 blo = bcx - bhi;
181 t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
182 _i = s0 - t0;
183 bvirt = s0 - _i;
184 u[0] = s0 - (_i + bvirt) + (bvirt - t0);
185 _j = s1 + _i;
186 bvirt = _j - s1;
187 _0 = s1 - (_j - bvirt) + (_i - bvirt);
188 _i = _0 - t1;
189 bvirt = _0 - _i;
190 u[1] = _0 - (_i + bvirt) + (bvirt - t1);
191 u3 = _j + _i;
192 bvirt = u3 - _j;
193 u[2] = _j - (u3 - bvirt) + (_i - bvirt);
194 u[3] = u3;
195 const C1len = sum(4, B, 4, u, C1);
196
197 s1 = acx * bcytail;
198 c = splitter * acx;
199 ahi = c - (c - acx);
200 alo = acx - ahi;
201 c = splitter * bcytail;
202 bhi = c - (c - bcytail);
203 blo = bcytail - bhi;
204 s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
205 t1 = acy * bcxtail;
206 c = splitter * acy;
207 ahi = c - (c - acy);
208 alo = acy - ahi;
209 c = splitter * bcxtail;
210 bhi = c - (c - bcxtail);
211 blo = bcxtail - bhi;
212 t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
213 _i = s0 - t0;
214 bvirt = s0 - _i;
215 u[0] = s0 - (_i + bvirt) + (bvirt - t0);
216 _j = s1 + _i;
217 bvirt = _j - s1;
218 _0 = s1 - (_j - bvirt) + (_i - bvirt);
219 _i = _0 - t1;
220 bvirt = _0 - _i;
221 u[1] = _0 - (_i + bvirt) + (bvirt - t1);
222 u3 = _j + _i;
223 bvirt = u3 - _j;
224 u[2] = _j - (u3 - bvirt) + (_i - bvirt);
225 u[3] = u3;
226 const C2len = sum(C1len, C1, 4, u, C2);
227
228 s1 = acxtail * bcytail;
229 c = splitter * acxtail;
230 ahi = c - (c - acxtail);
231 alo = acxtail - ahi;
232 c = splitter * bcytail;
233 bhi = c - (c - bcytail);
234 blo = bcytail - bhi;
235 s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
236 t1 = acytail * bcxtail;
237 c = splitter * acytail;
238 ahi = c - (c - acytail);
239 alo = acytail - ahi;
240 c = splitter * bcxtail;
241 bhi = c - (c - bcxtail);
242 blo = bcxtail - bhi;
243 t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
244 _i = s0 - t0;
245 bvirt = s0 - _i;
246 u[0] = s0 - (_i + bvirt) + (bvirt - t0);
247 _j = s1 + _i;
248 bvirt = _j - s1;
249 _0 = s1 - (_j - bvirt) + (_i - bvirt);
250 _i = _0 - t1;
251 bvirt = _0 - _i;
252 u[1] = _0 - (_i + bvirt) + (bvirt - t1);
253 u3 = _j + _i;
254 bvirt = u3 - _j;
255 u[2] = _j - (u3 - bvirt) + (_i - bvirt);
256 u[3] = u3;
257 const Dlen = sum(C2len, C2, 4, u, D);
258
259 return D[Dlen - 1];
260}
261
262function orient2d(ax, ay, bx, by, cx, cy) {
263 const detleft = (ay - cy) * (bx - cx);
264 const detright = (ax - cx) * (by - cy);
265 const det = detleft - detright;
266
267 const detsum = Math.abs(detleft + detright);
268 if (Math.abs(det) >= ccwerrboundA * detsum) return det;
269
270 return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);
271}
272
273const EPSILON = Math.pow(2, -52);
274const EDGE_STACK = new Uint32Array(512);
275
276class Delaunator {
277
278 static from(points, getX = defaultGetX, getY = defaultGetY) {
279 const n = points.length;
280 const coords = new Float64Array(n * 2);
281
282 for (let i = 0; i < n; i++) {
283 const p = points[i];
284 coords[2 * i] = getX(p);
285 coords[2 * i + 1] = getY(p);
286 }
287
288 return new Delaunator(coords);
289 }
290
291 constructor(coords) {
292 const n = coords.length >> 1;
293 if (n > 0 && typeof coords[0] !== 'number') throw new Error('Expected coords to contain numbers.');
294
295 this.coords = coords;
296
297 // arrays that will store the triangulation graph
298 const maxTriangles = Math.max(2 * n - 5, 0);
299 this._triangles = new Uint32Array(maxTriangles * 3);
300 this._halfedges = new Int32Array(maxTriangles * 3);
301
302 // temporary arrays for tracking the edges of the advancing convex hull
303 this._hashSize = Math.ceil(Math.sqrt(n));
304 this._hullPrev = new Uint32Array(n); // edge to prev edge
305 this._hullNext = new Uint32Array(n); // edge to next edge
306 this._hullTri = new Uint32Array(n); // edge to adjacent triangle
307 this._hullHash = new Int32Array(this._hashSize); // angular edge hash
308
309 // temporary arrays for sorting points
310 this._ids = new Uint32Array(n);
311 this._dists = new Float64Array(n);
312
313 this.update();
314 }
315
316 update() {
317 const {coords, _hullPrev: hullPrev, _hullNext: hullNext, _hullTri: hullTri, _hullHash: hullHash} = this;
318 const n = coords.length >> 1;
319
320 // populate an array of point indices; calculate input data bbox
321 let minX = Infinity;
322 let minY = Infinity;
323 let maxX = -Infinity;
324 let maxY = -Infinity;
325
326 for (let i = 0; i < n; i++) {
327 const x = coords[2 * i];
328 const y = coords[2 * i + 1];
329 if (x < minX) minX = x;
330 if (y < minY) minY = y;
331 if (x > maxX) maxX = x;
332 if (y > maxY) maxY = y;
333 this._ids[i] = i;
334 }
335 const cx = (minX + maxX) / 2;
336 const cy = (minY + maxY) / 2;
337
338 let i0, i1, i2;
339
340 // pick a seed point close to the center
341 for (let i = 0, minDist = Infinity; i < n; i++) {
342 const d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]);
343 if (d < minDist) {
344 i0 = i;
345 minDist = d;
346 }
347 }
348 const i0x = coords[2 * i0];
349 const i0y = coords[2 * i0 + 1];
350
351 // find the point closest to the seed
352 for (let i = 0, minDist = Infinity; i < n; i++) {
353 if (i === i0) continue;
354 const d = dist(i0x, i0y, coords[2 * i], coords[2 * i + 1]);
355 if (d < minDist && d > 0) {
356 i1 = i;
357 minDist = d;
358 }
359 }
360 let i1x = coords[2 * i1];
361 let i1y = coords[2 * i1 + 1];
362
363 let minRadius = Infinity;
364
365 // find the third point which forms the smallest circumcircle with the first two
366 for (let i = 0; i < n; i++) {
367 if (i === i0 || i === i1) continue;
368 const r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i], coords[2 * i + 1]);
369 if (r < minRadius) {
370 i2 = i;
371 minRadius = r;
372 }
373 }
374 let i2x = coords[2 * i2];
375 let i2y = coords[2 * i2 + 1];
376
377 if (minRadius === Infinity) {
378 // order collinear points by dx (or dy if all x are identical)
379 // and return the list as a hull
380 for (let i = 0; i < n; i++) {
381 this._dists[i] = (coords[2 * i] - coords[0]) || (coords[2 * i + 1] - coords[1]);
382 }
383 quicksort(this._ids, this._dists, 0, n - 1);
384 const hull = new Uint32Array(n);
385 let j = 0;
386 for (let i = 0, d0 = -Infinity; i < n; i++) {
387 const id = this._ids[i];
388 const d = this._dists[id];
389 if (d > d0) {
390 hull[j++] = id;
391 d0 = d;
392 }
393 }
394 this.hull = hull.subarray(0, j);
395 this.triangles = new Uint32Array(0);
396 this.halfedges = new Uint32Array(0);
397 return;
398 }
399
400 // swap the order of the seed points for counter-clockwise orientation
401 if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) {
402 const i = i1;
403 const x = i1x;
404 const y = i1y;
405 i1 = i2;
406 i1x = i2x;
407 i1y = i2y;
408 i2 = i;
409 i2x = x;
410 i2y = y;
411 }
412
413 const center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
414 this._cx = center.x;
415 this._cy = center.y;
416
417 for (let i = 0; i < n; i++) {
418 this._dists[i] = dist(coords[2 * i], coords[2 * i + 1], center.x, center.y);
419 }
420
421 // sort the points by distance from the seed triangle circumcenter
422 quicksort(this._ids, this._dists, 0, n - 1);
423
424 // set up the seed triangle as the starting hull
425 this._hullStart = i0;
426 let hullSize = 3;
427
428 hullNext[i0] = hullPrev[i2] = i1;
429 hullNext[i1] = hullPrev[i0] = i2;
430 hullNext[i2] = hullPrev[i1] = i0;
431
432 hullTri[i0] = 0;
433 hullTri[i1] = 1;
434 hullTri[i2] = 2;
435
436 hullHash.fill(-1);
437 hullHash[this._hashKey(i0x, i0y)] = i0;
438 hullHash[this._hashKey(i1x, i1y)] = i1;
439 hullHash[this._hashKey(i2x, i2y)] = i2;
440
441 this.trianglesLen = 0;
442 this._addTriangle(i0, i1, i2, -1, -1, -1);
443
444 for (let k = 0, xp, yp; k < this._ids.length; k++) {
445 const i = this._ids[k];
446 const x = coords[2 * i];
447 const y = coords[2 * i + 1];
448
449 // skip near-duplicate points
450 if (k > 0 && Math.abs(x - xp) <= EPSILON && Math.abs(y - yp) <= EPSILON) continue;
451 xp = x;
452 yp = y;
453
454 // skip seed triangle points
455 if (i === i0 || i === i1 || i === i2) continue;
456
457 // find a visible edge on the convex hull using edge hash
458 let start = 0;
459 for (let j = 0, key = this._hashKey(x, y); j < this._hashSize; j++) {
460 start = hullHash[(key + j) % this._hashSize];
461 if (start !== -1 && start !== hullNext[start]) break;
462 }
463
464 start = hullPrev[start];
465 let e = start, q;
466 while (q = hullNext[e], orient2d(x, y, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1]) >= 0) {
467 e = q;
468 if (e === start) {
469 e = -1;
470 break;
471 }
472 }
473 if (e === -1) continue; // likely a near-duplicate point; skip it
474
475 // add the first triangle from the point
476 let t = this._addTriangle(e, i, hullNext[e], -1, -1, hullTri[e]);
477
478 // recursively flip triangles from the point until they satisfy the Delaunay condition
479 hullTri[i] = this._legalize(t + 2);
480 hullTri[e] = t; // keep track of boundary triangles on the hull
481 hullSize++;
482
483 // walk forward through the hull, adding more triangles and flipping recursively
484 let n = hullNext[e];
485 while (q = hullNext[n], orient2d(x, y, coords[2 * n], coords[2 * n + 1], coords[2 * q], coords[2 * q + 1]) < 0) {
486 t = this._addTriangle(n, i, q, hullTri[i], -1, hullTri[n]);
487 hullTri[i] = this._legalize(t + 2);
488 hullNext[n] = n; // mark as removed
489 hullSize--;
490 n = q;
491 }
492
493 // walk backward from the other side, adding more triangles and flipping
494 if (e === start) {
495 while (q = hullPrev[e], orient2d(x, y, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1]) < 0) {
496 t = this._addTriangle(q, i, e, -1, hullTri[e], hullTri[q]);
497 this._legalize(t + 2);
498 hullTri[q] = t;
499 hullNext[e] = e; // mark as removed
500 hullSize--;
501 e = q;
502 }
503 }
504
505 // update the hull indices
506 this._hullStart = hullPrev[i] = e;
507 hullNext[e] = hullPrev[n] = i;
508 hullNext[i] = n;
509
510 // save the two new edges in the hash table
511 hullHash[this._hashKey(x, y)] = i;
512 hullHash[this._hashKey(coords[2 * e], coords[2 * e + 1])] = e;
513 }
514
515 this.hull = new Uint32Array(hullSize);
516 for (let i = 0, e = this._hullStart; i < hullSize; i++) {
517 this.hull[i] = e;
518 e = hullNext[e];
519 }
520
521 // trim typed triangle mesh arrays
522 this.triangles = this._triangles.subarray(0, this.trianglesLen);
523 this.halfedges = this._halfedges.subarray(0, this.trianglesLen);
524 }
525
526 _hashKey(x, y) {
527 return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize;
528 }
529
530 _legalize(a) {
531 const {_triangles: triangles, _halfedges: halfedges, coords} = this;
532
533 let i = 0;
534 let ar = 0;
535
536 // recursion eliminated with a fixed-size stack
537 while (true) {
538 const b = halfedges[a];
539
540 /* if the pair of triangles doesn't satisfy the Delaunay condition
541 * (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
542 * then do the same check/flip recursively for the new pair of triangles
543 *
544 * pl pl
545 * /||\ / \
546 * al/ || \bl al/ \a
547 * / || \ / \
548 * / a||b \ flip /___ar___\
549 * p0\ || /p1 => p0\---bl---/p1
550 * \ || / \ /
551 * ar\ || /br b\ /br
552 * \||/ \ /
553 * pr pr
554 */
555 const a0 = a - a % 3;
556 ar = a0 + (a + 2) % 3;
557
558 if (b === -1) { // convex hull edge
559 if (i === 0) break;
560 a = EDGE_STACK[--i];
561 continue;
562 }
563
564 const b0 = b - b % 3;
565 const al = a0 + (a + 1) % 3;
566 const bl = b0 + (b + 2) % 3;
567
568 const p0 = triangles[ar];
569 const pr = triangles[a];
570 const pl = triangles[al];
571 const p1 = triangles[bl];
572
573 const illegal = inCircle(
574 coords[2 * p0], coords[2 * p0 + 1],
575 coords[2 * pr], coords[2 * pr + 1],
576 coords[2 * pl], coords[2 * pl + 1],
577 coords[2 * p1], coords[2 * p1 + 1]);
578
579 if (illegal) {
580 triangles[a] = p1;
581 triangles[b] = p0;
582
583 const hbl = halfedges[bl];
584
585 // edge swapped on the other side of the hull (rare); fix the halfedge reference
586 if (hbl === -1) {
587 let e = this._hullStart;
588 do {
589 if (this._hullTri[e] === bl) {
590 this._hullTri[e] = a;
591 break;
592 }
593 e = this._hullPrev[e];
594 } while (e !== this._hullStart);
595 }
596 this._link(a, hbl);
597 this._link(b, halfedges[ar]);
598 this._link(ar, bl);
599
600 const br = b0 + (b + 1) % 3;
601
602 // don't worry about hitting the cap: it can only happen on extremely degenerate input
603 if (i < EDGE_STACK.length) {
604 EDGE_STACK[i++] = br;
605 }
606 } else {
607 if (i === 0) break;
608 a = EDGE_STACK[--i];
609 }
610 }
611
612 return ar;
613 }
614
615 _link(a, b) {
616 this._halfedges[a] = b;
617 if (b !== -1) this._halfedges[b] = a;
618 }
619
620 // add a new triangle given vertex indices and adjacent half-edge ids
621 _addTriangle(i0, i1, i2, a, b, c) {
622 const t = this.trianglesLen;
623
624 this._triangles[t] = i0;
625 this._triangles[t + 1] = i1;
626 this._triangles[t + 2] = i2;
627
628 this._link(t, a);
629 this._link(t + 1, b);
630 this._link(t + 2, c);
631
632 this.trianglesLen += 3;
633
634 return t;
635 }
636}
637
638// monotonically increases with real angle, but doesn't need expensive trigonometry
639function pseudoAngle(dx, dy) {
640 const p = dx / (Math.abs(dx) + Math.abs(dy));
641 return (dy > 0 ? 3 - p : 1 + p) / 4; // [0..1]
642}
643
644function dist(ax, ay, bx, by) {
645 const dx = ax - bx;
646 const dy = ay - by;
647 return dx * dx + dy * dy;
648}
649
650function inCircle(ax, ay, bx, by, cx, cy, px, py) {
651 const dx = ax - px;
652 const dy = ay - py;
653 const ex = bx - px;
654 const ey = by - py;
655 const fx = cx - px;
656 const fy = cy - py;
657
658 const ap = dx * dx + dy * dy;
659 const bp = ex * ex + ey * ey;
660 const cp = fx * fx + fy * fy;
661
662 return dx * (ey * cp - bp * fy) -
663 dy * (ex * cp - bp * fx) +
664 ap * (ex * fy - ey * fx) < 0;
665}
666
667function circumradius(ax, ay, bx, by, cx, cy) {
668 const dx = bx - ax;
669 const dy = by - ay;
670 const ex = cx - ax;
671 const ey = cy - ay;
672
673 const bl = dx * dx + dy * dy;
674 const cl = ex * ex + ey * ey;
675 const d = 0.5 / (dx * ey - dy * ex);
676
677 const x = (ey * bl - dy * cl) * d;
678 const y = (dx * cl - ex * bl) * d;
679
680 return x * x + y * y;
681}
682
683function circumcenter(ax, ay, bx, by, cx, cy) {
684 const dx = bx - ax;
685 const dy = by - ay;
686 const ex = cx - ax;
687 const ey = cy - ay;
688
689 const bl = dx * dx + dy * dy;
690 const cl = ex * ex + ey * ey;
691 const d = 0.5 / (dx * ey - dy * ex);
692
693 const x = ax + (ey * bl - dy * cl) * d;
694 const y = ay + (dx * cl - ex * bl) * d;
695
696 return {x, y};
697}
698
699function quicksort(ids, dists, left, right) {
700 if (right - left <= 20) {
701 for (let i = left + 1; i <= right; i++) {
702 const temp = ids[i];
703 const tempDist = dists[temp];
704 let j = i - 1;
705 while (j >= left && dists[ids[j]] > tempDist) ids[j + 1] = ids[j--];
706 ids[j + 1] = temp;
707 }
708 } else {
709 const median = (left + right) >> 1;
710 let i = left + 1;
711 let j = right;
712 swap(ids, median, i);
713 if (dists[ids[left]] > dists[ids[right]]) swap(ids, left, right);
714 if (dists[ids[i]] > dists[ids[right]]) swap(ids, i, right);
715 if (dists[ids[left]] > dists[ids[i]]) swap(ids, left, i);
716
717 const temp = ids[i];
718 const tempDist = dists[temp];
719 while (true) {
720 do i++; while (dists[ids[i]] < tempDist);
721 do j--; while (dists[ids[j]] > tempDist);
722 if (j < i) break;
723 swap(ids, i, j);
724 }
725 ids[left + 1] = ids[j];
726 ids[j] = temp;
727
728 if (right - i + 1 >= j - left) {
729 quicksort(ids, dists, i, right);
730 quicksort(ids, dists, left, j - 1);
731 } else {
732 quicksort(ids, dists, left, j - 1);
733 quicksort(ids, dists, i, right);
734 }
735 }
736}
737
738function swap(arr, i, j) {
739 const tmp = arr[i];
740 arr[i] = arr[j];
741 arr[j] = tmp;
742}
743
744function defaultGetX(p) {
745 return p[0];
746}
747function defaultGetY(p) {
748 return p[1];
749}
750
751return Delaunator;
752
753}));
Note: See TracBrowser for help on using the repository browser.