[英]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
表示水平, X
和Y
表示平鋪方案中的位置。
我剛剛發現我首先導致了問題。 我強迫 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.