1

I am trying to return [x,y] geo coordinates on a geo tile map. If you look in the console log on the following jsfiddle you will see they are coming out wrong. I am using the projection.invert() function, which I assume works backwards from the pixels to get back to the geo coordinates ... what am I doing wrong?

This is the bit of code that tries to seize the coordinates:

function mousemoved() {
  console.log(formatLocation(projection.invert(d3.mouse(this)), d3.zoomTransform(this).k));
}

function formatLocation(p, k) {
  var format = d3.format("." + Math.floor(Math.log(k) / 2 - 2) + "f");
  return (p[1] < 0 ? format(-p[1]) + "°S" : format(p[1]) + "°N") + " "
       + (p[0] < 0 ? format(-p[0]) + "°W" : format(p[0]) + "°E");
}
Noobster
  • 1,024
  • 1
  • 13
  • 28
  • Am guessing the dude who downvoted this knows the answer to the question ... :) – Noobster Jun 16 '18 at 19:04
  • 1
    Didn't down vote, but might have an answer for this (I find the d3-tile projection a bit of a run-around, inverting it will probably require a bit of run around too). – Andrew Reid Jun 16 '18 at 19:37
  • Hello Andrew. I've been struggling with the projection on D3 Tiles. I raised another question that is similar on here: https://stackoverflow.com/questions/50891330/cannot-get-labels-to-work-with-d3-tile-projection – Noobster Jun 16 '18 at 20:03

1 Answers1

2

D3-tile examples (and your fiddle) that I'm aware of (including most of the examples in the d3-tile documentation) generally use a projection scale of 1/tau (and no projection translate values) which would draw the earth within the space of a single pixel.

var projection = d3.geoMercator()
    .scale(1 / tau)
    .translate([0, 0]); 

While the projection converts the 3 dimensional latitude/longitude pairs to Cartesian coordinates, a d3-zoom does all the scaling and translating to fill the map dimensions. This zoom must be accounted for when inverting mouse coordinates to long/lat pairs.

So to get the latitude/longitude pairs of a point on the svg, we need to backtrack. First we need to get the mouse coordinate if we were to invert the zoom, and then we can invert the projection:

var transform = d3.zoomTransform(svg.node()); // get the current zoom
var xy = transform.invert(d3.mouse(this));    
var longlat = projection.invert(xy);          

(See also, this answer on transform.invert())

Here's an updated fiddle.

Andrew Reid
  • 37,021
  • 7
  • 64
  • 83
  • Thanks Andrew - this is a very complete answer. I see this has also been the subject of a debate on here https://github.com/d3/d3-plugins/issues/37 and that other peeps have been struggling to understand how the projection works in d3-tiles. – Noobster Jun 17 '18 at 03:14