Skip to content

Commit

Permalink
d3.geoPolyhedral() now uses d3-geo-polygon if the plugin is available.
Browse files Browse the repository at this point in the history
Note that d3-geo-polygon is still unstable. When we stream points that belong to the clipping polygon itself, it sometimes bleeds out -- for example on the Waterman projection with a default aspect -- rotate [0,0]).

I have been as conservative as possible: d3-geo-projection works as usual without d3-geo-polygon, and checks that it has projection.preclip (d3-geo > 1.8.1).

Examples and issues at [d3-geo-polygon](https://github.com/d3/d3-geo-polygon)

Solves #129
Solves #124
Solves d3/d3-geo#108
Solves #86
  • Loading branch information
Fil committed Feb 20, 2018
1 parent 2faded3 commit 918dd88
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 10 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"dependencies": {
"commander": "2",
"d3-array": "1",
"d3-geo": "^1.7.1"
"d3-geo": "^1.8.1",
"d3-geo-polygon": "1"
},
"devDependencies": {
"canvas": "1",
Expand Down
6 changes: 4 additions & 2 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ export default {
input: "index",
external: [
"d3-array",
"d3-geo"
"d3-geo",
"d3-geo-polygon"
],
output: {
extend: true,
file: "build/d3-geo-projection.js",
format: "umd",
globals: {
"d3-array": "d3",
"d3-geo": "d3"
"d3-geo": "d3",
"d3-geo-polygon": "d3"
},
name: "d3"
}
Expand Down
21 changes: 17 additions & 4 deletions src/polyhedral/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {geoBounds as bounds, geoCentroid as centroid, geoInterpolate as interpolate, geoProjection as projection} from "d3-geo";
import {geoClipPolygon as clipPolygon} from "d3-geo-polygon";
import {abs, cos, degrees, epsilon, pi, radians, sin} from "../math";
import {default as matrix, multiply, inverse} from "./matrix";

Expand Down Expand Up @@ -94,15 +95,27 @@ export default function(root, face, r) {
var proj = projection(forward),
stream_ = proj.stream;

// if d3-geo-polygon and proj.preclip are available:
// run around the mesh of faces and stream all vertices to create the clipping polygon
if (clipPolygon && proj.preclip) {
var polygon = [];
outline({point: function(lambda, phi) { polygon.push([lambda, phi]); }}, 1e-4, root);
proj.preclip(clipPolygon({ type: "Polygon", coordinates: [ polygon ] }));
}

function noClip(s) { return s; }

proj.stream = function(stream) {
var rotate = proj.rotate(),
preclip = proj.preclip ? proj.preclip() : null,
rotateStream = stream_(stream),
sphereStream = (proj.rotate([0, 0]), stream_(stream));
sphereStream = ((preclip ? proj.preclip(noClip) : proj).rotate([0, 0]), stream_(stream));
proj.rotate(rotate);
if (preclip) proj.preclip(preclip);
rotateStream.sphere = function() {
sphereStream.polygonStart();
sphereStream.lineStart();
outline(sphereStream, root);
outline(sphereStream, epsilon, root);
sphereStream.lineEnd();
sphereStream.polygonEnd();
};
Expand All @@ -112,7 +125,7 @@ export default function(root, face, r) {
return proj;
}

function outline(stream, node, parent) {
function outline(stream, epsilon, node, parent) {
var point,
edges = node.edges,
n = edges.length,
Expand Down Expand Up @@ -142,7 +155,7 @@ function outline(stream, node, parent) {
stream.point((point = interpolate(edge[1], c)(epsilon))[0], point[1]);
} else {
inside = false;
if (edge !== parent) outline(stream, edge, node);
if (edge !== parent) outline(stream, epsilon, edge, node);
}
}
}
Expand Down
17 changes: 14 additions & 3 deletions test/render-world
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,25 @@ switch (projectionName) {
case "modifiedStereographicMiller": outline = graticule.extent([[-40, -40], [80, 80]]).outline(); break;
}

var path = d3.geoPath()
.projection(d3[projectionSymbol]().precision(0.1))
.context(context);
var projection = d3[projectionSymbol]().precision(0.1),
path = d3.geoPath()
.projection(projection)
.context(context);

context.fillStyle = "#fff";
context.fillRect(0, 0, width, height);
context.save();

// don't switch to polygon clipping yet for the historical polyhedral projections
switch (projectionName) {
case "polyhedralButterfly":
case "polyhedralWaterman":
case "polyhedralCollignon": {
projection.preclip(d3.geoClipAntimeridian);
break;
}
}

switch (projectionName) {
case "armadillo":
case "berghaus":
Expand Down

0 comments on commit 918dd88

Please sign in to comment.