three-bvh-csg
Version:
A fast, flexible, dynamic CSG implementation on top of three-mesh-bvh
1,894 lines (1,560 loc) • 164 kB
JavaScript
import { BufferAttribute, Vector3, Ray, Vector2, Vector4, Mesh, Matrix4, Line3, Plane, Triangle, DoubleSide, Matrix3, BufferGeometry, Group, Color, MeshPhongMaterial, MathUtils, LineSegments, LineBasicMaterial, InstancedMesh, SphereGeometry, MeshBasicMaterial } from 'three';
import { MeshBVH, ExtendedTriangle } from 'three-mesh-bvh';
const HASH_WIDTH = 1e-6;
const HASH_HALF_WIDTH = HASH_WIDTH * 0.5;
const HASH_MULTIPLIER = Math.pow( 10, - Math.log10( HASH_WIDTH ) );
const HASH_ADDITION = HASH_HALF_WIDTH * HASH_MULTIPLIER;
function hashNumber( v ) {
return ~ ~ ( v * HASH_MULTIPLIER + HASH_ADDITION );
}
function hashVertex2( v ) {
return `${ hashNumber( v.x ) },${ hashNumber( v.y ) }`;
}
function hashVertex3( v ) {
return `${ hashNumber( v.x ) },${ hashNumber( v.y ) },${ hashNumber( v.z ) }`;
}
function hashVertex4( v ) {
return `${ hashNumber( v.x ) },${ hashNumber( v.y ) },${ hashNumber( v.z ) },${ hashNumber( v.w ) }`;
}
function hashRay( r ) {
return `${ hashVertex3( r.origin ) }-${ hashVertex3( r.direction ) }`;
}
function toNormalizedRay( v0, v1, target ) {
// get a normalized direction
target
.direction
.subVectors( v1, v0 )
.normalize();
// project the origin onto the perpendicular plane that
// passes through 0, 0, 0
const scalar = v0.dot( target.direction );
target.
origin
.copy( v0 )
.addScaledVector( target.direction, - scalar );
return target;
}
function areSharedArrayBuffersSupported() {
return typeof SharedArrayBuffer !== 'undefined';
}
function convertToSharedArrayBuffer( array ) {
if ( array.buffer instanceof SharedArrayBuffer ) {
return array;
}
const cons = array.constructor;
const buffer = array.buffer;
const sharedBuffer = new SharedArrayBuffer( buffer.byteLength );
const uintArray = new Uint8Array( buffer );
const sharedUintArray = new Uint8Array( sharedBuffer );
sharedUintArray.set( uintArray, 0 );
return new cons( sharedBuffer );
}
function getIndexArray( vertexCount, BufferConstructor = ArrayBuffer ) {
if ( vertexCount > 65535 ) {
return new Uint32Array( new BufferConstructor( 4 * vertexCount ) );
} else {
return new Uint16Array( new BufferConstructor( 2 * vertexCount ) );
}
}
function ensureIndex( geo, options ) {
if ( ! geo.index ) {
const vertexCount = geo.attributes.position.count;
const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
const index = getIndexArray( vertexCount, BufferConstructor );
geo.setIndex( new BufferAttribute( index, 1 ) );
for ( let i = 0; i < vertexCount; i ++ ) {
index[ i ] = i;
}
}
}
function getVertexCount( geo ) {
return geo.index ? geo.index.count : geo.attributes.position.count;
}
function getTriCount( geo ) {
return getVertexCount( geo ) / 3;
}
const DEGENERATE_EPSILON = 1e-8;
const _tempVec = new Vector3();
function toTriIndex( v ) {
return ~ ~ ( v / 3 );
}
function toEdgeIndex( v ) {
return v % 3;
}
function sortEdgeFunc( a, b ) {
return a.start - b.start;
}
function getProjectedDistance( ray, vec ) {
return _tempVec.subVectors( vec, ray.origin ).dot( ray.direction );
}
function hasOverlaps( arr ) {
arr = [ ...arr ].sort( sortEdgeFunc );
for ( let i = 0, l = arr.length; i < l - 1; i ++ ) {
const info0 = arr[ i ];
const info1 = arr[ i + 1 ];
if ( info1.start < info0.end && Math.abs( info1.start - info0.end ) > 1e-5 ) {
return true;
}
}
return false;
}
function getEdgeSetLength( arr ) {
let tot = 0;
arr.forEach( ( { start, end } ) => tot += end - start );
return tot;
}
function matchEdges( forward, reverse, disjointConnectivityMap, eps = DEGENERATE_EPSILON ) {
forward.sort( sortEdgeFunc );
reverse.sort( sortEdgeFunc );
for ( let i = 0; i < forward.length; i ++ ) {
const e0 = forward[ i ];
for ( let o = 0; o < reverse.length; o ++ ) {
const e1 = reverse[ o ];
if ( e1.start > e0.end ) {
// e2 is completely after e1
// break;
// NOTE: there are cases where there are overlaps due to precision issues or
// thin / degenerate triangles. Assuming the sibling side has the same issues
// we let the matching work here. Long term we should remove the degenerate
// triangles before this.
} else if ( e0.end < e1.start || e1.end < e0.start ) {
// e1 is completely before e2
continue;
} else if ( e0.start <= e1.start && e0.end >= e1.end ) {
// e1 is larger than and e2 is completely within e1
if ( ! areDistancesDegenerate( e1.end, e0.end ) ) {
forward.splice( i + 1, 0, {
start: e1.end,
end: e0.end,
index: e0.index,
} );
}
e0.end = e1.start;
e1.start = 0;
e1.end = 0;
} else if ( e0.start >= e1.start && e0.end <= e1.end ) {
// e2 is larger than and e1 is completely within e2
if ( ! areDistancesDegenerate( e0.end, e1.end ) ) {
reverse.splice( o + 1, 0, {
start: e0.end,
end: e1.end,
index: e1.index,
} );
}
e1.end = e0.start;
e0.start = 0;
e0.end = 0;
} else if ( e0.start <= e1.start && e0.end <= e1.end ) {
// e1 overlaps e2 at the beginning
const tmp = e0.end;
e0.end = e1.start;
e1.start = tmp;
} else if ( e0.start >= e1.start && e0.end >= e1.end ) {
// e1 overlaps e2 at the end
const tmp = e1.end;
e1.end = e0.start;
e0.start = tmp;
} else {
throw new Error();
}
// Add the connectivity information
if ( ! disjointConnectivityMap.has( e0.index ) ) {
disjointConnectivityMap.set( e0.index, [] );
}
if ( ! disjointConnectivityMap.has( e1.index ) ) {
disjointConnectivityMap.set( e1.index, [] );
}
disjointConnectivityMap
.get( e0.index )
.push( e1.index );
disjointConnectivityMap
.get( e1.index )
.push( e0.index );
if ( isEdgeDegenerate( e1 ) ) {
reverse.splice( o, 1 );
o --;
}
if ( isEdgeDegenerate( e0 ) ) {
// and if we have to remove the current original edge then exit this loop
// so we can work on the next one
forward.splice( i, 1 );
i --;
break;
}
}
}
cleanUpEdgeSet( forward );
cleanUpEdgeSet( reverse );
function cleanUpEdgeSet( arr ) {
for ( let i = 0; i < arr.length; i ++ ) {
if ( isEdgeDegenerate( arr[ i ] ) ) {
arr.splice( i, 1 );
i --;
}
}
}
function areDistancesDegenerate( start, end ) {
return Math.abs( end - start ) < eps;
}
function isEdgeDegenerate( e ) {
return Math.abs( e.end - e.start ) < eps;
}
}
const DIST_EPSILON = 1e-5;
const ANGLE_EPSILON = 1e-4;
class RaySet {
constructor() {
this._rays = [];
}
addRay( ray ) {
this._rays.push( ray );
}
findClosestRay( ray ) {
const rays = this._rays;
const inv = ray.clone();
inv.direction.multiplyScalar( - 1 );
let bestScore = Infinity;
let bestRay = null;
for ( let i = 0, l = rays.length; i < l; i ++ ) {
const r = rays[ i ];
if ( skipRay( r, ray ) && skipRay( r, inv ) ) {
continue;
}
const rayScore = scoreRays( r, ray );
const invScore = scoreRays( r, inv );
const score = Math.min( rayScore, invScore );
if ( score < bestScore ) {
bestScore = score;
bestRay = r;
}
}
return bestRay;
function skipRay( r0, r1 ) {
const distOutOfThreshold = r0.origin.distanceTo( r1.origin ) > DIST_EPSILON;
const angleOutOfThreshold = r0.direction.angleTo( r1.direction ) > ANGLE_EPSILON;
return angleOutOfThreshold || distOutOfThreshold;
}
function scoreRays( r0, r1 ) {
const originDistance = r0.origin.distanceTo( r1.origin );
const angleDistance = r0.direction.angleTo( r1.direction );
return originDistance / DIST_EPSILON + angleDistance / ANGLE_EPSILON;
}
}
}
const _v0 = new Vector3();
const _v1 = new Vector3();
const _ray$2 = new Ray();
function computeDisjointEdges(
geometry,
unmatchedSet,
eps,
) {
const attributes = geometry.attributes;
const indexAttr = geometry.index;
const posAttr = attributes.position;
const disjointConnectivityMap = new Map();
const fragmentMap = new Map();
const edges = Array.from( unmatchedSet );
const rays = new RaySet();
for ( let i = 0, l = edges.length; i < l; i ++ ) {
// get the triangle edge
const index = edges[ i ];
const triIndex = toTriIndex( index );
const edgeIndex = toEdgeIndex( index );
let i0 = 3 * triIndex + edgeIndex;
let i1 = 3 * triIndex + ( edgeIndex + 1 ) % 3;
if ( indexAttr ) {
i0 = indexAttr.getX( i0 );
i1 = indexAttr.getX( i1 );
}
_v0.fromBufferAttribute( posAttr, i0 );
_v1.fromBufferAttribute( posAttr, i1 );
// get the ray corresponding to the edge
toNormalizedRay( _v0, _v1, _ray$2 );
// find the shared ray with other edges
let info;
let commonRay = rays.findClosestRay( _ray$2 );
if ( commonRay === null ) {
commonRay = _ray$2.clone();
rays.addRay( commonRay );
}
if ( ! fragmentMap.has( commonRay ) ) {
fragmentMap.set( commonRay, {
forward: [],
reverse: [],
ray: commonRay,
} );
}
info = fragmentMap.get( commonRay );
// store the stride of edge endpoints along the ray
let start = getProjectedDistance( commonRay, _v0 );
let end = getProjectedDistance( commonRay, _v1 );
if ( start > end ) {
[ start, end ] = [ end, start ];
}
if ( _ray$2.direction.dot( commonRay.direction ) < 0 ) {
info.reverse.push( { start, end, index } );
} else {
info.forward.push( { start, end, index } );
}
}
// match the found sibling edges
fragmentMap.forEach( ( { forward, reverse }, ray ) => {
matchEdges( forward, reverse, disjointConnectivityMap, eps );
if ( forward.length === 0 && reverse.length === 0 ) {
fragmentMap.delete( ray );
}
} );
return {
disjointConnectivityMap,
fragmentMap,
};
}
const _vec2$2 = new Vector2();
const _vec3$1 = new Vector3();
const _vec4$1 = new Vector4();
const _hashes = [ '', '', '' ];
class HalfEdgeMap {
constructor() {
// result data
this.data = null;
this.disjointConnections = null;
this.unmatchedDisjointEdges = null;
this.unmatchedEdges = - 1;
this.matchedEdges = - 1;
// options
this.useDrawRange = true;
this.useAllAttributes = false;
this.matchDisjointEdges = false;
this.degenerateEpsilon = 1e-8;
}
getSiblingTriangleIndex( triIndex, edgeIndex ) {
const otherIndex = this.data[ triIndex * 3 + edgeIndex ];
return otherIndex === - 1 ? - 1 : ~ ~ ( otherIndex / 3 );
}
getSiblingEdgeIndex( triIndex, edgeIndex ) {
const otherIndex = this.data[ triIndex * 3 + edgeIndex ];
return otherIndex === - 1 ? - 1 : ( otherIndex % 3 );
}
getDisjointSiblingTriangleIndices( triIndex, edgeIndex ) {
const index = triIndex * 3 + edgeIndex;
const arr = this.disjointConnections.get( index );
return arr ? arr.map( i => ~ ~ ( i / 3 ) ) : [];
}
getDisjointSiblingEdgeIndices( triIndex, edgeIndex ) {
const index = triIndex * 3 + edgeIndex;
const arr = this.disjointConnections.get( index );
return arr ? arr.map( i => i % 3 ) : [];
}
isFullyConnected() {
return this.unmatchedEdges === 0;
}
updateFrom( geometry ) {
const { useAllAttributes, useDrawRange, matchDisjointEdges, degenerateEpsilon } = this;
const hashFunction = useAllAttributes ? hashAllAttributes : hashPositionAttribute;
// runs on the assumption that there is a 1 : 1 match of edges
const map = new Map();
// attributes
const { attributes } = geometry;
const attrKeys = useAllAttributes ? Object.keys( attributes ) : null;
const indexAttr = geometry.index;
const posAttr = attributes.position;
// get the potential number of triangles
let triCount = getTriCount( geometry );
const maxTriCount = triCount;
// get the real number of triangles from the based on the draw range
let offset = 0;
if ( useDrawRange ) {
offset = geometry.drawRange.start;
if ( geometry.drawRange.count !== Infinity ) {
triCount = ~ ~ ( geometry.drawRange.count / 3 );
}
}
// initialize the connectivity buffer - 1 means no connectivity
let data = this.data;
if ( ! data || data.length < 3 * maxTriCount ) {
data = new Int32Array( 3 * maxTriCount );
}
data.fill( - 1 );
// iterate over all triangles
let matchedEdges = 0;
let unmatchedSet = new Set();
for ( let i = offset, l = triCount * 3 + offset; i < l; i += 3 ) {
const i3 = i;
for ( let e = 0; e < 3; e ++ ) {
let i0 = i3 + e;
if ( indexAttr ) {
i0 = indexAttr.getX( i0 );
}
_hashes[ e ] = hashFunction( i0 );
}
for ( let e = 0; e < 3; e ++ ) {
const nextE = ( e + 1 ) % 3;
const vh0 = _hashes[ e ];
const vh1 = _hashes[ nextE ];
const reverseHash = `${ vh1 }_${ vh0 }`;
if ( map.has( reverseHash ) ) {
// create a reference between the two triangles and clear the hash
const index = i3 + e;
const otherIndex = map.get( reverseHash );
data[ index ] = otherIndex;
data[ otherIndex ] = index;
map.delete( reverseHash );
matchedEdges += 2;
unmatchedSet.delete( otherIndex );
} else {
// save the triangle and triangle edge index captured in one value
// triIndex = ~ ~ ( i0 / 3 );
// edgeIndex = i0 % 3;
const hash = `${ vh0 }_${ vh1 }`;
const index = i3 + e;
map.set( hash, index );
unmatchedSet.add( index );
}
}
}
if ( matchDisjointEdges ) {
const {
fragmentMap,
disjointConnectivityMap,
} = computeDisjointEdges( geometry, unmatchedSet, degenerateEpsilon );
unmatchedSet.clear();
fragmentMap.forEach( ( { forward, reverse } ) => {
forward.forEach( ( { index } ) => unmatchedSet.add( index ) );
reverse.forEach( ( { index } ) => unmatchedSet.add( index ) );
} );
this.unmatchedDisjointEdges = fragmentMap;
this.disjointConnections = disjointConnectivityMap;
matchedEdges = triCount * 3 - unmatchedSet.size;
}
this.matchedEdges = matchedEdges;
this.unmatchedEdges = unmatchedSet.size;
this.data = data;
function hashPositionAttribute( i ) {
_vec3$1.fromBufferAttribute( posAttr, i );
return hashVertex3( _vec3$1 );
}
function hashAllAttributes( i ) {
let result = '';
for ( let k = 0, l = attrKeys.length; k < l; k ++ ) {
const attr = attributes[ attrKeys[ k ] ];
let str;
switch ( attr.itemSize ) {
case 1:
str = hashNumber( attr.getX( i ) );
break;
case 2:
str = hashVertex2( _vec2$2.fromBufferAttribute( attr, i ) );
break;
case 3:
str = hashVertex3( _vec3$1.fromBufferAttribute( attr, i ) );
break;
case 4:
str = hashVertex4( _vec4$1.fromBufferAttribute( attr, i ) );
break;
}
if ( result !== '' ) {
result += '|';
}
result += str;
}
return result;
}
}
}
class Brush extends Mesh {
constructor( ...args ) {
super( ...args );
this.isBrush = true;
this._previousMatrix = new Matrix4();
this._previousMatrix.elements.fill( 0 );
this._halfEdges = null;
this._boundsTree = null;
this._groupIndices = null;
this._hash = null;
}
markUpdated() {
this._previousMatrix.copy( this.matrix );
}
isDirty() {
const { matrix, _previousMatrix } = this;
const el1 = matrix.elements;
const el2 = _previousMatrix.elements;
for ( let i = 0; i < 16; i ++ ) {
if ( el1[ i ] !== el2[ i ] ) {
return true;
}
}
return false;
}
prepareGeometry() {
// generate shared array buffers
const geometry = this.geometry;
const attributes = geometry.attributes;
const useSharedArrayBuffer = areSharedArrayBuffersSupported();
const index = geometry.index;
const posAttr = geometry.attributes.position;
const indexHash = index ? `${ index.uuid }_${ index.count }_${ index.version }` : '-1_-1_-1';
const posHash = `${ posAttr.uuid }_${ posAttr.count }_${ posAttr.version }`;
const hash = `${ geometry.uuid }_${ indexHash }_${ posHash }`;
if ( this._hash === hash ) {
return;
}
this._hash = hash;
if ( useSharedArrayBuffer ) {
for ( const key in attributes ) {
const attribute = attributes[ key ];
if ( attribute.isInterleavedBufferAttribute ) {
throw new Error( 'Brush: InterleavedBufferAttributes are not supported.' );
}
attribute.array = convertToSharedArrayBuffer( attribute.array );
}
}
// generate bounds tree
geometry.boundsTree = new MeshBVH( geometry, { maxLeafSize: 3, indirect: true, useSharedArrayBuffer } );
// generate half edges
if ( ! geometry.halfEdges ) {
geometry.halfEdges = new HalfEdgeMap();
}
geometry.halfEdges.updateFrom( geometry );
// save group indices for materials
const triCount = getTriCount( geometry );
if ( ! geometry.groupIndices || geometry.groupIndices.length !== triCount ) {
geometry.groupIndices = new Uint16Array( triCount );
}
const array = geometry.groupIndices;
const groups = geometry.groups;
for ( let i = 0, l = groups.length; i < l; i ++ ) {
const { start, count } = groups[ i ];
for ( let g = start / 3, lg = ( start + count ) / 3; g < lg; g ++ ) {
array[ g ] = i;
}
}
}
disposeCacheData() {
const { geometry } = this;
geometry.halfEdges = null;
geometry.boundsTree = null;
geometry.groupIndices = null;
}
}
// Auto-generated ESM bundle of cdt2d
var __getOwnPropNames = Object.getOwnPropertyNames;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
// node_modules/binary-search-bounds/search-bounds.js
var require_search_bounds = __commonJS({
"node_modules/binary-search-bounds/search-bounds.js"(exports, module) {
"use strict";
function ge(a, y, c, l, h) {
var i = h + 1;
while (l <= h) {
var m = l + h >>> 1, x = a[m];
var p = c !== void 0 ? c(x, y) : x - y;
if (p >= 0) {
i = m;
h = m - 1;
} else {
l = m + 1;
}
}
return i;
}
function gt(a, y, c, l, h) {
var i = h + 1;
while (l <= h) {
var m = l + h >>> 1, x = a[m];
var p = c !== void 0 ? c(x, y) : x - y;
if (p > 0) {
i = m;
h = m - 1;
} else {
l = m + 1;
}
}
return i;
}
function lt(a, y, c, l, h) {
var i = l - 1;
while (l <= h) {
var m = l + h >>> 1, x = a[m];
var p = c !== void 0 ? c(x, y) : x - y;
if (p < 0) {
i = m;
l = m + 1;
} else {
h = m - 1;
}
}
return i;
}
function le(a, y, c, l, h) {
var i = l - 1;
while (l <= h) {
var m = l + h >>> 1, x = a[m];
var p = c !== void 0 ? c(x, y) : x - y;
if (p <= 0) {
i = m;
l = m + 1;
} else {
h = m - 1;
}
}
return i;
}
function eq(a, y, c, l, h) {
while (l <= h) {
var m = l + h >>> 1, x = a[m];
var p = c !== void 0 ? c(x, y) : x - y;
if (p === 0) {
return m;
}
if (p <= 0) {
l = m + 1;
} else {
h = m - 1;
}
}
return -1;
}
function norm(a, y, c, l, h, f) {
if (typeof c === "function") {
return f(a, y, c, l === void 0 ? 0 : l | 0, h === void 0 ? a.length - 1 : h | 0);
}
return f(a, y, void 0, c === void 0 ? 0 : c | 0, l === void 0 ? a.length - 1 : l | 0);
}
module.exports = {
ge: function(a, y, c, l, h) {
return norm(a, y, c, l, h, ge);
},
gt: function(a, y, c, l, h) {
return norm(a, y, c, l, h, gt);
},
lt: function(a, y, c, l, h) {
return norm(a, y, c, l, h, lt);
},
le: function(a, y, c, l, h) {
return norm(a, y, c, l, h, le);
},
eq: function(a, y, c, l, h) {
return norm(a, y, c, l, h, eq);
}
};
}
});
// node_modules/two-product/two-product.js
var require_two_product = __commonJS({
"node_modules/two-product/two-product.js"(exports, module) {
"use strict";
module.exports = twoProduct;
var SPLITTER = +(Math.pow(2, 27) + 1);
function twoProduct(a, b, result) {
var x = a * b;
var c = SPLITTER * a;
var abig = c - a;
var ahi = c - abig;
var alo = a - ahi;
var d = SPLITTER * b;
var bbig = d - b;
var bhi = d - bbig;
var blo = b - bhi;
var err1 = x - ahi * bhi;
var err2 = err1 - alo * bhi;
var err3 = err2 - ahi * blo;
var y = alo * blo - err3;
if (result) {
result[0] = y;
result[1] = x;
return result;
}
return [y, x];
}
}
});
// node_modules/robust-sum/robust-sum.js
var require_robust_sum = __commonJS({
"node_modules/robust-sum/robust-sum.js"(exports, module) {
"use strict";
module.exports = linearExpansionSum;
function scalarScalar(a, b) {
var x = a + b;
var bv = x - a;
var av = x - bv;
var br = b - bv;
var ar = a - av;
var y = ar + br;
if (y) {
return [y, x];
}
return [x];
}
function linearExpansionSum(e, f) {
var ne = e.length | 0;
var nf = f.length | 0;
if (ne === 1 && nf === 1) {
return scalarScalar(e[0], f[0]);
}
var n = ne + nf;
var g = new Array(n);
var count = 0;
var eptr = 0;
var fptr = 0;
var abs = Math.abs;
var ei = e[eptr];
var ea = abs(ei);
var fi = f[fptr];
var fa = abs(fi);
var a, b;
if (ea < fa) {
b = ei;
eptr += 1;
if (eptr < ne) {
ei = e[eptr];
ea = abs(ei);
}
} else {
b = fi;
fptr += 1;
if (fptr < nf) {
fi = f[fptr];
fa = abs(fi);
}
}
if (eptr < ne && ea < fa || fptr >= nf) {
a = ei;
eptr += 1;
if (eptr < ne) {
ei = e[eptr];
ea = abs(ei);
}
} else {
a = fi;
fptr += 1;
if (fptr < nf) {
fi = f[fptr];
fa = abs(fi);
}
}
var x = a + b;
var bv = x - a;
var y = b - bv;
var q0 = y;
var q1 = x;
var _x, _bv, _av, _br, _ar;
while (eptr < ne && fptr < nf) {
if (ea < fa) {
a = ei;
eptr += 1;
if (eptr < ne) {
ei = e[eptr];
ea = abs(ei);
}
} else {
a = fi;
fptr += 1;
if (fptr < nf) {
fi = f[fptr];
fa = abs(fi);
}
}
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y) {
g[count++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
}
while (eptr < ne) {
a = ei;
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y) {
g[count++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
eptr += 1;
if (eptr < ne) {
ei = e[eptr];
}
}
while (fptr < nf) {
a = fi;
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y) {
g[count++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
fptr += 1;
if (fptr < nf) {
fi = f[fptr];
}
}
if (q0) {
g[count++] = q0;
}
if (q1) {
g[count++] = q1;
}
if (!count) {
g[count++] = 0;
}
g.length = count;
return g;
}
}
});
// node_modules/two-sum/two-sum.js
var require_two_sum = __commonJS({
"node_modules/two-sum/two-sum.js"(exports, module) {
"use strict";
module.exports = fastTwoSum;
function fastTwoSum(a, b, result) {
var x = a + b;
var bv = x - a;
var av = x - bv;
var br = b - bv;
var ar = a - av;
if (result) {
result[0] = ar + br;
result[1] = x;
return result;
}
return [ar + br, x];
}
}
});
// node_modules/robust-scale/robust-scale.js
var require_robust_scale = __commonJS({
"node_modules/robust-scale/robust-scale.js"(exports, module) {
"use strict";
var twoProduct = require_two_product();
var twoSum = require_two_sum();
module.exports = scaleLinearExpansion;
function scaleLinearExpansion(e, scale) {
var n = e.length;
if (n === 1) {
var ts = twoProduct(e[0], scale);
if (ts[0]) {
return ts;
}
return [ts[1]];
}
var g = new Array(2 * n);
var q = [0.1, 0.1];
var t = [0.1, 0.1];
var count = 0;
twoProduct(e[0], scale, q);
if (q[0]) {
g[count++] = q[0];
}
for (var i = 1; i < n; ++i) {
twoProduct(e[i], scale, t);
var pq = q[1];
twoSum(pq, t[0], q);
if (q[0]) {
g[count++] = q[0];
}
var a = t[1];
var b = q[1];
var x = a + b;
var bv = x - a;
var y = b - bv;
q[1] = x;
if (y) {
g[count++] = y;
}
}
if (q[1]) {
g[count++] = q[1];
}
if (count === 0) {
g[count++] = 0;
}
g.length = count;
return g;
}
}
});
// node_modules/robust-subtract/robust-diff.js
var require_robust_diff = __commonJS({
"node_modules/robust-subtract/robust-diff.js"(exports, module) {
"use strict";
module.exports = robustSubtract;
function scalarScalar(a, b) {
var x = a + b;
var bv = x - a;
var av = x - bv;
var br = b - bv;
var ar = a - av;
var y = ar + br;
if (y) {
return [y, x];
}
return [x];
}
function robustSubtract(e, f) {
var ne = e.length | 0;
var nf = f.length | 0;
if (ne === 1 && nf === 1) {
return scalarScalar(e[0], -f[0]);
}
var n = ne + nf;
var g = new Array(n);
var count = 0;
var eptr = 0;
var fptr = 0;
var abs = Math.abs;
var ei = e[eptr];
var ea = abs(ei);
var fi = -f[fptr];
var fa = abs(fi);
var a, b;
if (ea < fa) {
b = ei;
eptr += 1;
if (eptr < ne) {
ei = e[eptr];
ea = abs(ei);
}
} else {
b = fi;
fptr += 1;
if (fptr < nf) {
fi = -f[fptr];
fa = abs(fi);
}
}
if (eptr < ne && ea < fa || fptr >= nf) {
a = ei;
eptr += 1;
if (eptr < ne) {
ei = e[eptr];
ea = abs(ei);
}
} else {
a = fi;
fptr += 1;
if (fptr < nf) {
fi = -f[fptr];
fa = abs(fi);
}
}
var x = a + b;
var bv = x - a;
var y = b - bv;
var q0 = y;
var q1 = x;
var _x, _bv, _av, _br, _ar;
while (eptr < ne && fptr < nf) {
if (ea < fa) {
a = ei;
eptr += 1;
if (eptr < ne) {
ei = e[eptr];
ea = abs(ei);
}
} else {
a = fi;
fptr += 1;
if (fptr < nf) {
fi = -f[fptr];
fa = abs(fi);
}
}
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y) {
g[count++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
}
while (eptr < ne) {
a = ei;
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y) {
g[count++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
eptr += 1;
if (eptr < ne) {
ei = e[eptr];
}
}
while (fptr < nf) {
a = fi;
b = q0;
x = a + b;
bv = x - a;
y = b - bv;
if (y) {
g[count++] = y;
}
_x = q1 + x;
_bv = _x - q1;
_av = _x - _bv;
_br = x - _bv;
_ar = q1 - _av;
q0 = _ar + _br;
q1 = _x;
fptr += 1;
if (fptr < nf) {
fi = -f[fptr];
}
}
if (q0) {
g[count++] = q0;
}
if (q1) {
g[count++] = q1;
}
if (!count) {
g[count++] = 0;
}
g.length = count;
return g;
}
}
});
// node_modules/robust-orientation/orientation.js
var require_orientation = __commonJS({
"node_modules/robust-orientation/orientation.js"(exports, module) {
"use strict";
var twoProduct = require_two_product();
var robustSum = require_robust_sum();
var robustScale = require_robust_scale();
var robustSubtract = require_robust_diff();
var NUM_EXPAND = 5;
var EPSILON = 11102230246251565e-32;
var ERRBOUND3 = (3 + 16 * EPSILON) * EPSILON;
var ERRBOUND4 = (7 + 56 * EPSILON) * EPSILON;
function orientation_3(sum, prod, scale, sub) {
return function orientation3Exact2(m0, m1, m2) {
var p = sum(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])));
var n = sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0]));
var d = sub(p, n);
return d[d.length - 1];
};
}
function orientation_4(sum, prod, scale, sub) {
return function orientation4Exact2(m0, m1, m2, m3) {
var p = sum(sum(scale(sum(prod(m2[1], m3[0]), prod(-m3[1], m2[0])), m1[2]), sum(scale(sum(prod(m1[1], m3[0]), prod(-m3[1], m1[0])), -m2[2]), scale(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), m3[2]))), sum(scale(sum(prod(m1[1], m3[0]), prod(-m3[1], m1[0])), m0[2]), sum(scale(sum(prod(m0[1], m3[0]), prod(-m3[1], m0[0])), -m1[2]), scale(sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])), m3[2]))));
var n = sum(sum(scale(sum(prod(m2[1], m3[0]), prod(-m3[1], m2[0])), m0[2]), sum(scale(sum(prod(m0[1], m3[0]), prod(-m3[1], m0[0])), -m2[2]), scale(sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0])), m3[2]))), sum(scale(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), m0[2]), sum(scale(sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0])), -m1[2]), scale(sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])), m2[2]))));
var d = sub(p, n);
return d[d.length - 1];
};
}
function orientation_5(sum, prod, scale, sub) {
return function orientation5Exact(m0, m1, m2, m3, m4) {
var p = sum(sum(sum(scale(sum(scale(sum(prod(m3[1], m4[0]), prod(-m4[1], m3[0])), m2[2]), sum(scale(sum(prod(m2[1], m4[0]), prod(-m4[1], m2[0])), -m3[2]), scale(sum(prod(m2[1], m3[0]), prod(-m3[1], m2[0])), m4[2]))), m1[3]), sum(scale(sum(scale(sum(prod(m3[1], m4[0]), prod(-m4[1], m3[0])), m1[2]), sum(scale(sum(prod(m1[1], m4[0]), prod(-m4[1], m1[0])), -m3[2]), scale(sum(prod(m1[1], m3[0]), prod(-m3[1], m1[0])), m4[2]))), -m2[3]), scale(sum(scale(sum(prod(m2[1], m4[0]), prod(-m4[1], m2[0])), m1[2]), sum(scale(sum(prod(m1[1], m4[0]), prod(-m4[1], m1[0])), -m2[2]), scale(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), m4[2]))), m3[3]))), sum(scale(sum(scale(sum(prod(m2[1], m3[0]), prod(-m3[1], m2[0])), m1[2]), sum(scale(sum(prod(m1[1], m3[0]), prod(-m3[1], m1[0])), -m2[2]), scale(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), m3[2]))), -m4[3]), sum(scale(sum(scale(sum(prod(m3[1], m4[0]), prod(-m4[1], m3[0])), m1[2]), sum(scale(sum(prod(m1[1], m4[0]), prod(-m4[1], m1[0])), -m3[2]), scale(sum(prod(m1[1], m3[0]), prod(-m3[1], m1[0])), m4[2]))), m0[3]), scale(sum(scale(sum(prod(m3[1], m4[0]), prod(-m4[1], m3[0])), m0[2]), sum(scale(sum(prod(m0[1], m4[0]), prod(-m4[1], m0[0])), -m3[2]), scale(sum(prod(m0[1], m3[0]), prod(-m3[1], m0[0])), m4[2]))), -m1[3])))), sum(sum(scale(sum(scale(sum(prod(m1[1], m4[0]), prod(-m4[1], m1[0])), m0[2]), sum(scale(sum(prod(m0[1], m4[0]), prod(-m4[1], m0[0])), -m1[2]), scale(sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])), m4[2]))), m3[3]), sum(scale(sum(scale(sum(prod(m1[1], m3[0]), prod(-m3[1], m1[0])), m0[2]), sum(scale(sum(prod(m0[1], m3[0]), prod(-m3[1], m0[0])), -m1[2]), scale(sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])), m3[2]))), -m4[3]), scale(sum(scale(sum(prod(m2[1], m3[0]), prod(-m3[1], m2[0])), m1[2]), sum(scale(sum(prod(m1[1], m3[0]), prod(-m3[1], m1[0])), -m2[2]), scale(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), m3[2]))), m0[3]))), sum(scale(sum(scale(sum(prod(m2[1], m3[0]), prod(-m3[1], m2[0])), m0[2]), sum(scale(sum(prod(m0[1], m3[0]), prod(-m3[1], m0[0])), -m2[2]), scale(sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0])), m3[2]))), -m1[3]), sum(scale(sum(scale(sum(prod(m1[1], m3[0]), prod(-m3[1], m1[0])), m0[2]), sum(scale(sum(prod(m0[1], m3[0]), prod(-m3[1], m0[0])), -m1[2]), scale(sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])), m3[2]))), m2[3]), scale(sum(scale(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), m0[2]), sum(scale(sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0])), -m1[2]), scale(sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])), m2[2]))), -m3[3])))));
var n = sum(sum(sum(scale(sum(scale(sum(prod(m3[1], m4[0]), prod(-m4[1], m3[0])), m2[2]), sum(scale(sum(prod(m2[1], m4[0]), prod(-m4[1], m2[0])), -m3[2]), scale(sum(prod(m2[1], m3[0]), prod(-m3[1], m2[0])), m4[2]))), m0[3]), scale(sum(scale(sum(prod(m3[1], m4[0]), prod(-m4[1], m3[0])), m0[2]), sum(scale(sum(prod(m0[1], m4[0]), prod(-m4[1], m0[0])), -m3[2]), scale(sum(prod(m0[1], m3[0]), prod(-m3[1], m0[0])), m4[2]))), -m2[3])), sum(scale(sum(scale(sum(prod(m2[1], m4[0]), prod(-m4[1], m2[0])), m0[2]), sum(scale(sum(prod(m0[1], m4[0]), prod(-m4[1], m0[0])), -m2[2]), scale(sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0])), m4[2]))), m3[3]), scale(sum(scale(sum(prod(m2[1], m3[0]), prod(-m3[1], m2[0])), m0[2]), sum(scale(sum(prod(m0[1], m3[0]), prod(-m3[1], m0[0])), -m2[2]), scale(sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0])), m3[2]))), -m4[3]))), sum(sum(scale(sum(scale(sum(prod(m2[1], m4[0]), prod(-m4[1], m2[0])), m1[2]), sum(scale(sum(prod(m1[1], m4[0]), prod(-m4[1], m1[0])), -m2[2]), scale(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), m4[2]))), m0[3]), scale(sum(scale(sum(prod(m2[1], m4[0]), prod(-m4[1], m2[0])), m0[2]), sum(scale(sum(prod(m0[1], m4[0]), prod(-m4[1], m0[0])), -m2[2]), scale(sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0])), m4[2]))), -m1[3])), sum(scale(sum(scale(sum(prod(m1[1], m4[0]), prod(-m4[1], m1[0])), m0[2]), sum(scale(sum(prod(m0[1], m4[0]), prod(-m4[1], m0[0])), -m1[2]), scale(sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])), m4[2]))), m2[3]), scale(sum(scale(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), m0[2]), sum(scale(sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0])), -m1[2]), scale(sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])), m2[2]))), -m4[3]))));
var d = sub(p, n);
return d[d.length - 1];
};
}
function orientation(n) {
var fn = n === 3 ? orientation_3 : n === 4 ? orientation_4 : orientation_5;
return fn(robustSum, twoProduct, robustScale, robustSubtract);
}
var orientation3Exact = orientation(3);
var orientation4Exact = orientation(4);
var CACHED = [
function orientation0() {
return 0;
},
function orientation1() {
return 0;
},
function orientation2(a, b) {
return b[0] - a[0];
},
function orientation3(a, b, c) {
var l = (a[1] - c[1]) * (b[0] - c[0]);
var r = (a[0] - c[0]) * (b[1] - c[1]);
var det = l - r;
var s;
if (l > 0) {
if (r <= 0) {
return det;
} else {
s = l + r;
}
} else if (l < 0) {
if (r >= 0) {
return det;
} else {
s = -(l + r);
}
} else {
return det;
}
var tol = ERRBOUND3 * s;
if (det >= tol || det <= -tol) {
return det;
}
return orientation3Exact(a, b, c);
},
function orientation4(a, b, c, d) {
var adx = a[0] - d[0];
var bdx = b[0] - d[0];
var cdx = c[0] - d[0];
var ady = a[1] - d[1];
var bdy = b[1] - d[1];
var cdy = c[1] - d[1];
var adz = a[2] - d[2];
var bdz = b[2] - d[2];
var cdz = c[2] - d[2];
var bdxcdy = bdx * cdy;
var cdxbdy = cdx * bdy;
var cdxady = cdx * ady;
var adxcdy = adx * cdy;
var adxbdy = adx * bdy;
var bdxady = bdx * ady;
var det = adz * (bdxcdy - cdxbdy) + bdz * (cdxady - adxcdy) + cdz * (adxbdy - bdxady);
var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) + (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) + (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz);
var tol = ERRBOUND4 * permanent;
if (det > tol || -det > tol) {
return det;
}
return orientation4Exact(a, b, c, d);
}
];
function slowOrient(args) {
var proc2 = CACHED[args.length];
if (!proc2) {
proc2 = CACHED[args.length] = orientation(args.length);
}
return proc2.apply(void 0, args);
}
function proc(slow, o0, o1, o2, o3, o4, o5) {
return function getOrientation(a0, a1, a2, a3, a4) {
switch (arguments.length) {
case 0:
case 1:
return 0;
case 2:
return o2(a0, a1);
case 3:
return o3(a0, a1, a2);
case 4:
return o4(a0, a1, a2, a3);
case 5:
return o5(a0, a1, a2, a3, a4);
}
var s = new Array(arguments.length);
for (var i = 0; i < arguments.length; ++i) {
s[i] = arguments[i];
}
return slow(s);
};
}
function generateOrientationProc() {
while (CACHED.length <= NUM_EXPAND) {
CACHED.push(orientation(CACHED.length));
}
module.exports = proc.apply(void 0, [slowOrient].concat(CACHED));
for (var i = 0; i <= NUM_EXPAND; ++i) {
module.exports[i] = CACHED[i];
}
}
generateOrientationProc();
}
});
// node_modules/cdt2d/lib/monotone.js
var require_monotone = __commonJS({
"node_modules/cdt2d/lib/monotone.js"(exports, module) {
"use strict";
var bsearch = require_search_bounds();
var orient = require_orientation()[3];
var EVENT_POINT = 0;
var EVENT_END = 1;
var EVENT_START = 2;
module.exports = monotoneTriangulate;
function PartialHull(a, b, idx, lowerIds, upperIds) {
this.a = a;
this.b = b;
this.idx = idx;
this.lowerIds = lowerIds;
this.upperIds = upperIds;
}
function Event(a, b, type, idx) {
this.a = a;
this.b = b;
this.type = type;
this.idx = idx;
}
function compareEvent(a, b) {
var d = a.a[0] - b.a[0] || a.a[1] - b.a[1] || a.type - b.type;
if (d) {
return d;
}
if (a.type !== EVENT_POINT) {
d = orient(a.a, a.b, b.b);
if (d) {
return d;
}
}
return a.idx - b.idx;
}
function testPoint(hull, p) {
return orient(hull.a, hull.b, p);
}
function addPoint(cells, hulls, points, p, idx) {
var lo = bsearch.lt(hulls, p, testPoint);
var hi = bsearch.gt(hulls, p, testPoint);
for (var i = lo; i < hi; ++i) {
var hull = hulls[i];
var lowerIds = hull.lowerIds;
var m = lowerIds.length;
while (m > 1 && orient(
points[lowerIds[m - 2]],
points[lowerIds[m - 1]],
p
) > 0) {
cells.push(
[
lowerIds[m - 1],
lowerIds[m - 2],
idx
]
);
m -= 1;
}
lowerIds.length = m;
lowerIds.push(idx);
var upperIds = hull.upperIds;
var m = upperIds.length;
while (m > 1 && orient(
points[upperIds[m - 2]],
points[upperIds[m - 1]],
p
) < 0) {
cells.push(
[
upperIds[m - 2],
upperIds[m - 1],
idx
]
);
m -= 1;
}
upperIds.length = m;
upperIds.push(idx);
}
}
function findSplit(hull, edge) {
var d;
if (hull.a[0] < edge.a[0]) {
d = orient(hull.a, hull.b, edge.a);
} else {
d = orient(edge.b, edge.a, hull.a);
}
if (d) {
return d;
}
if (edge.b[0] < hull.b[0]) {
d = orient(hull.a, hull.b, edge.b);
} else {
d = orient(edge.b, edge.a, hull.b);
}
return d || hull.idx - edge.idx;
}
function splitHulls(hulls, points, event) {
var splitIdx = bsearch.le(hulls, event, findSplit);
var hull = hulls[splitIdx];
var upperIds = hull.upperIds;
var x = upperIds[upperIds.length - 1];
hull.upperIds = [x];
hulls.splice(
splitIdx + 1,
0,
new PartialHull(event.a, event.b, event.idx, [x], upperIds)
);
}
function mergeHulls(hulls, points, event) {
var tmp = event.a;
event.a = event.b;
event.b = tmp;
var mergeIdx = bsearch.eq(hulls, event, findSplit);
var upper = hulls[mergeIdx];
var lower = hulls[mergeIdx - 1];
lower.upperIds = upper.upperIds;
hulls.splice(mergeIdx, 1);
}
function monotoneTriangulate(points, edges) {
var numPoints = points.length;
var numEdges = edges.length;
var events = [];
for (var i = 0; i < numPoints; ++i) {
events.push(new Event(
points[i],
null,
EVENT_POINT,
i
));
}
for (var i = 0; i < numEdges; ++i) {
var e = edges[i];
var a = points[e[0]];
var b = points[e[1]];
if (a[0] < b[0]) {
events.push(
new Event(a, b, EVENT_START, i),
new Event(b, a, EVENT_END, i)
);
} else if (a[0] > b[0]) {
events.push(
new Event(b, a, EVENT_START, i),
new Event(a, b, EVENT_END, i)
);
}
}
events.sort(compareEvent);
var minX = events[0].a[0] - (1 + Math.abs(events[0].a[0])) * Math.pow(2, -52);
var hull = [new PartialHull([minX, 1], [minX, 0], -1, [], [], [], [])];
var cells = [];
for (var i = 0, numEvents = events.length; i < numEvents; ++i) {
var event = events[i];
var type = event.type;
if (type === EVENT_POINT) {
addPoint(cells, hull, points, event.a, event.idx);
} else if (type === EVENT_START) {
splitHulls(hull, points, event);
} else {
mergeHulls(hull, points, event);
}
}
return cells;
}
}
});
// node_modules/cdt2d/lib/triangulation.js
var require_triangulation = __commonJS({
"node_modules/cdt2d/lib/triangulation.js"(exports, module) {
"use strict";
var bsearch = require_search_bounds();
module.exports = createTriangulation;
function Triangulation(stars, edges) {
this.stars = stars;
this.edges = edges;
}
var proto = Triangulation.prototype;
function removePair(list, j, k) {
for (var i = 1, n = list.length; i < n; i += 2) {
if (list[i - 1] === j && list[i] === k) {
list[i - 1] = list[n - 2];
list[i] = list[n - 1];
list.length = n - 2;
return;
}
}
}
proto.isConstraint = /* @__PURE__ */ (function() {
var e = [0, 0];
function compareLex(a, b) {
return a[0] - b[0] || a[1] - b[1];
}
return function(i, j) {
e[0] = Math.min(i, j);
e[1] = Math.max(i, j);
return bsearch.eq(this.edges, e, compareLex) >= 0;
};
})();
proto.removeTriangle = function(i, j, k) {
var stars = this.stars;
removePair(stars[i], j, k);
removePair(stars[j], k, i);
removePair(stars[k], i, j);
};
proto.addTriangle = function(i, j, k) {
var stars = this.stars;
stars[i].push(j, k);
stars[j].push(k, i);
stars[k].push(i, j);
};
proto.opposite = function(j, i) {
var list = this.stars[i];
for (var k = 1, n = list.length; k < n; k += 2) {
if (list[k] === j) {
return list[k - 1];
}
}
return -1;
};
proto.flip = function(i, j) {
var a = this.opposite(i, j);
var b = this.opposite(j, i);
this.removeTriangle(i, j, a);
this.removeTriangle(j, i, b);
this.addTriangle(i, b, a);
this.addTriangle(j, a, b);
};
proto.edges = function() {
var stars = this.stars;
var result = [];
for (var i = 0, n = stars.length; i < n; ++i) {
var list = stars[i];
for (var j = 0, m = list.length; j < m; j += 2) {
result.push([list[j], list[j + 1]]);
}
}
return result;
};
proto.cells = function() {
var stars = this.stars;
var result = [];
for (var i = 0, n = stars.length; i < n; ++i) {
var list = stars[i];
for (var j = 0, m = list.length; j < m; j += 2) {
var s = list[j];
var t = list[j + 1];
if (i < Math.min(s, t)) {
result.push([i, s, t]);
}
}
}
return result;
};
function createTriangulation(numVerts, edges) {
var stars = new Array(numVerts);
for (var i = 0; i < numVerts; ++i) {
stars[i] = [];
}
return new Triangulation(stars, edges);
}
}
});
// node_modules/robust-in-sphere/in-sphere.js
var require_in_sphere = __commonJS({
"node_modules/robust-in-sphere/in-sphere.js"(exports, module) {
"use strict";
var twoProduct = require_two_product();
var robustSum = require_robust_sum();
var robustDiff = require_robust_diff();
var robustScale = require_robust_scale();
var NUM_EXPAND = 6;
function orientation(n) {
var fn = n === 3 ? inSphere3 : n === 4 ? inSphere4 : n === 5 ? inSphere5 : inSphere6;
return fn(robustSum, robustDiff, twoProduct, robustScale);
}
function inSphere0() {
return 0;
}
function inSphere1() {
return 0;
}
function inSphere2() {
return 0;
}
function inSphere3(sum, diff, prod, scale) {
function exactInSphere3(m0, m1, m2) {
var w0 = prod(m0[0], m0[0]);
var w0m1 = scale(w0, m1[0]);
var w0m2 = scale(w0, m2[0]);
var w1 = prod(m1[0], m1[0]);
var w1m0 = scale(w1, m0[0]);
var w1m2 = scale(w1, m2[0]);
var w2 = prod(m2[0], m2[0]);
var w2m0 = scale(w2, m0[0]);
var w2m1 = scale(w2, m1[0]);
var p = sum(diff(w2m1, w1m2), diff(w1m0, w0m1));
var n = diff(w2m0, w0m2);
var d = diff(p, n);
return d[d.length - 1];
}
return exactInSphere3;
}
function inSphere4(sum, diff, prod, scale) {
function exactInSphere4(m0, m1, m2, m3) {
var w0 = sum(prod(m0[0], m0[0]), prod(m0[1], m0[1]));
var w0m1 = scale(w0, m1[0]);
var w0m2 = scale(w0, m2[0]);
var w0m3 = scale(w0, m3[0]);
var w1 = sum(prod(m1[0], m1[0]), prod(m1[1], m1[1]));
var w1m0 = scale(w1, m0[0]);
var w1m2 = scale(w1, m2[0]);
var w1m3 = scale(w1, m3[0]);
var w2 = sum(prod(m2[0], m2[0]), prod(m2[1], m2[1]));
var w2m0 = scale(w2, m0[0]);
var w2m1 = scale(w2, m1[0]);
var w2m3 = scale(w2, m3[0]);
var w3 = sum(prod(m3[0], m3[0]), prod(m3[1], m3[1]));
var w3m0 = scale(w3, m0[0]);
var w3m1 = scale(w3, m1[0]);
var w3m2 = scale(w3, m2[0]);
var p = sum(sum(scale(diff(w3m2, w2m3), m1[1]), sum(scale(diff(w3m1, w1m3), -m2[1]), scale(diff(w2m1, w1m2), m3[1]))), sum(scale(diff(w3m1, w1m3), m0[1]), sum(scale(diff(w3m0, w0m3), -m1[1]), scale(diff(w1m0, w0m1), m3[1]))));
var n = sum(sum(scale(diff(w3m2, w2m3), m0[1]), sum(scale(diff(w3m0, w0m3), -m2[1]), scale(diff(w2m0, w0m2), m3[1]))), sum(scale(diff(w2m1, w1m2), m0[1]), sum(scale(diff(w2m0, w0m2), -m1[1]), scale(diff(w1m0, w0m1), m2[1]))));
var d = diff(p, n);
return d[d.length - 1];
}
return exactInSphere4;
}
function inSphere5(sum, diff, prod, scale) {
function exactInSphere5(m0, m1, m2, m3, m4) {
var w0 = sum(prod(m0[0], m0[0]), sum(prod(m0[1], m0[1]), prod(m0[2], m0[2])));
var w0m1 = scale(w0, m1[0]);
var w0m2 = scale(w0, m2[0]);
var w0m3 = scale(w0, m3[0]);
var w0m4 = scale(w0, m4[0]);
var w1 = sum(prod(m1[0], m1[0]), sum(prod(m1[1], m1[1]), prod(m1[2], m1[2])));
var w1m0 = scale(w1, m0[0]);
var w1m2 = scale(w1, m2[0]);
var w1m3 = scale(w1, m3[0]);
var w1m4 = scale(w1, m4[0]);
var w2 = sum(prod(m2[0], m2[0]), sum(prod(m2[1], m2[1]), prod(m2[2], m2[2])));
var w2m0 = scale(w2, m0[0]);
var w2m1 = scale(w2, m1[0]);
var w2m3 = scale(w2, m3[0]);
var w2m4 = scale(w2, m4[0]);
var w3 = sum(prod(m3[0], m3[0]), sum(prod(m3[1], m3[1]), prod(m3[2], m3[2])));
var w3m0 = scale(w3, m0[0]);
var w3m1 = scale(w3, m1[0]);
var w3m2 = scale(w3, m2[0]);
var w3m4 = scale(w3, m4[0]);
var w4 = sum(prod(m4[0], m4[0]), sum(prod(m4[1], m4[1]), prod(m4[2], m4[2])));
var w4m0 = scale(w4, m0[0]);
var w4m1 = scale(w4, m1[0]);
var w4m2 = scale(w4, m2[0]);
var w4m3 = scale(w4, m3[0]);