获取地图图块边界框

Get map tiles bounding box

是否可以获取图块 LngLat 边界框? (如果可能的话 center/width)

即给定任何图块“id”(例如 6/33/24),计算所需坐标。我非常渴望得到一个答案,我什至不在乎它是用什么语言写的。


上下文

磁贴“id”有 3 个部分:6/33/24 (z/x/y).

z 从 left/top 原点开始缩放 (0-24) 和 x/y 瓷砖编号。

当缩放为1时,整个地图被分成4个相等的图块(如图所示)。每次缩放 (z) 增加时,每个图块都会细分为 4 个相等的图块(例如缩放 2 = 16 个图块)。

 _______________________
|          |           |
|  1/0/0   |   1/1/0   |
|          |           |
|__________|___________|
|          |           |
|  1/0/1   |   1/1/1   |
|          |           |
|__________|___________|

为什么?

我想实现客户端标记缓存并将它们绑定到图块似乎是最合理的解决方案。我知道如何获取图块(遍历 sourceCaches 个图块或使用少数 transform 方法)但我不知道如何从图块矩阵或图块 ID 获取 LngLat 数据。

标记缓存的超级基本JavaScript概念(针对上下文):

const markerCache = {
  cache: {},

  getMarkersForTile: function(key) { // tiles have unique keys
    if (this.cache[key]) {
      return Promise.resolve(this.cache[key]);
    }

    // ??? what should be in "getTileBounds"?
    const bounds = getTileBounds(key);
    
    return fetchMarkersForTile(bounds).then(markers => {
      this.cache[key] = markers;
      return markers;
    });
  }
};

我相信您正在寻找 Slippy Map Tilenames specs as mentioned in https://docs.mapbox.com/api/maps/vector-tiles/

link

中有许多编程语言实现

Java 例子

  class BoundingBox {
    double north;
    double south;
    double east;
    double west;   
  }

  BoundingBox tile2boundingBox(final int x, final int y, final int zoom) {
    BoundingBox bb = new BoundingBox();
    bb.north = tile2lat(y, zoom);
    bb.south = tile2lat(y + 1, zoom);
    bb.west = tile2lon(x, zoom);
    bb.east = tile2lon(x + 1, zoom);
    return bb;
  }

  static double tile2lon(int x, int z) {
     return x / Math.pow(2.0, z) * 360.0 - 180;
  }

  static double tile2lat(int y, int z) {
    double n = Math.PI - (2.0 * Math.PI * y) / Math.pow(2.0, z);
    return Math.toDegrees(Math.atan(Math.sinh(n)));
  }

我相信您正在寻找这个图书馆:

https://github.com/mapbox/tilebelt

它包含 tileToBBOX(tile) 函数,它将 return 给定图块的边界框。

用法:

var tilebelt = require('@mapbox/tilebelt');

var tile = [10,15,8] // x,y,z

var bbox = tilebelt.tileToBBOX(tile);