Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Latitude and Longitude Bounds from Google Maps x y and zoom parameters

I have seen some questions with similar titles, but they seem to be referring to x and y pixel coordinates.

I am asking about the actual tile numbers of x and y from Google Maps getTile() function:

To clarify the question...

Given the x, y, and zoom parameters in the getTile() function, how can I find the latitude and longitude bounds of the tile?

CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {

    var x = coord.x,
    y = coord.y,
    url = "http://mt1.google.com/vt/lyrs=y&x="+x+"&y="+y+"&z="+zoom;
    //other stuff   
}

The only reason at the moment that I need this is that I want to determine the maximum zoom level at this tile projection. From this link: Maximum Zoom, it states that in order to find the maximum zoom, I will need a latitude and longitude value using getMaxZoomAtLatLng(). So if I can get the bounds, then I can use any latitude and longitude points within the bounds to find my max Zoom.

Alternatives I have thought of were creating an image and checking if the src url had an error (this seems like a terrible idea to me, as I would be making many bad requests just to check if imagery existed).

var img = new Image;
img.onload = function() {/*imagery exists*/ }
img.onerror = function() {/*past maximum zoom*/ }
img.src = url;

EDIT:

After further investigation, I realize that the getMaxZoomAtLatLng() function is using an ajax call which will not fit into my plans. But I still am interested in how to find the latitude and longitude boundaries of a given tile ( that could be useful for other applications ).

like image 499
Douglas.Sesar Avatar asked May 04 '14 15:05

Douglas.Sesar


1 Answers

Assuming a basic google-map using mercator-projection and a tileSize of 256x256:

The number of tiles on each(x-axis and y-axis) is Math.pow(2,zoom), so on zoom 0 the map is using 1 tile, on zoom 1 4 tiles, on zoom 2 16 tiles and so on.

First calculate the southWest/northeast-points of the tile.

the size of a tile (in points) is 256/Math.pow(2,zoom)

southWest-point:

x = tile.x * tileSizeInPoints
y = (tile.y * tileSizeInPoints) + tileSizeInPoints

northEast-point:

x = (tile.x * tileSizeInPoints) + tileSizeInPoints
y = tile.y * tileSizeInPoints

These points must be translated to LatLngs. When you use a map you may use the method fromLatLngToPoint of the maps projection.

For a custom implementation take a look at https://developers.google.com/maps/documentation/javascript/examples/map-coordinates.

A possible API-independant implementation:

MERCATOR={

  fromLatLngToPoint:function(latLng){
     var siny =  Math.min(Math.max(Math.sin(latLng.lat* (Math.PI / 180)), 
                                   -.9999),
                          .9999);
     return {
      x: 128 + latLng.lng * (256/360),
      y: 128 + 0.5 * Math.log((1 + siny) / (1 - siny)) * -(256 / (2 * Math.PI))
     };
  },

  fromPointToLatLng: function(point){

     return {
      lat: (2 * Math.atan(Math.exp((point.y - 128) / -(256 / (2 * Math.PI)))) -
             Math.PI / 2)/ (Math.PI / 180),
      lng:  (point.x - 128) / (256 / 360)
     };

  },

  getTileAtLatLng:function(latLng,zoom){
    var t=Math.pow(2,zoom),
        s=256/t,
        p=this.fromLatLngToPoint(latLng);
        return {x:Math.floor(p.x/s),y:Math.floor(p.y/s),z:zoom};
  },

  getTileBounds:function(tile){
    tile=this.normalizeTile(tile);
    var t=Math.pow(2,tile.z),
        s=256/t,
        sw={x:tile.x*s,
            y:(tile.y*s)+s},
        ne={x:tile.x*s+s,
            y:(tile.y*s)};
        return{sw:this.fromPointToLatLng(sw),
               ne:this.fromPointToLatLng(ne)
              }
  },
  normalizeTile:function(tile){
    var t=Math.pow(2,tile.z);
    tile.x=((tile.x%t)+t)%t;
    tile.y=((tile.y%t)+t)%t;
    return tile;
  }

}

call MERCATOR.getTileBounds() by supplying a single object as argument with the following format:

{
 x:tileIndexX,
 y:tileIndexY,
 z:zoom 
}

Demo: http://jsfiddle.net/doktormolle/55Nke/

like image 183
Dr.Molle Avatar answered Oct 04 '22 11:10

Dr.Molle