feat: 氧化铝数字孪生系统监控大屏完成

This commit is contained in:
2026-04-08 21:44:08 +08:00
commit a48babc68d
67606 changed files with 3337335 additions and 0 deletions

15
node_modules/delaunator/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,15 @@
ISC License
Copyright (c) 2026, Mapbox
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

157
node_modules/delaunator/README.md generated vendored Normal file
View File

@@ -0,0 +1,157 @@
# Delaunator [![CI](https://github.com/mapbox/delaunator/actions/workflows/node.yml/badge.svg)](https://github.com/mapbox/delaunator/actions/workflows/node.yml) [![](https://img.shields.io/badge/simply-awesome-brightgreen.svg)](https://github.com/mourner/projects) [![](https://badgen.net/bundlephobia/minzip/delaunator)](https://unpkg.com/delaunator)
An incredibly fast and robust JavaScript library for
[Delaunay triangulation](https://en.wikipedia.org/wiki/Delaunay_triangulation) of 2D points.
- [Interactive Demo](https://mapbox.github.io/delaunator/demo.html)
- [Guide to data structures](https://mapbox.github.io/delaunator/)
<img src="delaunator.png" alt="Delaunay triangulation example" width="600" />
### Projects based on Delaunator
- [d3-delaunay](https://github.com/d3/d3-delaunay) for Voronoi diagrams, search, traversal and rendering (a part of [D3](https://d3js.org)).
- [d3-geo-voronoi](https://github.com/Fil/d3-geo-voronoi) for Delaunay triangulations and Voronoi diagrams on a sphere (e.g. for geographic locations).
## Example
```js
const coords = [377,479, 453,434, 326,387, 444,359, 511,389,
586,429, 470,315, 622,493, 627,367, 570,314];
const delaunay = new Delaunator(coords);
console.log(delaunay.triangles);
// [4,3,1, 4,6,3, 1,5,4, 4,9,6, 2,0,1, 1,7,5,
// 5,9,4, 6,2,3, 3,2,1, 5,8,9, 0,7,1, 5,7,8]
```
<img src="docs/example.png" alt="Delaunay triangulation example with labeled points" width="600" />
## Install
Install with NPM (`npm install delaunator`) or Yarn (`yarn add delaunator`), then import as an ES module:
```js
import Delaunator from 'delaunator';
```
To use as a module in a browser:
```html
<script type="module">
import Delaunator from 'https://cdn.skypack.dev/delaunator@5.0.0';
</script>
```
Or use a browser UMD build that exposes a `Delaunator` global variable:
```html
<script src="https://unpkg.com/delaunator@5.0.0/delaunator.min.js"></script>
```
## API Reference
#### new Delaunator(coords)
Constructs a delaunay triangulation object given an array of point coordinates of the form:
`[x0, y0, x1, y1, ...]` (use a typed array for best performance).
#### Delaunator.from(points[, getX, getY])
Constructs a delaunay triangulation object given an array of points (`[x, y]` by default).
`getX` and `getY` are optional functions of the form `(point) => value` for custom point formats.
Duplicate points are skipped.
#### delaunay.triangles
A `Uint32Array` array of triangle vertex indices (each group of three numbers forms a triangle).
All triangles are directed counterclockwise.
To get the coordinates of all triangles when using `Delaunator.from(points)`, use:
```js
for (let i = 0; i < triangles.length; i += 3) {
coordinates.push([
points[triangles[i]],
points[triangles[i + 1]],
points[triangles[i + 2]]
]);
}
```
To get the coordinates of all triangles when using `new Delaunator(coords)`, use:
```js
for (let i = 0; i < triangles.length; i += 3) {
coordinates.push([
[coords[2 * triangles[i]], coords[2 * triangles[i] + 1]],
[coords[2 * triangles[i + 1]], coords[2 * triangles[i + 1] + 1]],
[coords[2 * triangles[i + 2]], coords[2 * triangles[i + 2] + 1]]
]);
}
```
#### delaunay.halfedges
A `Int32Array` array of triangle half-edge indices that allows you to traverse the triangulation.
`i`-th half-edge in the array corresponds to vertex `triangles[i]` the half-edge is coming from.
`halfedges[i]` is the index of a twin half-edge in an adjacent triangle
(or `-1` for outer half-edges on the convex hull).
The flat array-based data structures might be counterintuitive,
but they're one of the key reasons this library is fast.
#### delaunay.hull
A `Uint32Array` array of indices that reference points on the convex hull of the input data, counter-clockwise.
#### delaunay.coords
An array of input coordinates in the form `[x0, y0, x1, y1, ....]`,
of the type provided in the constructor (or `Float64Array` if you used `Delaunator.from`).
#### delaunay.update()
Updates the triangulation if you modified `delaunay.coords` values in place, avoiding expensive memory allocations.
Useful for iterative relaxation algorithms such as [Lloyd's](https://en.wikipedia.org/wiki/Lloyd%27s_algorithm).
## Performance
Benchmark results against other Delaunay JS libraries
(`npm run bench` on Macbook Pro Retina 15" 2017, Node v10.10.0):
&nbsp; | uniform 100k | gauss 100k | grid 100k | degen 100k | uniform 1&nbsp;million | gauss 1&nbsp;million | grid 1&nbsp;million | degen 1&nbsp;million
:-- | --: | --: | --: | --: | --: | --: | --: | --:
**delaunator** | 82ms | 61ms | 66ms | 25ms | 1.07s | 950ms | 830ms | 278ms
[faster&#8209;delaunay](https://github.com/Bathlamos/delaunay-triangulation) | 473ms | 411ms | 272ms | 68ms | 4.27s | 4.62s | 4.3s | 810ms
[incremental&#8209;delaunay](https://github.com/mikolalysenko/incremental-delaunay) | 547ms | 505ms | 172ms | 528ms | 5.9s | 6.08s | 2.11s | 6.09s
[d3&#8209;voronoi](https://github.com/d3/d3-voronoi) | 972ms | 909ms | 358ms | 720ms | 15.04s | 13.86s | 5.55s | 11.13s
[delaunay&#8209;fast](https://github.com/darkskyapp/delaunay-fast) | 3.8s | 4s | 12.57s | timeout | 132s | 138s | 399s | timeout
[delaunay](https://github.com/darkskyapp/delaunay) | 4.85s | 5.73s | 15.05s | timeout | 156s | 178s | 326s | timeout
[delaunay&#8209;triangulate](https://github.com/mikolalysenko/delaunay-triangulate) | 2.24s | 2.04s | OOM | 1.51s | OOM | OOM | OOM | OOM
[cdt2d](https://github.com/mikolalysenko/cdt2d) | 45s | 51s | 118s | 17s | timeout | timeout | timeout | timeout
## Papers
The algorithm is based on ideas from the following papers:
- [A simple sweep-line Delaunay triangulation algorithm](http://www.academicpub.org/jao/paperInfo.aspx?paperid=15630), 2013, Liu Yonghe, Feng Jinming and Shao Yuehong
- [S-hull: a fast radial sweep-hull routine for Delaunay triangulation](http://www.s-hull.org/paper/s_hull.pdf), 2010, David Sinclair
- [A faster circle-sweep Delaunay triangulation algorithm](http://cglab.ca/~biniaz/papers/Sweep%20Circle.pdf), 2011, Ahmad Biniaz and Gholamhossein Dastghaibyfard
## Robustness
Delaunator should produce valid output even on highly degenerate input. It does so by depending on [robust-predicates](https://github.com/mourner/robust-predicates), a modern port of Jonathan Shewchuk's robust geometric predicates, an industry standard in computational geometry.
## Ports to other languages
- [delaunator-rs](https://github.com/mourner/delaunator-rs) (Rust)
- [fogleman/delaunay](https://github.com/fogleman/delaunay) (Go)
- [delaunator-cpp](https://github.com/abellgithub/delaunator-cpp) (C++)
- [delaunator-sharp](https://github.com/nol1fe/delaunator-sharp) (C#)
- [delaunator-ruby](https://github.com/hendrixfan/delaunator-ruby) (Ruby)
- [Delaunator-Python](https://github.com/HakanSeven12/Delaunator-Python) (Python)
- [torch-delaunay](https://github.com/ybubnov/torch_delaunay) (Python/Torch)
- [ricardomatias/delaunator](https://github.com/ricardomatias/delaunator) (Kotlin)
- [delaunator-java](https://github.com/waveware4ai/delaunator-java) (Java)
- [delaunay-Stata](https://github.com/asjadnaqvi/stata-delaunay-voronoi) (Stata/Mata)
- [Delaunator.jl](https://github.com/JuliaGeometry/Delaunator.jl) (Julia)

880
node_modules/delaunator/delaunator.js generated vendored Normal file
View File

@@ -0,0 +1,880 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Delaunator = factory());
})(this, (function () { 'use strict';
const epsilon = 1.1102230246251565e-16;
const splitter = 134217729;
const resulterrbound = (3 + 8 * epsilon) * epsilon;
// fast_expansion_sum_zeroelim routine from oritinal code
function sum(elen, e, flen, f, h) {
let Q, Qnew, hh, bvirt;
let enow = e[0];
let fnow = f[0];
let eindex = 0;
let findex = 0;
if ((fnow > enow) === (fnow > -enow)) {
Q = enow;
enow = e[++eindex];
} else {
Q = fnow;
fnow = f[++findex];
}
let hindex = 0;
if (eindex < elen && findex < flen) {
if ((fnow > enow) === (fnow > -enow)) {
Qnew = enow + Q;
hh = Q - (Qnew - enow);
enow = e[++eindex];
} else {
Qnew = fnow + Q;
hh = Q - (Qnew - fnow);
fnow = f[++findex];
}
Q = Qnew;
if (hh !== 0) {
h[hindex++] = hh;
}
while (eindex < elen && findex < flen) {
if ((fnow > enow) === (fnow > -enow)) {
Qnew = Q + enow;
bvirt = Qnew - Q;
hh = Q - (Qnew - bvirt) + (enow - bvirt);
enow = e[++eindex];
} else {
Qnew = Q + fnow;
bvirt = Qnew - Q;
hh = Q - (Qnew - bvirt) + (fnow - bvirt);
fnow = f[++findex];
}
Q = Qnew;
if (hh !== 0) {
h[hindex++] = hh;
}
}
}
while (eindex < elen) {
Qnew = Q + enow;
bvirt = Qnew - Q;
hh = Q - (Qnew - bvirt) + (enow - bvirt);
enow = e[++eindex];
Q = Qnew;
if (hh !== 0) {
h[hindex++] = hh;
}
}
while (findex < flen) {
Qnew = Q + fnow;
bvirt = Qnew - Q;
hh = Q - (Qnew - bvirt) + (fnow - bvirt);
fnow = f[++findex];
Q = Qnew;
if (hh !== 0) {
h[hindex++] = hh;
}
}
if (Q !== 0 || hindex === 0) {
h[hindex++] = Q;
}
return hindex;
}
function estimate(elen, e) {
let Q = e[0];
for (let i = 1; i < elen; i++) Q += e[i];
return Q;
}
function vec(n) {
return new Float64Array(n);
}
const ccwerrboundA = (3 + 16 * epsilon) * epsilon;
const ccwerrboundB = (2 + 12 * epsilon) * epsilon;
const ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;
const B = vec(4);
const C1 = vec(8);
const C2 = vec(12);
const D = vec(16);
const u = vec(4);
function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {
let acxtail, acytail, bcxtail, bcytail;
let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;
const acx = ax - cx;
const bcx = bx - cx;
const acy = ay - cy;
const bcy = by - cy;
s1 = acx * bcy;
c = splitter * acx;
ahi = c - (c - acx);
alo = acx - ahi;
c = splitter * bcy;
bhi = c - (c - bcy);
blo = bcy - bhi;
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
t1 = acy * bcx;
c = splitter * acy;
ahi = c - (c - acy);
alo = acy - ahi;
c = splitter * bcx;
bhi = c - (c - bcx);
blo = bcx - bhi;
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
_i = s0 - t0;
bvirt = s0 - _i;
B[0] = s0 - (_i + bvirt) + (bvirt - t0);
_j = s1 + _i;
bvirt = _j - s1;
_0 = s1 - (_j - bvirt) + (_i - bvirt);
_i = _0 - t1;
bvirt = _0 - _i;
B[1] = _0 - (_i + bvirt) + (bvirt - t1);
u3 = _j + _i;
bvirt = u3 - _j;
B[2] = _j - (u3 - bvirt) + (_i - bvirt);
B[3] = u3;
let det = estimate(4, B);
let errbound = ccwerrboundB * detsum;
if (det >= errbound || -det >= errbound) {
return det;
}
bvirt = ax - acx;
acxtail = ax - (acx + bvirt) + (bvirt - cx);
bvirt = bx - bcx;
bcxtail = bx - (bcx + bvirt) + (bvirt - cx);
bvirt = ay - acy;
acytail = ay - (acy + bvirt) + (bvirt - cy);
bvirt = by - bcy;
bcytail = by - (bcy + bvirt) + (bvirt - cy);
if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {
return det;
}
errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);
det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
if (det >= errbound || -det >= errbound) return det;
s1 = acxtail * bcy;
c = splitter * acxtail;
ahi = c - (c - acxtail);
alo = acxtail - ahi;
c = splitter * bcy;
bhi = c - (c - bcy);
blo = bcy - bhi;
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
t1 = acytail * bcx;
c = splitter * acytail;
ahi = c - (c - acytail);
alo = acytail - ahi;
c = splitter * bcx;
bhi = c - (c - bcx);
blo = bcx - bhi;
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
_i = s0 - t0;
bvirt = s0 - _i;
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
_j = s1 + _i;
bvirt = _j - s1;
_0 = s1 - (_j - bvirt) + (_i - bvirt);
_i = _0 - t1;
bvirt = _0 - _i;
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
u3 = _j + _i;
bvirt = u3 - _j;
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
u[3] = u3;
const C1len = sum(4, B, 4, u, C1);
s1 = acx * bcytail;
c = splitter * acx;
ahi = c - (c - acx);
alo = acx - ahi;
c = splitter * bcytail;
bhi = c - (c - bcytail);
blo = bcytail - bhi;
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
t1 = acy * bcxtail;
c = splitter * acy;
ahi = c - (c - acy);
alo = acy - ahi;
c = splitter * bcxtail;
bhi = c - (c - bcxtail);
blo = bcxtail - bhi;
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
_i = s0 - t0;
bvirt = s0 - _i;
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
_j = s1 + _i;
bvirt = _j - s1;
_0 = s1 - (_j - bvirt) + (_i - bvirt);
_i = _0 - t1;
bvirt = _0 - _i;
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
u3 = _j + _i;
bvirt = u3 - _j;
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
u[3] = u3;
const C2len = sum(C1len, C1, 4, u, C2);
s1 = acxtail * bcytail;
c = splitter * acxtail;
ahi = c - (c - acxtail);
alo = acxtail - ahi;
c = splitter * bcytail;
bhi = c - (c - bcytail);
blo = bcytail - bhi;
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
t1 = acytail * bcxtail;
c = splitter * acytail;
ahi = c - (c - acytail);
alo = acytail - ahi;
c = splitter * bcxtail;
bhi = c - (c - bcxtail);
blo = bcxtail - bhi;
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
_i = s0 - t0;
bvirt = s0 - _i;
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
_j = s1 + _i;
bvirt = _j - s1;
_0 = s1 - (_j - bvirt) + (_i - bvirt);
_i = _0 - t1;
bvirt = _0 - _i;
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
u3 = _j + _i;
bvirt = u3 - _j;
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
u[3] = u3;
const Dlen = sum(C2len, C2, 4, u, D);
return D[Dlen - 1];
}
function orient2d(ax, ay, bx, by, cx, cy) {
const detleft = (ay - cy) * (bx - cx);
const detright = (ax - cx) * (by - cy);
const det = detleft - detright;
const detsum = Math.abs(detleft + detright);
if (Math.abs(det) >= ccwerrboundA * detsum) return det;
return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);
}
const EPSILON = Math.pow(2, -52);
const EDGE_STACK = new Uint32Array(512);
/** @template {ArrayLike<number>} T */
class Delaunator {
/**
* Constructs a delaunay triangulation object given an array of points (`[x, y]` by default).
* `getX` and `getY` are optional functions of the form `(point) => value` for custom point formats.
*
* @template P
* @param {P[]} points
* @param {(p: P) => number} [getX]
* @param {(p: P) => number} [getY]
*/
// @ts-expect-error TS2322
static from(points, getX = defaultGetX, getY = defaultGetY) {
const n = points.length;
const coords = new Float64Array(n * 2);
for (let i = 0; i < n; i++) {
const p = points[i];
coords[2 * i] = getX(p);
coords[2 * i + 1] = getY(p);
}
return new Delaunator(coords);
}
/**
* Constructs a delaunay triangulation object given an array of point coordinates of the form:
* `[x0, y0, x1, y1, ...]` (use a typed array for best performance). Duplicate points are skipped.
*
* @param {T} coords
*/
constructor(coords) {
const n = coords.length >> 1;
if (n > 0 && typeof coords[0] !== 'number') throw new Error('Expected coords to contain numbers.');
this.coords = coords;
// arrays that will store the triangulation graph
const maxTriangles = Math.max(2 * n - 5, 0);
/** @private */ this._triangles = new Uint32Array(maxTriangles * 3);
/** @private */ this._halfedges = new Int32Array(maxTriangles * 3);
// temporary arrays for tracking the edges of the advancing convex hull
/** @private */ this._hashSize = Math.ceil(Math.sqrt(n));
/** @private */ this._hullPrev = new Uint32Array(n); // edge to prev edge
/** @private */ this._hullNext = new Uint32Array(n); // edge to next edge
/** @private */ this._hullTri = new Uint32Array(n); // edge to adjacent triangle
/** @private */ this._hullHash = new Int32Array(this._hashSize); // angular edge hash
// temporary arrays for sorting points
/** @private */ this._ids = new Uint32Array(n);
/** @private */ this._dists = new Float64Array(n);
/** @private */ this.trianglesLen = 0;
/** @private */ this._cx = 0;
/** @private */ this._cy = 0;
/** @private */ this._hullStart = 0;
/** A `Uint32Array` array of indices that reference points on the convex hull of the input data, counter-clockwise. */
this.hull = this._triangles;
/** A `Uint32Array` array of triangle vertex indices (each group of three numbers forms a triangle). All triangles are directed counterclockwise. */
this.triangles = this._triangles;
/**
* A `Int32Array` array of triangle half-edge indices that allows you to traverse the triangulation.
* `i`-th half-edge in the array corresponds to vertex `triangles[i]` the half-edge is coming from.
* `halfedges[i]` is the index of a twin half-edge in an adjacent triangle (or `-1` for outer half-edges on the convex hull).
*/
this.halfedges = this._halfedges;
this.update();
}
/**
* Updates the triangulation if you modified `delaunay.coords` values in place, avoiding expensive memory allocations.
* Useful for iterative relaxation algorithms such as Lloyd's.
*/
update() {
const {coords, _hullPrev: hullPrev, _hullNext: hullNext, _hullTri: hullTri, _hullHash: hullHash} = this;
const n = coords.length >> 1;
// populate an array of point indices; calculate input data bbox
let minX = Infinity;
let minY = Infinity;
let maxX = -Infinity;
let maxY = -Infinity;
for (let i = 0; i < n; i++) {
const x = coords[2 * i];
const y = coords[2 * i + 1];
if (x < minX) minX = x;
if (y < minY) minY = y;
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
this._ids[i] = i;
}
const cx = (minX + maxX) / 2;
const cy = (minY + maxY) / 2;
let i0 = 0, i1 = 0, i2 = 0;
// pick a seed point close to the center
for (let i = 0, minDist = Infinity; i < n; i++) {
const d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]);
if (d < minDist) {
i0 = i;
minDist = d;
}
}
const i0x = coords[2 * i0];
const i0y = coords[2 * i0 + 1];
// find the point closest to the seed
for (let i = 0, minDist = Infinity; i < n; i++) {
if (i === i0) continue;
const d = dist(i0x, i0y, coords[2 * i], coords[2 * i + 1]);
if (d < minDist && d > 0) {
i1 = i;
minDist = d;
}
}
let i1x = coords[2 * i1];
let i1y = coords[2 * i1 + 1];
let minRadius = Infinity;
// find the third point which forms the smallest circumcircle with the first two
for (let i = 0; i < n; i++) {
if (i === i0 || i === i1) continue;
const r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i], coords[2 * i + 1]);
if (r < minRadius) {
i2 = i;
minRadius = r;
}
}
let i2x = coords[2 * i2];
let i2y = coords[2 * i2 + 1];
if (minRadius === Infinity) {
// order collinear points by dx (or dy if all x are identical)
// and return the list as a hull
for (let i = 0; i < n; i++) {
this._dists[i] = (coords[2 * i] - coords[0]) || (coords[2 * i + 1] - coords[1]);
}
quicksort(this._ids, this._dists, 0, n - 1);
const hull = new Uint32Array(n);
let j = 0;
for (let i = 0, d0 = -Infinity; i < n; i++) {
const id = this._ids[i];
const d = this._dists[id];
if (d > d0) {
hull[j++] = id;
d0 = d;
}
}
this.hull = hull.subarray(0, j);
this.triangles = new Uint32Array(0);
this.halfedges = new Int32Array(0);
return;
}
// swap the order of the seed points for counter-clockwise orientation
if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) {
const i = i1;
const x = i1x;
const y = i1y;
i1 = i2;
i1x = i2x;
i1y = i2y;
i2 = i;
i2x = x;
i2y = y;
}
const center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
this._cx = center.x;
this._cy = center.y;
for (let i = 0; i < n; i++) {
this._dists[i] = dist(coords[2 * i], coords[2 * i + 1], center.x, center.y);
}
// sort the points by distance from the seed triangle circumcenter
quicksort(this._ids, this._dists, 0, n - 1);
// set up the seed triangle as the starting hull
this._hullStart = i0;
let hullSize = 3;
hullNext[i0] = hullPrev[i2] = i1;
hullNext[i1] = hullPrev[i0] = i2;
hullNext[i2] = hullPrev[i1] = i0;
hullTri[i0] = 0;
hullTri[i1] = 1;
hullTri[i2] = 2;
hullHash.fill(-1);
hullHash[this._hashKey(i0x, i0y)] = i0;
hullHash[this._hashKey(i1x, i1y)] = i1;
hullHash[this._hashKey(i2x, i2y)] = i2;
this.trianglesLen = 0;
this._addTriangle(i0, i1, i2, -1, -1, -1);
for (let k = 0, xp = 0, yp = 0; k < this._ids.length; k++) {
const i = this._ids[k];
const x = coords[2 * i];
const y = coords[2 * i + 1];
// skip near-duplicate points
if (k > 0 && Math.abs(x - xp) <= EPSILON && Math.abs(y - yp) <= EPSILON) continue;
xp = x;
yp = y;
// skip seed triangle points
if (i === i0 || i === i1 || i === i2) continue;
// find a visible edge on the convex hull using edge hash
let start = 0;
for (let j = 0, key = this._hashKey(x, y); j < this._hashSize; j++) {
start = hullHash[(key + j) % this._hashSize];
if (start !== -1 && start !== hullNext[start]) break;
}
start = hullPrev[start];
let e = start, q;
while (q = hullNext[e], orient2d(x, y, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1]) >= 0) {
e = q;
if (e === start) {
e = -1;
break;
}
}
if (e === -1) continue; // likely a near-duplicate point; skip it
// add the first triangle from the point
let t = this._addTriangle(e, i, hullNext[e], -1, -1, hullTri[e]);
// recursively flip triangles from the point until they satisfy the Delaunay condition
hullTri[i] = this._legalize(t + 2);
hullTri[e] = t; // keep track of boundary triangles on the hull
hullSize++;
// walk forward through the hull, adding more triangles and flipping recursively
let n = hullNext[e];
while (q = hullNext[n], orient2d(x, y, coords[2 * n], coords[2 * n + 1], coords[2 * q], coords[2 * q + 1]) < 0) {
t = this._addTriangle(n, i, q, hullTri[i], -1, hullTri[n]);
hullTri[i] = this._legalize(t + 2);
hullNext[n] = n; // mark as removed
hullSize--;
n = q;
}
// walk backward from the other side, adding more triangles and flipping
if (e === start) {
while (q = hullPrev[e], orient2d(x, y, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1]) < 0) {
t = this._addTriangle(q, i, e, -1, hullTri[e], hullTri[q]);
this._legalize(t + 2);
hullTri[q] = t;
hullNext[e] = e; // mark as removed
hullSize--;
e = q;
}
}
// update the hull indices
this._hullStart = hullPrev[i] = e;
hullNext[e] = hullPrev[n] = i;
hullNext[i] = n;
// save the two new edges in the hash table
hullHash[this._hashKey(x, y)] = i;
hullHash[this._hashKey(coords[2 * e], coords[2 * e + 1])] = e;
}
this.hull = new Uint32Array(hullSize);
for (let i = 0, e = this._hullStart; i < hullSize; i++) {
this.hull[i] = e;
e = hullNext[e];
}
// trim typed triangle mesh arrays
this.triangles = this._triangles.subarray(0, this.trianglesLen);
this.halfedges = this._halfedges.subarray(0, this.trianglesLen);
}
/**
* Calculate an angle-based key for the edge hash used for advancing convex hull.
*
* @param {number} x
* @param {number} y
* @private
*/
_hashKey(x, y) {
return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize;
}
/**
* Flip an edge in a pair of triangles if it doesn't satisfy the Delaunay condition.
*
* @param {number} a
* @private
*/
_legalize(a) {
const {_triangles: triangles, _halfedges: halfedges, coords} = this;
let i = 0;
let ar = 0;
// recursion eliminated with a fixed-size stack
while (true) {
const b = halfedges[a];
/* if the pair of triangles doesn't satisfy the Delaunay condition
* (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
* then do the same check/flip recursively for the new pair of triangles
*
* pl pl
* /||\ / \
* al/ || \bl al/ \a
* / || \ / \
* / a||b \ flip /___ar___\
* p0\ || /p1 => p0\---bl---/p1
* \ || / \ /
* ar\ || /br b\ /br
* \||/ \ /
* pr pr
*/
const a0 = a - a % 3;
ar = a0 + (a + 2) % 3;
if (b === -1) { // convex hull edge
if (i === 0) break;
a = EDGE_STACK[--i];
continue;
}
const b0 = b - b % 3;
const al = a0 + (a + 1) % 3;
const bl = b0 + (b + 2) % 3;
const p0 = triangles[ar];
const pr = triangles[a];
const pl = triangles[al];
const p1 = triangles[bl];
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]);
if (illegal) {
triangles[a] = p1;
triangles[b] = p0;
const hbl = halfedges[bl];
// edge swapped on the other side of the hull (rare); fix the half-edge reference
if (hbl === -1) {
let e = this._hullStart;
do {
if (this._hullTri[e] === bl) {
this._hullTri[e] = a;
break;
}
e = this._hullPrev[e];
} while (e !== this._hullStart);
}
this._link(a, hbl);
this._link(b, halfedges[ar]);
this._link(ar, bl);
const br = b0 + (b + 1) % 3;
// don't worry about hitting the cap: it can only happen on extremely degenerate input
if (i < EDGE_STACK.length) {
EDGE_STACK[i++] = br;
}
} else {
if (i === 0) break;
a = EDGE_STACK[--i];
}
}
return ar;
}
/**
* Link two half-edges to each other.
* @param {number} a
* @param {number} b
* @private
*/
_link(a, b) {
this._halfedges[a] = b;
if (b !== -1) this._halfedges[b] = a;
}
/**
* Add a new triangle given vertex indices and adjacent half-edge ids.
*
* @param {number} i0
* @param {number} i1
* @param {number} i2
* @param {number} a
* @param {number} b
* @param {number} c
* @private
*/
_addTriangle(i0, i1, i2, a, b, c) {
const t = this.trianglesLen;
this._triangles[t] = i0;
this._triangles[t + 1] = i1;
this._triangles[t + 2] = i2;
this._link(t, a);
this._link(t + 1, b);
this._link(t + 2, c);
this.trianglesLen += 3;
return t;
}
}
/**
* Monotonically increases with real angle, but doesn't need expensive trigonometry.
*
* @param {number} dx
* @param {number} dy
*/
function pseudoAngle(dx, dy) {
const p = dx / (Math.abs(dx) + Math.abs(dy));
return (dy > 0 ? 3 - p : 1 + p) / 4; // [0..1]
}
/**
* Squared distance between two points.
*
* @param {number} ax
* @param {number} ay
* @param {number} bx
* @param {number} by
*/
function dist(ax, ay, bx, by) {
const dx = ax - bx;
const dy = ay - by;
return dx * dx + dy * dy;
}
/**
* Check whether point P is inside a circle formed by points A, B, C.
*
* @param {number} ax
* @param {number} ay
* @param {number} bx
* @param {number} by
* @param {number} cx
* @param {number} cy
* @param {number} px
* @param {number} py
*/
function inCircle(ax, ay, bx, by, cx, cy, px, py) {
const dx = ax - px;
const dy = ay - py;
const ex = bx - px;
const ey = by - py;
const fx = cx - px;
const fy = cy - py;
const ap = dx * dx + dy * dy;
const bp = ex * ex + ey * ey;
const cp = fx * fx + fy * fy;
return dx * (ey * cp - bp * fy) -
dy * (ex * cp - bp * fx) +
ap * (ex * fy - ey * fx) < 0;
}
/**
* Squared radius of the circle formed by points A, B, C.
*
* @param {number} ax
* @param {number} ay
* @param {number} bx
* @param {number} by
* @param {number} cx
* @param {number} cy
*/
function circumradius(ax, ay, bx, by, cx, cy) {
const dx = bx - ax;
const dy = by - ay;
const ex = cx - ax;
const ey = cy - ay;
const bl = dx * dx + dy * dy;
const cl = ex * ex + ey * ey;
const d = 0.5 / (dx * ey - dy * ex);
const x = (ey * bl - dy * cl) * d;
const y = (dx * cl - ex * bl) * d;
return x * x + y * y;
}
/**
* Get coordinates of a circumcenter for points A, B, C.
*
* @param {number} ax
* @param {number} ay
* @param {number} bx
* @param {number} by
* @param {number} cx
* @param {number} cy
*/
function circumcenter(ax, ay, bx, by, cx, cy) {
const dx = bx - ax;
const dy = by - ay;
const ex = cx - ax;
const ey = cy - ay;
const bl = dx * dx + dy * dy;
const cl = ex * ex + ey * ey;
const d = 0.5 / (dx * ey - dy * ex);
const x = ax + (ey * bl - dy * cl) * d;
const y = ay + (dx * cl - ex * bl) * d;
return {x, y};
}
/**
* Sort points by distance via an array of point indices and an array of calculated distances.
*
* @param {Uint32Array} ids
* @param {Float64Array} dists
* @param {number} left
* @param {number} right
*/
function quicksort(ids, dists, left, right) {
if (right - left <= 20) {
for (let i = left + 1; i <= right; i++) {
const temp = ids[i];
const tempDist = dists[temp];
let j = i - 1;
while (j >= left && dists[ids[j]] > tempDist) ids[j + 1] = ids[j--];
ids[j + 1] = temp;
}
} else {
const median = (left + right) >> 1;
let i = left + 1;
let j = right;
swap(ids, median, i);
if (dists[ids[left]] > dists[ids[right]]) swap(ids, left, right);
if (dists[ids[i]] > dists[ids[right]]) swap(ids, i, right);
if (dists[ids[left]] > dists[ids[i]]) swap(ids, left, i);
const temp = ids[i];
const tempDist = dists[temp];
while (true) {
do i++; while (dists[ids[i]] < tempDist);
do j--; while (dists[ids[j]] > tempDist);
if (j < i) break;
swap(ids, i, j);
}
ids[left + 1] = ids[j];
ids[j] = temp;
if (right - i + 1 >= j - left) {
quicksort(ids, dists, i, right);
quicksort(ids, dists, left, j - 1);
} else {
quicksort(ids, dists, left, j - 1);
quicksort(ids, dists, i, right);
}
}
}
/**
* @param {Uint32Array} arr
* @param {number} i
* @param {number} j
*/
function swap(arr, i, j) {
const tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
/** @param {[number, number]} p */
function defaultGetX(p) {
return p[0];
}
/** @param {[number, number]} p */
function defaultGetY(p) {
return p[1];
}
return Delaunator;
}));

1
node_modules/delaunator/delaunator.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

83
node_modules/delaunator/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,83 @@
/** @template {ArrayLike<number>} T */
export default class Delaunator<T extends ArrayLike<number>> {
/**
* Constructs a delaunay triangulation object given an array of points (`[x, y]` by default).
* `getX` and `getY` are optional functions of the form `(point) => value` for custom point formats.
*
* @template P
* @param {P[]} points
* @param {(p: P) => number} [getX]
* @param {(p: P) => number} [getY]
*/
static from<P>(points: P[], getX?: (p: P) => number, getY?: (p: P) => number): Delaunator<Float64Array<ArrayBuffer>>;
/**
* Constructs a delaunay triangulation object given an array of point coordinates of the form:
* `[x0, y0, x1, y1, ...]` (use a typed array for best performance). Duplicate points are skipped.
*
* @param {T} coords
*/
constructor(coords: T);
coords: T;
/** @private */ private _triangles;
/** @private */ private _halfedges;
/** @private */ private _hashSize;
/** @private */ private _hullPrev;
/** @private */ private _hullNext;
/** @private */ private _hullTri;
/** @private */ private _hullHash;
/** @private */ private _ids;
/** @private */ private _dists;
/** @private */ private trianglesLen;
/** @private */ private _cx;
/** @private */ private _cy;
/** @private */ private _hullStart;
/** A `Uint32Array` array of indices that reference points on the convex hull of the input data, counter-clockwise. */
hull: Uint32Array<ArrayBuffer>;
/** A `Uint32Array` array of triangle vertex indices (each group of three numbers forms a triangle). All triangles are directed counterclockwise. */
triangles: Uint32Array<ArrayBuffer>;
/**
* A `Int32Array` array of triangle half-edge indices that allows you to traverse the triangulation.
* `i`-th half-edge in the array corresponds to vertex `triangles[i]` the half-edge is coming from.
* `halfedges[i]` is the index of a twin half-edge in an adjacent triangle (or `-1` for outer half-edges on the convex hull).
*/
halfedges: Int32Array<ArrayBuffer>;
/**
* Updates the triangulation if you modified `delaunay.coords` values in place, avoiding expensive memory allocations.
* Useful for iterative relaxation algorithms such as Lloyd's.
*/
update(): void;
/**
* Calculate an angle-based key for the edge hash used for advancing convex hull.
*
* @param {number} x
* @param {number} y
* @private
*/
private _hashKey;
/**
* Flip an edge in a pair of triangles if it doesn't satisfy the Delaunay condition.
*
* @param {number} a
* @private
*/
private _legalize;
/**
* Link two half-edges to each other.
* @param {number} a
* @param {number} b
* @private
*/
private _link;
/**
* Add a new triangle given vertex indices and adjacent half-edge ids.
*
* @param {number} i0
* @param {number} i1
* @param {number} i2
* @param {number} a
* @param {number} b
* @param {number} c
* @private
*/
private _addTriangle;
}

607
node_modules/delaunator/index.js generated vendored Normal file
View File

@@ -0,0 +1,607 @@
const EPSILON = Math.pow(2, -52);
const EDGE_STACK = new Uint32Array(512);
import {orient2d} from 'robust-predicates';
/** @template {ArrayLike<number>} T */
export default class Delaunator {
/**
* Constructs a delaunay triangulation object given an array of points (`[x, y]` by default).
* `getX` and `getY` are optional functions of the form `(point) => value` for custom point formats.
*
* @template P
* @param {P[]} points
* @param {(p: P) => number} [getX]
* @param {(p: P) => number} [getY]
*/
// @ts-expect-error TS2322
static from(points, getX = defaultGetX, getY = defaultGetY) {
const n = points.length;
const coords = new Float64Array(n * 2);
for (let i = 0; i < n; i++) {
const p = points[i];
coords[2 * i] = getX(p);
coords[2 * i + 1] = getY(p);
}
return new Delaunator(coords);
}
/**
* Constructs a delaunay triangulation object given an array of point coordinates of the form:
* `[x0, y0, x1, y1, ...]` (use a typed array for best performance). Duplicate points are skipped.
*
* @param {T} coords
*/
constructor(coords) {
const n = coords.length >> 1;
if (n > 0 && typeof coords[0] !== 'number') throw new Error('Expected coords to contain numbers.');
this.coords = coords;
// arrays that will store the triangulation graph
const maxTriangles = Math.max(2 * n - 5, 0);
/** @private */ this._triangles = new Uint32Array(maxTriangles * 3);
/** @private */ this._halfedges = new Int32Array(maxTriangles * 3);
// temporary arrays for tracking the edges of the advancing convex hull
/** @private */ this._hashSize = Math.ceil(Math.sqrt(n));
/** @private */ this._hullPrev = new Uint32Array(n); // edge to prev edge
/** @private */ this._hullNext = new Uint32Array(n); // edge to next edge
/** @private */ this._hullTri = new Uint32Array(n); // edge to adjacent triangle
/** @private */ this._hullHash = new Int32Array(this._hashSize); // angular edge hash
// temporary arrays for sorting points
/** @private */ this._ids = new Uint32Array(n);
/** @private */ this._dists = new Float64Array(n);
/** @private */ this.trianglesLen = 0;
/** @private */ this._cx = 0;
/** @private */ this._cy = 0;
/** @private */ this._hullStart = 0;
/** A `Uint32Array` array of indices that reference points on the convex hull of the input data, counter-clockwise. */
this.hull = this._triangles;
/** A `Uint32Array` array of triangle vertex indices (each group of three numbers forms a triangle). All triangles are directed counterclockwise. */
this.triangles = this._triangles;
/**
* A `Int32Array` array of triangle half-edge indices that allows you to traverse the triangulation.
* `i`-th half-edge in the array corresponds to vertex `triangles[i]` the half-edge is coming from.
* `halfedges[i]` is the index of a twin half-edge in an adjacent triangle (or `-1` for outer half-edges on the convex hull).
*/
this.halfedges = this._halfedges;
this.update();
}
/**
* Updates the triangulation if you modified `delaunay.coords` values in place, avoiding expensive memory allocations.
* Useful for iterative relaxation algorithms such as Lloyd's.
*/
update() {
const {coords, _hullPrev: hullPrev, _hullNext: hullNext, _hullTri: hullTri, _hullHash: hullHash} = this;
const n = coords.length >> 1;
// populate an array of point indices; calculate input data bbox
let minX = Infinity;
let minY = Infinity;
let maxX = -Infinity;
let maxY = -Infinity;
for (let i = 0; i < n; i++) {
const x = coords[2 * i];
const y = coords[2 * i + 1];
if (x < minX) minX = x;
if (y < minY) minY = y;
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
this._ids[i] = i;
}
const cx = (minX + maxX) / 2;
const cy = (minY + maxY) / 2;
let i0 = 0, i1 = 0, i2 = 0;
// pick a seed point close to the center
for (let i = 0, minDist = Infinity; i < n; i++) {
const d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]);
if (d < minDist) {
i0 = i;
minDist = d;
}
}
const i0x = coords[2 * i0];
const i0y = coords[2 * i0 + 1];
// find the point closest to the seed
for (let i = 0, minDist = Infinity; i < n; i++) {
if (i === i0) continue;
const d = dist(i0x, i0y, coords[2 * i], coords[2 * i + 1]);
if (d < minDist && d > 0) {
i1 = i;
minDist = d;
}
}
let i1x = coords[2 * i1];
let i1y = coords[2 * i1 + 1];
let minRadius = Infinity;
// find the third point which forms the smallest circumcircle with the first two
for (let i = 0; i < n; i++) {
if (i === i0 || i === i1) continue;
const r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i], coords[2 * i + 1]);
if (r < minRadius) {
i2 = i;
minRadius = r;
}
}
let i2x = coords[2 * i2];
let i2y = coords[2 * i2 + 1];
if (minRadius === Infinity) {
// order collinear points by dx (or dy if all x are identical)
// and return the list as a hull
for (let i = 0; i < n; i++) {
this._dists[i] = (coords[2 * i] - coords[0]) || (coords[2 * i + 1] - coords[1]);
}
quicksort(this._ids, this._dists, 0, n - 1);
const hull = new Uint32Array(n);
let j = 0;
for (let i = 0, d0 = -Infinity; i < n; i++) {
const id = this._ids[i];
const d = this._dists[id];
if (d > d0) {
hull[j++] = id;
d0 = d;
}
}
this.hull = hull.subarray(0, j);
this.triangles = new Uint32Array(0);
this.halfedges = new Int32Array(0);
return;
}
// swap the order of the seed points for counter-clockwise orientation
if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) {
const i = i1;
const x = i1x;
const y = i1y;
i1 = i2;
i1x = i2x;
i1y = i2y;
i2 = i;
i2x = x;
i2y = y;
}
const center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
this._cx = center.x;
this._cy = center.y;
for (let i = 0; i < n; i++) {
this._dists[i] = dist(coords[2 * i], coords[2 * i + 1], center.x, center.y);
}
// sort the points by distance from the seed triangle circumcenter
quicksort(this._ids, this._dists, 0, n - 1);
// set up the seed triangle as the starting hull
this._hullStart = i0;
let hullSize = 3;
hullNext[i0] = hullPrev[i2] = i1;
hullNext[i1] = hullPrev[i0] = i2;
hullNext[i2] = hullPrev[i1] = i0;
hullTri[i0] = 0;
hullTri[i1] = 1;
hullTri[i2] = 2;
hullHash.fill(-1);
hullHash[this._hashKey(i0x, i0y)] = i0;
hullHash[this._hashKey(i1x, i1y)] = i1;
hullHash[this._hashKey(i2x, i2y)] = i2;
this.trianglesLen = 0;
this._addTriangle(i0, i1, i2, -1, -1, -1);
for (let k = 0, xp = 0, yp = 0; k < this._ids.length; k++) {
const i = this._ids[k];
const x = coords[2 * i];
const y = coords[2 * i + 1];
// skip near-duplicate points
if (k > 0 && Math.abs(x - xp) <= EPSILON && Math.abs(y - yp) <= EPSILON) continue;
xp = x;
yp = y;
// skip seed triangle points
if (i === i0 || i === i1 || i === i2) continue;
// find a visible edge on the convex hull using edge hash
let start = 0;
for (let j = 0, key = this._hashKey(x, y); j < this._hashSize; j++) {
start = hullHash[(key + j) % this._hashSize];
if (start !== -1 && start !== hullNext[start]) break;
}
start = hullPrev[start];
let e = start, q;
while (q = hullNext[e], orient2d(x, y, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1]) >= 0) {
e = q;
if (e === start) {
e = -1;
break;
}
}
if (e === -1) continue; // likely a near-duplicate point; skip it
// add the first triangle from the point
let t = this._addTriangle(e, i, hullNext[e], -1, -1, hullTri[e]);
// recursively flip triangles from the point until they satisfy the Delaunay condition
hullTri[i] = this._legalize(t + 2);
hullTri[e] = t; // keep track of boundary triangles on the hull
hullSize++;
// walk forward through the hull, adding more triangles and flipping recursively
let n = hullNext[e];
while (q = hullNext[n], orient2d(x, y, coords[2 * n], coords[2 * n + 1], coords[2 * q], coords[2 * q + 1]) < 0) {
t = this._addTriangle(n, i, q, hullTri[i], -1, hullTri[n]);
hullTri[i] = this._legalize(t + 2);
hullNext[n] = n; // mark as removed
hullSize--;
n = q;
}
// walk backward from the other side, adding more triangles and flipping
if (e === start) {
while (q = hullPrev[e], orient2d(x, y, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1]) < 0) {
t = this._addTriangle(q, i, e, -1, hullTri[e], hullTri[q]);
this._legalize(t + 2);
hullTri[q] = t;
hullNext[e] = e; // mark as removed
hullSize--;
e = q;
}
}
// update the hull indices
this._hullStart = hullPrev[i] = e;
hullNext[e] = hullPrev[n] = i;
hullNext[i] = n;
// save the two new edges in the hash table
hullHash[this._hashKey(x, y)] = i;
hullHash[this._hashKey(coords[2 * e], coords[2 * e + 1])] = e;
}
this.hull = new Uint32Array(hullSize);
for (let i = 0, e = this._hullStart; i < hullSize; i++) {
this.hull[i] = e;
e = hullNext[e];
}
// trim typed triangle mesh arrays
this.triangles = this._triangles.subarray(0, this.trianglesLen);
this.halfedges = this._halfedges.subarray(0, this.trianglesLen);
}
/**
* Calculate an angle-based key for the edge hash used for advancing convex hull.
*
* @param {number} x
* @param {number} y
* @private
*/
_hashKey(x, y) {
return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize;
}
/**
* Flip an edge in a pair of triangles if it doesn't satisfy the Delaunay condition.
*
* @param {number} a
* @private
*/
_legalize(a) {
const {_triangles: triangles, _halfedges: halfedges, coords} = this;
let i = 0;
let ar = 0;
// recursion eliminated with a fixed-size stack
while (true) {
const b = halfedges[a];
/* if the pair of triangles doesn't satisfy the Delaunay condition
* (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
* then do the same check/flip recursively for the new pair of triangles
*
* pl pl
* /||\ / \
* al/ || \bl al/ \a
* / || \ / \
* / a||b \ flip /___ar___\
* p0\ || /p1 => p0\---bl---/p1
* \ || / \ /
* ar\ || /br b\ /br
* \||/ \ /
* pr pr
*/
const a0 = a - a % 3;
ar = a0 + (a + 2) % 3;
if (b === -1) { // convex hull edge
if (i === 0) break;
a = EDGE_STACK[--i];
continue;
}
const b0 = b - b % 3;
const al = a0 + (a + 1) % 3;
const bl = b0 + (b + 2) % 3;
const p0 = triangles[ar];
const pr = triangles[a];
const pl = triangles[al];
const p1 = triangles[bl];
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]);
if (illegal) {
triangles[a] = p1;
triangles[b] = p0;
const hbl = halfedges[bl];
// edge swapped on the other side of the hull (rare); fix the half-edge reference
if (hbl === -1) {
let e = this._hullStart;
do {
if (this._hullTri[e] === bl) {
this._hullTri[e] = a;
break;
}
e = this._hullPrev[e];
} while (e !== this._hullStart);
}
this._link(a, hbl);
this._link(b, halfedges[ar]);
this._link(ar, bl);
const br = b0 + (b + 1) % 3;
// don't worry about hitting the cap: it can only happen on extremely degenerate input
if (i < EDGE_STACK.length) {
EDGE_STACK[i++] = br;
}
} else {
if (i === 0) break;
a = EDGE_STACK[--i];
}
}
return ar;
}
/**
* Link two half-edges to each other.
* @param {number} a
* @param {number} b
* @private
*/
_link(a, b) {
this._halfedges[a] = b;
if (b !== -1) this._halfedges[b] = a;
}
/**
* Add a new triangle given vertex indices and adjacent half-edge ids.
*
* @param {number} i0
* @param {number} i1
* @param {number} i2
* @param {number} a
* @param {number} b
* @param {number} c
* @private
*/
_addTriangle(i0, i1, i2, a, b, c) {
const t = this.trianglesLen;
this._triangles[t] = i0;
this._triangles[t + 1] = i1;
this._triangles[t + 2] = i2;
this._link(t, a);
this._link(t + 1, b);
this._link(t + 2, c);
this.trianglesLen += 3;
return t;
}
}
/**
* Monotonically increases with real angle, but doesn't need expensive trigonometry.
*
* @param {number} dx
* @param {number} dy
*/
function pseudoAngle(dx, dy) {
const p = dx / (Math.abs(dx) + Math.abs(dy));
return (dy > 0 ? 3 - p : 1 + p) / 4; // [0..1]
}
/**
* Squared distance between two points.
*
* @param {number} ax
* @param {number} ay
* @param {number} bx
* @param {number} by
*/
function dist(ax, ay, bx, by) {
const dx = ax - bx;
const dy = ay - by;
return dx * dx + dy * dy;
}
/**
* Check whether point P is inside a circle formed by points A, B, C.
*
* @param {number} ax
* @param {number} ay
* @param {number} bx
* @param {number} by
* @param {number} cx
* @param {number} cy
* @param {number} px
* @param {number} py
*/
function inCircle(ax, ay, bx, by, cx, cy, px, py) {
const dx = ax - px;
const dy = ay - py;
const ex = bx - px;
const ey = by - py;
const fx = cx - px;
const fy = cy - py;
const ap = dx * dx + dy * dy;
const bp = ex * ex + ey * ey;
const cp = fx * fx + fy * fy;
return dx * (ey * cp - bp * fy) -
dy * (ex * cp - bp * fx) +
ap * (ex * fy - ey * fx) < 0;
}
/**
* Squared radius of the circle formed by points A, B, C.
*
* @param {number} ax
* @param {number} ay
* @param {number} bx
* @param {number} by
* @param {number} cx
* @param {number} cy
*/
function circumradius(ax, ay, bx, by, cx, cy) {
const dx = bx - ax;
const dy = by - ay;
const ex = cx - ax;
const ey = cy - ay;
const bl = dx * dx + dy * dy;
const cl = ex * ex + ey * ey;
const d = 0.5 / (dx * ey - dy * ex);
const x = (ey * bl - dy * cl) * d;
const y = (dx * cl - ex * bl) * d;
return x * x + y * y;
}
/**
* Get coordinates of a circumcenter for points A, B, C.
*
* @param {number} ax
* @param {number} ay
* @param {number} bx
* @param {number} by
* @param {number} cx
* @param {number} cy
*/
function circumcenter(ax, ay, bx, by, cx, cy) {
const dx = bx - ax;
const dy = by - ay;
const ex = cx - ax;
const ey = cy - ay;
const bl = dx * dx + dy * dy;
const cl = ex * ex + ey * ey;
const d = 0.5 / (dx * ey - dy * ex);
const x = ax + (ey * bl - dy * cl) * d;
const y = ay + (dx * cl - ex * bl) * d;
return {x, y};
}
/**
* Sort points by distance via an array of point indices and an array of calculated distances.
*
* @param {Uint32Array} ids
* @param {Float64Array} dists
* @param {number} left
* @param {number} right
*/
function quicksort(ids, dists, left, right) {
if (right - left <= 20) {
for (let i = left + 1; i <= right; i++) {
const temp = ids[i];
const tempDist = dists[temp];
let j = i - 1;
while (j >= left && dists[ids[j]] > tempDist) ids[j + 1] = ids[j--];
ids[j + 1] = temp;
}
} else {
const median = (left + right) >> 1;
let i = left + 1;
let j = right;
swap(ids, median, i);
if (dists[ids[left]] > dists[ids[right]]) swap(ids, left, right);
if (dists[ids[i]] > dists[ids[right]]) swap(ids, i, right);
if (dists[ids[left]] > dists[ids[i]]) swap(ids, left, i);
const temp = ids[i];
const tempDist = dists[temp];
while (true) {
do i++; while (dists[ids[i]] < tempDist);
do j--; while (dists[ids[j]] > tempDist);
if (j < i) break;
swap(ids, i, j);
}
ids[left + 1] = ids[j];
ids[j] = temp;
if (right - i + 1 >= j - left) {
quicksort(ids, dists, i, right);
quicksort(ids, dists, left, j - 1);
} else {
quicksort(ids, dists, left, j - 1);
quicksort(ids, dists, i, right);
}
}
}
/**
* @param {Uint32Array} arr
* @param {number} i
* @param {number} j
*/
function swap(arr, i, j) {
const tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
/** @param {[number, number]} p */
function defaultGetX(p) {
return p[0];
}
/** @param {[number, number]} p */
function defaultGetY(p) {
return p[1];
}

50
node_modules/delaunator/package.json generated vendored Normal file
View File

@@ -0,0 +1,50 @@
{
"name": "delaunator",
"version": "5.1.0",
"description": "An incredibly fast JavaScript library for Delaunay triangulation of 2D points",
"main": "index.js",
"module": "index.js",
"type": "module",
"types": "index.d.ts",
"jsdelivr": "delaunator.min.js",
"unpkg": "delaunator.min.js",
"sideEffects": false,
"dependencies": {
"robust-predicates": "^3.0.2"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^16.0.3",
"@rollup/plugin-terser": "^1.0.0",
"eslint": "^10.1.0",
"eslint-config-mourner": "^4.1.0",
"rollup": "^4.59.1",
"typescript": "^5.9.3"
},
"repository": {
"type": "git",
"url": "https://github.com/mapbox/delaunator.git"
},
"scripts": {
"lint": "eslint index.js test/test.js bench.js rollup.config.js docs/diagrams.js",
"pretest": "npm run lint",
"test": "tsc && node test/test.js",
"cov": "node --experimental-test-coverage test/test.js",
"bench": "node bench.js",
"build": "rollup -c",
"start": "rollup -cw",
"prepublishOnly": "npm test && npm run build"
},
"files": [
"index.js",
"index.d.ts",
"delaunator.js",
"delaunator.min.js"
],
"keywords": [
"delaunay triangulation",
"computational geometry",
"algorithms"
],
"author": "Vladimir Agafonkin",
"license": "ISC"
}