如何从Google地图的x、y和缩放参数中获取纬度和经度范围界限

7
我看到一些类似的问题标题,但它们似乎是指xy像素坐标。
我询问有关Google Maps getTile()函数中xy的实际瓦片编号:
为了澄清问题...
在getTile()函数中给定x、y和缩放参数,如何找到瓦片的纬度和经度边界?
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   
}

目前我需要这个的唯一原因是想要确定此瓦片投影的最大缩放级别。从这个链接中:最大缩放级别,它指出为了找到最大缩放级别,我需要使用getMaxZoomAtLatLng()获取纬度和经度值。所以如果我可以得到边界,那么我可以使用边界内的任何纬度和经度点来查找我的最大缩放级别。

我想到的替代方案是创建一个图像并检查src url是否有错误(对我来说这似乎是一个可怕的想法,因为我将会发出许多错误请求来检查图像是否存在)。

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

编辑:

经过进一步调查,我发现getMaxZoomAtLatLng()函数使用的是一个ajax调用,这将不适合我的计划。但我仍然对如何找到给定瓦片的纬度和经度边界感兴趣(这可能对其他应用程序有用)。


1
为什么要踩我?我在措辞和准备这个问题方面花费了很大的心思。 - Douglas.Sesar
3个回答

18

假设使用墨卡托投影和 256x256 的 tileSize,生成一个基本的谷歌地图:

每个轴(x 和 y)上的瓦片数量为 Math.pow(2,zoom),所以在缩放级别 0 上,地图使用 1 个瓦片,在缩放级别 1 上,使用 4 个瓦片,在缩放级别 2 上使用 16 个瓦片,以此类推。

首先计算瓦片的 southwest/northeast 点。

瓦片的大小(以点为单位)为 256/Math.pow(2,zoom)

southwest-point:

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

北东角点:

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

这些点必须转换为LatLngs。当您使用地图时,可以使用地图投影的方法fromLatLngToPoint

对于自定义实现,请查看https://developers.google.com/maps/documentation/javascript/examples/map-coordinates

一个可能的独立于API的实现:

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;
  }

}

通过提供以下格式的单个对象作为参数来调用 MERCATOR.getTileBounds()

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

示例:http://jsfiddle.net/doktormolle/55Nke/


1
谢谢,我很感激所有这些信息都在一个地方。 - Douglas.Sesar
leaflet瓦片怎么样? - knutole
很棒的答案,但是当我使用瓦片大小=64时,似乎不起作用。当然,我在getTileBoundsfromPointToLatLng函数中替换了256=64,128=32。我的意思是,你能不能写一个带有tileSize作为参数的函数? - undefined

1

不确定这是否完全有助于边界,但为了找到瓦片坐标的简单显示,我在这里查看:

https://developers.google.com/maps/documentation/javascript/examples/map-coordinates

并且在代码行上使用 TypeScript:

  const chicago = new google.maps.LatLng(-33.76781028848151, 150.73644505329204
);

将经纬度更改为您想要的位置...他们有一个漂亮的用户界面,可以在缩放时计算所有更改。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接