Skip to content

Instantly share code, notes, and snippets.

@tpreusse
Forked from nrabinowitz/fitProjection.js
Last active July 21, 2016 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tpreusse/6e81ae2feb01bdb9a824eeb84807c85c to your computer and use it in GitHub Desktop.
Save tpreusse/6e81ae2feb01bdb9a824eeb84807c85c to your computer and use it in GitHub Desktop.
D3 function for fitting a projection to geodata
import d3 from 'd3';
export const fitProjection = (projection, data, box, center) => {
// get the bounding box for the data - might be more efficient approaches
let left = Infinity;
let bottom = -Infinity;
let right = -Infinity;
let top = Infinity;
// reset projection
projection.scale(1).translate([0, 0]);
data.features.forEach((feature) => {
d3.geo.bounds(feature).forEach((coords) => {
const [x, y] = projection(coords);
if (x < left) left = x;
if (x > right) right = x;
if (y > bottom) bottom = y;
if (y < top) top = y;
});
});
// project the bounding box, find aspect ratio
const width = (bb) => (bb[1][0] - bb[0][0]);
const height = (bb) => (bb[1][1] - bb[0][1]);
const aspect = (bb) => width(bb) / height(bb);
const startbox = [[left, top], [right, bottom]];
const widthDetermined = aspect(startbox) > aspect(box);
const scale = widthDetermined ?
// scale determined by width
width(box) / width(startbox) :
// scale determined by height
height(box) / height(startbox);
// set x translation
let transX = box[0][0] - startbox[0][0] * scale;
// set y translation
let transY = box[0][1] - startbox[0][1] * scale;
// center if requested
if (center) {
if (widthDetermined) {
transY = transY - (transY + startbox[1][1] * scale - box[1][1]) / 2;
} else {
transX = transX - (transX + startbox[1][0] * scale - box[1][0]) / 2;
}
}
return projection.scale(scale).translate([transX, transY]);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment