Convert Lat/Longs to X/Y Co-ordinates
Asked Answered
M

3

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)
Maddis answered 19/6, 2009 at 20:56 Comment(2)
There's a good Javascript library, PROJ4JS, that allows you to do transformations between different projections.Eduard
"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.Holytide
C
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 +
Camfort answered 19/6, 2009 at 21:54 Comment(1)
Thanks, how to reverse this ? So from X and Y to lat/long with specified bounding box coordinates ?Glorianna
A
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>
Ampulla answered 20/6, 2009 at 1:4 Comment(9)
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!Maddis
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. :PXanthippe
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 ?>Katabatic
@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.Ampulla
@mat: Thanks! Code is fixed now.Ampulla
thank you! your point 40.756, -73.986 located in New York, but example show point in Canada.Predispose
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?Sepulchral
@Sepulchral 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.Ampulla
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 guidesButtons
C
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 +
Camfort answered 19/6, 2009 at 21:54 Comment(1)
Thanks, how to reverse this ? So from X and Y to lat/long with specified bounding box coordinates ?Glorianna
P
0

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

Photophore answered 19/6, 2009 at 21:36 Comment(1)
You are correct, but in this case I would gladly use an appropriate image to match a working solution for a specific projection.Maddis

© 2022 - 2024 — McMap. All rights reserved.