簡體   English   中英

確定 Cesium Map Tiles 的緯度/經度邊界

[英]Determining Lat/Long bounds for Cesium Map Tiles

我正在嘗試根據我們存儲在數據庫中的數據生成地圖圖塊,並使用 UrlTemplateImageryProvider 將它們提供給 Cesium。 對於每個地圖圖塊,我需要知道緯度/經度邊界才能找到匹配的數據。 我使用與 Google Maps 相同的圖塊方案,請求類似於http://host/tiles/zoom/x/y 最初我一直在使用方程將這些地圖瓦片坐標轉換為經緯度范圍: http : //wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_bounding_box但現在我想知道這是否不是正確的投影正在使用。

首先,我看到的所有 Web Mercator 文檔都說 Tile 0,0 @ zoom lvl 0 應該覆蓋整個世界。 這不是我在 Cesium 中看到的(縮放級別為 0 時有 2 個圖塊)。 也就是說,我的計算似乎適用於縮放級別 0、1、2 和 3,但是當我轉到縮放級別 4 時,緯度計算開始向南移動。 如果我在 2D 谷歌地圖上繪制生成的經緯度點,它們看起來是正確的,但我可以清楚地看到 cesium 請求的圖塊具有不同的邊界。 所以我現在假設我只是使用錯誤的投影來計算瓷磚邊界。

我也試過這里的計算: http : //www.maptiler.org/google-maps-coordinates-tile-bounds-projection/從像素轉換到米,到緯度/經度,但它們似乎是相同的結果作為 web 墨卡托計算。

那么任何人都可以幫我弄清楚如何計算銫請求的瓷磚的緯度/經度邊界框?

以下是我基於 Slippy Map Tiles 的方法:

public static Box getLatLonBoundsForTile(int zoom, int x, int y) {
    double longitudeMin = tile2lon(x, zoom);
    double longitudeMax = tile2lon(x + 1, zoom);
    double latitudeMin = tile2lat(y + 1, zoom);
    double latitudeMax = tile2lat(y, zoom);

    Point swPoint = new Point(longitudeMin, latitudeMin);
    Point nePoint = new Point(longitudeMax, latitudeMax);

    return new Box(swPoint, nePoint);
}

public static double getColsForZoomLevel(int zoom) {
    if (zoom == 0) return 2;
    int noTiles = 8 * (int) (Math.pow(4, zoom - 1));
    return noTiles / getRowsForZoomLevel(zoom);
}
public static double getRowsForZoomLevel(int zoom) {
    if (zoom == 0) return 1;
    return Math.pow(2, zoom);
}
public static double tile2lon(int x, int zoom) {
    return x / getColsForZoomLevel(zoom) * 360.0 - 180;
}

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

Cesium包含一個類WebMercatorTilingScheme ( source ),用於計算瓦片的緯度/經度值(以弧度為單位),在根級別具有可配置的瓦片數量。

對於 3D 渲染,切片通常是方形的,邊緣長度為 2 的冪,例如 256 x 256 像素圖像,在所有級別。 地球儀本身通常用矩形紋理(360 度寬,180 度高)包裹。 為了解決這個問題,平鋪方案的第 0 層通常是兩個平鋪寬但只有一個平鋪高 (2 x 1)。 下一層是 4 x 2 瓷磚,然后是 8 x 4、16 x 8 等。

要實時查看此操作,請加載Cesium Inspector ,在頁面右側查找一些選項,單擊Terrain旁邊的小+ ,然后在Show tile coordinates tileordinate 上打勾。 坐標用L表示水平, XY表示平鋪方案中的位置。

我剛剛發現我首先導致了問題。 我強迫 Cesium 在 UrlTemplateImageryProvider 中使用 GeographicTilingScheme。 我之前的配置是這樣的:

var layer = new Cesium.UrlTemplateImageryProvider({
    url : '/map/tile/{z}/{x}/{y}?debug=true',
    credit : '© Me',
    tilingScheme : new Cesium.GeographicTilingScheme(),
    maximumLevel : 11
});

我從文檔中的示例中復制的。 所以,現在我從配置中刪除了 tilingScheme,它默認為 WebMercatorTilingScheme。 這是新配置:

var layer = new Cesium.UrlTemplateImageryProvider({
    url : '/map/tile/{z}/{x}/{y}?debug=true',
    credit : '© Me',
    maximumLevel : 11
});

完成此操作后,我必須刪除我對 2 個圖塊@縮放級別 0 的假設並將其更改回 1,現在使用上述方法一切正常! 我只是像這樣改變了這個方法:

public static double getColsForZoomLevel(int zoom) {
    return getRowsForZoomLevel(zoom);
}

所以這一切都歸結為先檢查簡單事物的古老教訓。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM