17

I have the Lat/Long value of New York City, NY; 40.7560540,-73.9869510 and a flat image of the earth, 1000px × 446px.

I would like to be able to convert, using Javascript, the Lat/Long to an X,Y coordinate where the point would reflect the location.

So the X,Y coordinate form the Top-Left corner of the image would be; 289, 111

Things to note:

  1. don't worry about issues of what projection to use, make your own assumption or go with what you know might work
  2. X,Y can be form any corner of the image
  3. Bonus points for the same solution in PHP (but I really need the JS)
winwaed
  • 7,645
  • 6
  • 36
  • 81
donohoe
  • 13,867
  • 4
  • 37
  • 59
  • "Don't worry about ... what projection to use" how then do we know what the X Y co-ord mapping will be? I could have just said X is Lat, Y is Long and that probably would have satisfied you since apparently the result doesn't need to mean anything or relate to a real world projection. – 1owk3y Aug 30 '17 at 04:31
  • There's a good Javascript library, [PROJ4JS](http://proj4js.org/), that allows you to do transformations between different projections. – andri Jun 20 '09 at 01:59

3 Answers3

18

The projection you use is going to change everything, but this will work assuming a Mercator projection:

<html>
<head>
<script language="Javascript">
var dot_size = 3;
var longitude_shift = 55;   // number of pixels your map's prime meridian is off-center.
var x_pos = 54;
var y_pos = 19;
var map_width = 430;
var map_height = 332;
var half_dot = Math.floor(dot_size / 2);
function draw_point(x, y) {
    dot = '<div style="position:absolute;width:' + dot_size + 'px;height:' + dot_size + 'px;top:' + y + 'px;left:' + x + 'px;background:#00ff00"></div>';
    document.body.innerHTML += dot;
}
function plot_point(lat, lng) {
    // Mercator projection

    // longitude: just scale and shift
    x = (map_width * (180 + lng) / 360) % map_width + longitude_shift;

    // latitude: using the Mercator projection
    lat = lat * Math.PI / 180;  // convert from degrees to radians
    y = Math.log(Math.tan((lat/2) + (Math.PI/4)));  // do the Mercator projection (w/ equator of 2pi units)
    y = (map_height / 2) - (map_width * y / (2 * Math.PI)) + y_pos;   // fit it to our map

    x -= x_pos;
    y -= y_pos;

    draw_point(x - half_dot, y - half_dot);
}
</script>
</head>
<body onload="plot_point(40.756, -73.986)">
    <!-- image found at http://www.math.ubc.ca/~israel/m103/mercator.png -->
    <img src="mercator.png" style="position:absolute;top:0px;left:0px">
</body>
</html>
Community
  • 1
  • 1
Paul A Jungwirth
  • 23,504
  • 14
  • 74
  • 93
  • This also worked for me and is an excellent answer. I did have change 'lng' to 'parseInt(lng, 10)' on this line: x = (map_width * (180 + lng) / 360 + longitude_shift) % map_width; It would work when I manually call the function, put passing value from an array returned NaN for x Thanks! – donohoe Jun 21 '09 at 02:32
  • i think x = (map_width * (180 + lng) / 360 + longitude_shift) % map_width; should be x = ((map_width * (180 + lng) / 360) % map_width) + longitude_shift; otherwise japan and the east coast of australia (me included) get "wrapped" to the middle of the pacific ocean. :P – mat kelcey Oct 15 '09 at 11:20
  • Awesome, works great! Only thing I didn't find what the y_pos did? This in PHP is: $lat = $lat * M_PI / 180; // convert from degrees to radians $y = log(tan(($lat/2) + (M_PI/4))); // do the Mercator projection (w/ equator of 2pi units) $targetY = ($h / 2) - ($w * $y / (2 * M_PI)); //+ y_pos; // fit it to our map ?> – PanMan Aug 02 '11 at 20:18
  • @PanMan: y_pos was because the image referenced in the code has a 19-pixel top border, so you need to go down 19 pixels before you reach the map. – Paul A Jungwirth Aug 03 '11 at 12:27
  • @mat: Thanks! Code is fixed now. – Paul A Jungwirth Aug 03 '11 at 12:30
  • 1
    thank you! your point 40.756, -73.986 located in New York, but example show point in Canada. – Ramil Amerzyanov Sep 21 '13 at 15:19
  • what is x_pos and y_pos? since you add y_pos to y and then removing it 3 lines later, what's the point? – shredding Dec 16 '15 at 10:11
  • @shredding if you look at the comment history you'll see I didn't add those lines. :-) Also it's been six years since I wrote the code. . . . But x_pos and y_pos are the offset to the "start" of the map since the image I used originally had a white border around the edges. – Paul A Jungwirth Dec 16 '15 at 16:03
  • I tested this and it doesn't work at all. I literally copied and pasted the code, and it showed the wrong location for a coordinate. It didn't even match up with the guides – rubixibuc Mar 01 '23 at 01:18
8

A basic conversion function in js would be:

MAP_WIDTH = 1000;
MAP_HEIGHT = 446;

function convert(lat, lon){
    var y = ((-1 * lat) + 90) * (MAP_HEIGHT / 180);
    var x = (lon + 180) * (MAP_WIDTH / 360);
    return {x:x,y:y};
}

This will return the number of pixels from upper left. This function assumes the following:

  1. That your image is properly aligned with the upper left corner (0,0) aligning with 90* North by 180* West.
  2. That your coords are signed with N being -, S being +, W being - and E being +
Mike Clark
  • 11,769
  • 6
  • 39
  • 43
0

If you have a picture of the whole earth, the projection does always matter. But maybe I just don't understand your question.

hanno
  • 6,401
  • 8
  • 48
  • 80
  • You are correct, but in this case I would gladly use an appropriate image to match a working solution for a specific projection. – donohoe Jun 21 '09 at 00:47