6

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)

1 Answer 1

8

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.

2
  • thanks mike! Now I just need to find an NYC shapefile that I can render with SVG without breaking my laptop
    – Mike Dewar
    Commented Mar 9, 2012 at 11:51
  • And once again we see why look at this link to ... are discouraged. That would be a 404. Was it this one? gist.github.com/minikomi/4552802
    – user13500
    Commented Mar 2, 2014 at 19:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.