Skip to content

Commit

Permalink
more robustness wrt NaN, Infinity…
Browse files Browse the repository at this point in the history
  • Loading branch information
Fil committed May 21, 2019
1 parent 0d18b55 commit d9ec0ba
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 24 deletions.
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "d3-geo-voronoi",
"version": "1.2.1",
"version": "1.3.0",
"description": "Spherical Voronoi Diagram and Delaunay Triangulation",
"keywords": [
"d3",
Expand All @@ -9,9 +9,9 @@
"d3-delaunay"
],
"license": "MIT",
"main": "build/d3-geo-voronoi.js",
"unpkg": "build/d3-geo-voronoi.min.js",
"jsdelivr": "build/d3-geo-voronoi.min.js",
"main": "dist/d3-geo-voronoi.js",
"unpkg": "dist/d3-geo-voronoi.min.js",
"jsdelivr": "dist/d3-geo-voronoi.min.js",
"module": "index",
"jsnext:main": "index",
"homepage": "https://github.com/Fil/d3-geo-voronoi",
Expand All @@ -24,10 +24,10 @@
"url": "https://github.com/Fil"
},
"scripts": {
"pretest": "rm -rf build && mkdir build && rollup --banner \"$(preamble)\" -g d3-array:d3,d3-geo:d3,d3-delaunay:d3 -f umd -n d3 --extend d3 -o build/d3-geo-voronoi.js -- index.js",
"pretest": "rm -rf dist && mkdir dist && rollup --banner \"$(preamble)\" -g d3-array:d3,d3-geo:d3,d3-delaunay:d3 -f umd -n d3 --extend d3 -o dist/d3-geo-voronoi.js -- index.js",
"test": "tape 'test/**/*-test.js'",
"prepublishOnly": "npm run test && terser --preamble \"$(preamble)\" build/d3-geo-voronoi.js -c passes=2 -c negate_iife=false -m -o build/d3-geo-voronoi.min.js",
"postpublish": "zip -j build/d3-geo-voronoi.zip -- LICENSE README.md build/d3-geo-voronoi.js build/d3-geo-voronoi.min.js"
"prepublishOnly": "npm run test && terser --preamble \"$(preamble)\" dist/d3-geo-voronoi.js -c passes=2 -c negate_iife=false -m -o dist/d3-geo-voronoi.min.js",
"postpublish": "zip -j dist/d3-geo-voronoi.zip -- LICENSE README.md dist/d3-geo-voronoi.js dist/d3-geo-voronoi.min.js"
},
"dependencies": {
"d3-array": "^2.0",
Expand Down
17 changes: 11 additions & 6 deletions src/delaunay.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,25 @@ function geo_find(neighbors, points) {
function geo_delaunay_from(points) {
if (points.length < 2) return {};

const r = geoRotation(points[0]),
// find a valid point to send to infinity
let pivot = 0;
while (isNaN(points[pivot][0]+points[pivot][1]) && pivot++ < points.length) {}

const r = geoRotation(points[pivot]),
projection = geoStereographic()
.translate([0, 0])
.scale(1)
.rotate(r.invert([180, 0]));
points = points.map(projection);

const zeros = [0];
const zeros = [];
let max2 = 1;
for (let i = 1, n = points.length; i < n; i++) {
let m = points[i][0] * points[i][0] + points[i][1] * points[i][1];
if (isNaN(m)) zeros.push(i);
if (m > max2) max2 = m;
for (let i = 0, n = points.length; i < n; i++) {
let m = points[i][0] ** 2 + points[i][1] ** 2;
if (!isFinite(m)) zeros.push(i);
else if (m > max2) max2 = m;
}

const FAR = 1e6 * sqrt(max2);

zeros.forEach(i => (points[i] = [FAR / 2, i]));
Expand Down
38 changes: 28 additions & 10 deletions src/voronoi.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ export function geoVoronoi(data) {
v._data = v._data.features;
}
if (typeof v._data === "object") {
v.points = v._data.map(i => [v._vx(i), v._vy(i)]);
const temp = v._data
.map(d => [v._vx(d), v._vy(d), d])
.filter(d => isFinite(d[0] + d[1]));
v.points = temp.map(d => [d[0], d[1]]);
v.valid = temp.map(d => d[2]);
v.delaunay = geoDelaunay(v.points);
}
return v;
Expand Down Expand Up @@ -53,12 +57,15 @@ export function geoVoronoi(data) {
if (data !== undefined) {
v(data);
}

if (!v.delaunay) return false;
if (v._data.length === 0) return null;
if (v._data.length === 1) return { type: "Sphere" };
return {
const coll = {
type: "FeatureCollection",
features: v.delaunay.polygons.map((poly, i) => ({
features: []
};
if (v.valid.length === 0) return coll;
v.delaunay.polygons.forEach((poly, i) =>
coll.features.push({
type: "Feature",
geometry: !poly
? null
Expand All @@ -67,12 +74,23 @@ export function geoVoronoi(data) {
coordinates: [[...poly, poly[0]].map(i => v.delaunay.centers[i])]
},
properties: {
site: v._data[i],
site: v.valid[i],
sitecoordinates: v.points[i],
neighbours: v.delaunay.neighbors[i] // not part of the public API
}
}))
};
})
);
if (v.valid.length === 1)
coll.features.push({
type: "Feature",
geometry: { type: "Sphere" },
properties: {
site: v.valid[0],
sitecoordinates: v.points[0],
neighbours: []
}
});
return coll;
};

v.triangles = function(data) {
Expand Down Expand Up @@ -117,8 +135,8 @@ export function geoVoronoi(data) {
features: v.delaunay.edges.map((e, i) => ({
type: "Feature",
properties: {
source: v._data[e[0]],
target: v._data[e[1]],
source: v.valid[e[0]],
target: v.valid[e[1]],
length: _distances[i],
urquhart: !!_urquart[i]
},
Expand Down
16 changes: 15 additions & 1 deletion test/geo-voronoi-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,24 @@ tape("geoVoronoi.polygons(sites) tolerates NaN.", function(test) {
//var u = geoVoronoi.geoVoronoi().polygons(sites)[0][0], v = [ 5, 4.981069 ];
//test.ok( (Math.abs(u[0]-v[0]) < 1e-6) && (Math.abs(u[1]-v[1]) < 1e-6) );
const sites = [[0, 0], [2, 1], [NaN, -1], [4, NaN], [5,10]];
var u = geoVoronoi.geoVoronoi(sites).polygons()
var u = geoVoronoi.geoVoronoi(sites).polygons();
test.end();
});

tape("geoVoronoi.polygons([no valid site]) returns an empty collection.", function(test) {
const sites = [[NaN, -1], [4, NaN], [Infinity,10]];
var u = geoVoronoi.geoVoronoi(sites).polygons();
test.deepEqual(u.features, []);
test.end();
});

tape("geoVoronoi.polygons([1 site]) returns a Sphere.", function(test) {
const sites = [[NaN, -1], [4, NaN], [5,10]];
var u = geoVoronoi.geoVoronoi(sites).polygons();
test.equal(u.features[0].type, "Feature");
test.equal(u.features[0].geometry.type, "Sphere");
test.end();
});

var sites = [[0,0], [10,0], [0,10]];

Expand Down

0 comments on commit d9ec0ba

Please sign in to comment.