latlng to point in gmaps v3

2010-11-21

While google maps v2 had a simple fromLatLngToContainerPixel(latlng, z) on every projection (and the other way around as well), v3 seems to be lacking a bit in its api. While this certainly isn't the only thing the api lacks, it's at least something that was solved quite quickly with the help of the google maps group.

So in v2 you could do map.getProjection().fromLatLngToContainerPixel(latlng, 4) and you'd get the proper point according to given zoom index. v3 almost has that method, but only on the MapCanvasProjection object and only without a zoom parameter. Suck.

So here is your fromLatLngToPixel and fromPixelToLatLng, in gmaps v3 style. I found it in this post (last reply, I don't know how to link to that directly... UI fail?).

Code: (gmaps)
/**
* @param {google.maps.Map} map
* @param {google.maps.LatLng} latlng
* @param {int} z
* @return {google.maps.Point}
*/
var latlngToPoint = function(map, latlng, z){
var normalizedPoint = map.getProjection().fromLatLngToPoint(latlng); // returns x,y normalized to 0~255
var scale = Math.pow(2, z);
var pixelCoordinate = new google.maps.Point(normalizedPoint.x * scale, normalizedPoint.y * scale);
return pixelCoordinate;
};
/**
* @param {google.maps.Map} map
* @param {google.maps.Point} point
* @param {int} z
* @return {google.maps.LatLng}
*/
var pointToLatlng = function(map, point, z){
var scale = Math.pow(2, z);
var normalizedPoint = new google.maps.Point(point.x / scale, point.y / scale);
var latlng = map.getProjection().fromPointToLatLng(normalizedPoint);
return latlng;
};

It works quite simple actually. But it would probably help if the docs would have explained this one slightly better.

Some interesting facts to help explaining this function:

So "my" latlngToPoint function uses these facts. First it asks where the latlng would be on zoom level 0 (this is one tile of 256x256 pixels). You can't get to zoom level 0 by normal means (but you can somewhat clearly see that level 1 consists of four tiles). We get a very high precision floating number back, between 0 and 255.

Next we take the zoom level. Each level increases the size by two fold so to get the size of the "world" at zoom level z, we need to double it z times. That's what Math.pow(2,z) does. The last step is actually multiplying the normalized coordinate with the zoom factor and voila, there's the point in our world at zoom level z.

Of course, pointToLatlng is simply the inverse of that.

Please note that there is another method (again, last reply) of doing this. Sort of. It involves creating a new MapCanvasProjection and using fromLatLngToContainerPixel from that. Like..

Code: (gmaps)
overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
var point = overlay.getProjection().fromLatLngToContainerPixel(latLng);

I can only say uuuuugeleeeeey. Thanks. Please use the two functions I described first :)

Hope it helps you :)