Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V5 — fully robust, no transpilation, native ESM #68

Merged
merged 5 commits into from
Mar 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
language: node_js
node_js:
- "10"
- "node"
- "12"
- "14"
24 changes: 6 additions & 18 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
const EPSILON = Math.pow(2, -52);
const EDGE_STACK = new Uint32Array(512);

import {orient2d} from 'robust-predicates';

export default class Delaunator {

static from(points, getX = defaultGetX, getY = defaultGetY) {
Expand Down Expand Up @@ -129,7 +131,7 @@ export default class Delaunator {
}

// swap the order of the seed points for counter-clockwise orientation
if (orient(i0x, i0y, i1x, i1y, i2x, i2y)) {
if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) {
const i = i1;
const x = i1x;
const y = i1y;
Expand Down Expand Up @@ -194,7 +196,7 @@ export default class Delaunator {

start = hullPrev[start];
let e = start, q;
while (q = hullNext[e], !orient(x, y, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1])) {
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;
Expand All @@ -213,7 +215,7 @@ export default class Delaunator {

// walk forward through the hull, adding more triangles and flipping recursively
let n = hullNext[e];
while (q = hullNext[n], orient(x, y, coords[2 * n], coords[2 * n + 1], coords[2 * q], coords[2 * q + 1])) {
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
Expand All @@ -223,7 +225,7 @@ export default class Delaunator {

// walk backward from the other side, adding more triangles and flipping
if (e === start) {
while (q = hullPrev[e], orient(x, y, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1])) {
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;
Expand Down Expand Up @@ -378,20 +380,6 @@ function dist(ax, ay, bx, by) {
return dx * dx + dy * dy;
}

// return 2d orientation sign if we're confident in it through J. Shewchuk's error bound check
function orientIfSure(px, py, rx, ry, qx, qy) {
const l = (ry - py) * (qx - px);
const r = (rx - px) * (qy - py);
return Math.abs(l - r) >= 3.3306690738754716e-16 * Math.abs(l + r) ? l - r : 0;
}

// a more robust orientation test that's stable in a given triangle (to fix robustness issues)
function orient(rx, ry, qx, qy, px, py) {
return (orientIfSure(px, py, rx, ry, qx, qy) ||
orientIfSure(rx, ry, qx, qy, px, py) ||
orientIfSure(qx, qy, px, py, rx, ry)) < 0;
}

function inCircle(ax, ay, bx, by, cx, cy, px, py) {
const dx = ax - px;
const dy = ay - py;
Expand Down
29 changes: 17 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@
"name": "delaunator",
"version": "4.0.1",
"description": "An incredibly fast JavaScript library for Delaunay triangulation of 2D points",
"main": "delaunator.js",
"main": "index.js",
"module": "index.js",
"type": "module",
"jsdelivr": "delaunator.min.js",
"unpkg": "delaunator.min.js",
"sideEffects": false,
"dependencies": {},
"dependencies": {
"robust-predicates": "^3.0.0"
},
"devDependencies": {
"c8": "^7.1.0",
"eslint": "^6.8.0",
"@rollup/plugin-node-resolve": "^11.2.0",
"c8": "^7.6.0",
"eslint": "^7.22.0",
"eslint-config-mourner": "^3.0.0",
"esm": "^3.2.25",
"rollup": "^1.31.1",
"rollup-plugin-buble": "^0.19.8",
"rollup-plugin-terser": "^5.2.0",
"tape": "^4.13.0"
"rollup": "^2.42.4",
"rollup-plugin-terser": "^7.0.2",
"tape": "^5.2.2"
},
"repository": {
"type": "git",
Expand All @@ -25,9 +27,9 @@
"scripts": {
"lint": "eslint index.js test/test.js bench.js rollup.config.js docs/diagrams.js",
"pretest": "npm run lint",
"test": "node -r esm test/test.js",
"cov": "c8 node -r esm test/test.js && c8 report -r html",
"bench": "node -r esm bench.js",
"test": "node test/test.js",
"cov": "c8 node test/test.js && c8 report -r html",
"bench": "node bench.js",
"build": "rollup -c",
"start": "rollup -cw",
"prepublishOnly": "npm test && npm run build"
Expand All @@ -41,6 +43,9 @@
"extends": "mourner",
"rules": {
"no-sequences": 0
},
"parserOptions": {
"ecmaVersion": 2020
}
},
"keywords": [
Expand Down
9 changes: 4 additions & 5 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import {terser} from 'rollup-plugin-terser';
import buble from 'rollup-plugin-buble';
import resolve from '@rollup/plugin-node-resolve';

const config = (file, plugins) => ({
input: 'index.js',
output: {
name: 'Delaunator',
format: 'umd',
indent: false,
file
},
plugins
});

const bubleConfig = {transforms: {dangerousForOf: true}};

export default [
config('delaunator.js', [buble(bubleConfig)]),
config('delaunator.min.js', [terser(), buble(bubleConfig)])
config('delaunator.js', [resolve()]),
config('delaunator.min.js', [resolve(), terser()])
];
1 change: 1 addition & 0 deletions test/fixtures/robustness3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[[1.2000108248775223,0.08939813876119695],[3.197878575122478,0.08939813876119695],[3.9347512248775223,0.08939813876119695],[5.932618975122478,0.08939813876119695],[6.669491624877522,0.08939813876119695],[1.2000108248775223,1.9106018612388114],[3.197878575122478,1.9106018612388114],[3.9347512248775223,1.9106018612388114],[5.932618975122478,1.9106018612388114],[6.669491624877522,1.9106018612388114],[2.0267626140791766,-0.21046296655057145],[2.371126785920824,-0.21046296655057145],[4.761503014079176,-0.21046296655057145],[5.105867185920824,-0.21046296655057145],[7.496243414079176,-0.21046296655057145],[2.0267626140791766,2.2104629665505797],[2.371126785920824,2.2104629665505797],[4.761503014079176,2.2104629665505797],[5.105867185920824,2.2104629665505797],[7.496243414079176,2.2104629665505797],[1.5802128246274927,0.22503184151033584],[2.8176765753725075,0.22503184151033584],[4.314953224627493,0.22503184151033584],[5.552416975372507,0.22503184151033584],[7.049693624627492,0.22503184151033584],[1.5802128246274927,1.7749681584896724],[2.8176765753725075,1.7749681584896724],[4.314953224627493,1.7749681584896724],[5.552416975372507,1.7749681584896724],[7.049693624627492,1.7749681584896724],[0.8315745000000003,1.000000000000004],[3.5663149,1.000000000000004],[3.5663149,1.000000000000004],[6.3010553,1.000000000000004],[6.3010553,1.000000000000004],[0.8315745000000003,1.0000000000000044],[3.5663149,1.0000000000000044],[3.5663149,1.0000000000000044],[6.3010553,1.0000000000000044],[6.3010553,1.0000000000000044],[0.8315745000000003,-0.488685099999997],[3.5663149,-0.488685099999997],[3.5663149,-0.488685099999997],[6.3010553,-0.488685099999997],[6.3010553,-0.488685099999997],[0.8315745000000003,2.4886851000000054],[3.5663149,2.4886851000000054],[3.5663149,2.4886851000000054],[6.3010553,2.4886851000000054],[6.3010553,2.4886851000000054],[2.1989447,-0.61],[2.1989447,-0.61],[4.9336851,-0.61],[4.9336851,-0.61],[7.6684255,-0.61],[2.1989447,2.6100000000000083],[2.1989447,2.6100000000000083],[4.9336851,2.6100000000000083],[4.9336851,2.6100000000000083],[7.6684255,2.6100000000000083],[2.1989447,0.878685100000001],[2.1989447,0.878685100000001],[4.9336851,0.878685100000001],[4.9336851,0.878685100000001],[7.6684255,0.878685100000001],[2.1989447,1.1213149000000073],[2.1989447,1.1213149000000073],[4.9336851,1.1213149000000073],[4.9336851,1.1213149000000073],[7.6684255,1.1213149000000073]]
1 change: 1 addition & 0 deletions test/fixtures/robustness4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[[-3.0381276552207055, 10.481881920449052], [-2.1931270567413446, 11.016647278872279], [-1.3481264582619854, 11.551412637295508], [-0.5031258597826245, 12.086177995718735], [0.3418747386967347, 12.620943354141964], [1.1868753371760938, 13.155708712565193], [-2.5033622967974765, 9.63688132196969], [-1.6583616983181173, 10.171646680392918], [-0.8133610998387582, 10.706412038816147], [0.03163949864060278, 11.241177397239376], [0.8766400971199619, 11.775942755662605], [1.721640695599322, 12.310708114085832], [-1.9685969383742474, 8.791880723490332], [-1.1235963398948883, 9.326646081913559], [-0.2785957414155291, 9.861411440336788], [0.5664048570638318, 10.396176798760017], [1.411405455543191, 10.930942157183246], [2.25640605402255, 11.465707515606473], [-1.4338315799510184, 7.9468801250109715], [-0.5888309814716592, 8.4816454834342], [0.2561696170076999, 9.016410841857429], [1.10117021548706, 9.551176200280658], [1.94617081396642, 10.085941558703885], [2.791171412445779, 10.620706917127112], [-0.8990662215277911, 7.1018795265316115], [-0.05406562304843021, 7.6366448849548405], [0.7909349754309281, 8.17141024337807], [1.635935573910288, 8.706175601801297], [2.4809361723896473, 9.240940960224526], [3.3259367708690073, 9.775706318647753], [-0.3643008631045621, 6.256878928052252], [0.48069973537479704, 6.7916442864754805], [1.3257003338541562, 7.326409644898709], [2.1707009323335162, 7.861175003321938], [3.0157015308128763, 8.395940361745165], [3.8607021292922354, 8.930705720168394]]
21 changes: 15 additions & 6 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@

import {test} from 'tape';
import Delaunator from '../index.js';
import {readFileSync} from 'fs';

import points from './fixtures/ukraine.json';
import issue13 from './fixtures/issue13.json';
import issue43 from './fixtures/issue43.json';
import issue44 from './fixtures/issue44.json';
import robustness1 from './fixtures/robustness1.json';
import robustness2 from './fixtures/robustness2.json';
function loadJSON(path) {
return JSON.parse(readFileSync(new URL(path, import.meta.url), 'utf8'));
}

const points = loadJSON('./fixtures/ukraine.json');
const issue13 = loadJSON('./fixtures/issue13.json');
const issue43 = loadJSON('./fixtures/issue43.json');
const issue44 = loadJSON('./fixtures/issue44.json');
const robustness1 = loadJSON('./fixtures/robustness1.json');
const robustness2 = loadJSON('./fixtures/robustness2.json');
const robustness3 = loadJSON('./fixtures/robustness3.json');
const robustness4 = loadJSON('./fixtures/robustness4.json');

test('triangulates plain array', (t) => {
const d = new Delaunator([].concat(...points));
Expand Down Expand Up @@ -88,6 +95,8 @@ test('robustness', (t) => {
validate(t, robustness1.map(p => [p[0] * 1e9, p[1] * 1e9]));
validate(t, robustness2.slice(0, 100));
validate(t, robustness2);
validate(t, robustness3);
validate(t, robustness4);
t.end();
});

Expand Down