15

I'm trying to plot a few points onto a map using the D3 geo library based on latitudes and longitudes. However, when I pass these values into my projection function, it results in coordinates that our outside the bounds of my SVG image. My code is based on this example provided in the documentation.

I've thrown the current code up at: http://bl.ocks.org/rpowelll/8312317

My source data is a simple array of objects formatted like so

var places = [
  {
    name: "Wollongong, Australia",
    location: {
      latitude: -34.42507,
      longitude: 150.89315
    }
  },
  {
    name: "Newcastle, Australia",
    location: {
      latitude: -32.92669,
      longitude: 151.77892
    }
  }
]

Following this I set up an Plate Carrée projection like so:

var width = 960,
height = 480

var projection = d3.geo.equirectangular()
    .scale(153)
    .translate([width / 2, height / 2])
    .precision(.1);

var path = d3.geo.path()
    .projection(projection)

From there I draw the map with code effectively identical to the linked example. At the end of my script, I use the following code to plot points on this map:

svg.selectAll(".pin")
    .data(places)
  .enter().append("circle", ".pin")
    .attr("r", 5)
    .attr("transform", function(d) {
      return "translate(" + projection([
        d.location.latitude,
        d.location.longitude
      ]) + ")"
    })

However this code results in points that are outside of the SVG element's bounds. Is there anything obvious I'm doing wrong here?

rpowell
  • 1,464
  • 2
  • 16
  • 29
  • Sounds like the scale/translate of your projection is off. [This question](http://stackoverflow.com/questions/14492284/center-a-map-in-d3-given-a-geojson-object) may help. – Lars Kotthoff Jan 08 '14 at 09:45
  • It seems like the projection itself is alright, as the actual map path uses the same projection and draws without issue. – rpowell Jan 08 '14 at 10:09

1 Answers1

24

You have a simple typo in your code -- coordinates should be passed as (longitude, latitude) to the projection, not the other way round. This code should work fine:

 svg.selectAll(".pin")
  .data(places)
  .enter().append("circle", ".pin")
  .attr("r", 5)
  .attr("transform", function(d) {
    return "translate(" + projection([
      d.location.longitude,
      d.location.latitude
    ]) + ")";
  });
Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
Lars Kotthoff
  • 107,425
  • 16
  • 204
  • 204
  • 2
    Thank you so much! That seems somewhat counterintuitive though. – rpowell Jan 08 '14 at 10:16
  • 1
    @rpowell It is counterintuitive because we *say* "latitude and longitude", but we say them backwards -- longitude is the x-coordinate and latitude is the y-coordinate, and the translation expects its arguments in the order x, y. – BallpointBen Jun 14 '20 at 05:24