views:

2459

answers:

5

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)
A: 

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

hanno
You are correct, but in this case I would gladly use an appropriate image to match a working solution for a specific projection.
michael
+3  A: 

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
+6  A: 

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 + longitude_shift) % map_width;

    // 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

    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>
Paul A Jungwirth
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 xThanks!
michael
i thinkx = (map_width * (180 + lng) / 360 + longitude_shift) % map_width;should bex = ((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
matpalm
+2  A: 

There's a good Javascript library, PROJ4JS, that allows you to do transformations between different projections.

andri
A: 

how can i draw the points if i am using US mercetor map. Actually i want points some cities in US map. can you help me

Dinesh
Probably best to create your own Question since this one is old and doesn't directly cover this. Might mean better response and visibility.
michael