Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scaling d3.js projections

I'm trying to draw a map of NYC using d3. I've downloaded a bunch of shapefiles from http://www.nyc.gov/html/dcp/html/bytes/dwndistricts.shtml. I've converted them to geoJSON using http://converter.mygeodata.eu/, such that they're in WGS 84 (aka, I think, latitude and longitude).

I'm pretty sure the geoJSON is valid: I can plot it using matplotlib and it looks like NYC, and the numbers seem to be in a valid range. Here's my javascript:

var path = d3.geo.path()
d3.select("body")
  .append("svg")
    .attr("height", 1000)
    .attr("width", 1000)
  .append("g")
  .selectAll("path")
  .data(data.features)
  .enter()
  .append("path")
    .attr("d", path)
    .style("stroke","black")
    .style("stroke-width","1px")

This plots, as advertised, the Albers projection of NYC. Trouble is, I think, that the scale of the projection is chosen so that the US fits onto a nice webpage, making the paths for NYC a little squiggle at the right-hand-side of the screen.

What's the 'correct' way (lemme try to claim to be the first to say d3onic) to scale a geo.path() such that the extents of my lat/lon scale onto the width and height of my SVG?

(little disclaimer: apologies if I've missed something obvious, this is for a project I'm trying to complete at the extreme ends of the day)

like image 847
Mike Dewar Avatar asked Mar 09 '12 03:03

Mike Dewar


People also ask

What is projection in d3?

geoProjection or d3. geoProjectionMutator. # projection(point) <> Returns a new array [x, y] (typically in pixels) representing the projected point of the given point. The point must be specified as a two-element array [longitude, latitude] in degrees.

What is the use of d3 Geopath () method?

The d3. geopath function takes our projection, and returns another function that can be used to generate the d attribute for the path element. path is now a function which accepts GeoJSON polygons, and returns a string which can directly be used as the d attribute of an SVG path.


1 Answers

First, you'll want to create a projection, and assign that to the d3.geo.path, so that you can customize the projection settings.

var albers = d3.geo.albers(),
    path = d3.geo.path().projection(albers);

The default projection is d3.geo.albersUsa, which is actually a composite projection (with four different discontinuous areas) designed for showing the 48 states, Alaska, Hawaii and Puerto Rico. Ah, ethnocentrism. ;)

Use the albers example in the git repository to determine the correct projection settings interactively. The settings you need to set are:

  • the origin should be NYC's latitude and longitude (perhaps 73.98°, 40.71°)
  • the translate should be the center of your display area (so, if you're drawing something 960×500, you can use the default 480,250; this will be the pixel location of the origin)
  • the scale is some number that specifies how much to zoom-in; since you're drawing a city-scale map, you probably want a value more like 10000

Lastly, you'll need to pick some parallels. You can use the defaults provided by d3.geo.albers(), but there might be more suitable ones for NYC. Possibly check with the USGS, because they often publish standard parallels for different map areas.

like image 164
mbostock Avatar answered Nov 15 '22 11:11

mbostock