1,墨卡托投影
使用經緯度表示位置的大地坐標系雖然可以描述地球上點的位置,但是對於地圖地理數據在二維平面內展示的場景,需要通過投影的方式將三維空間中的點映射到二維空間中。地圖投影需要建立地球表面點與投影平面點的一一對應關系,在互聯網地圖中常使用墨卡托投影。墨卡托投影是荷蘭地理學家墨卡托於1569年提出的一種地球投影方法,該方法是圓柱投影的一種。
墨卡托投影如下:
2,瓦片切割和瓦片坐標
對於經過墨卡托投影為平面的世界地圖,在不同的地圖分辨率(整個世界地圖的像素大小)下,通過切割的方式將世界地圖划分為地圖單元,划分成的每一塊地圖單元稱為地圖瓦片。
地圖瓦片具有以下特點:
--具有唯一的瓦片等級(Level)和瓦片坐標編號(X, Y)。
--瓦片分辨率為256*256。
--最小的地圖等級是0,此時世界地圖只由一張瓦片組成。
--瓦片等級越高,組成世界地圖的瓦片數越多,可以展示的地圖越詳細。
--某一瓦片等級地圖的瓦片是由低一級的各瓦片切割成的4個瓦片組成,形成了瓦片金字塔。
3,高德地圖瓦片坐標與坐標系定義
高德地圖瓦片坐標與Google Map、Open Street Map相同。高德地圖的墨卡托投影截取了緯度(約85.05ºS, 約85.05ºN)之間部分的地球,使得投影后的平面地圖水平方向和垂直方向長度相等。將墨卡托投影地圖的左上角作為瓦片坐標系起點,往左方向為X軸,X軸與北緯85.05º重合且方向向左;往下方向為Y軸,Y軸與東經180º(亦為西經180º)重合且方向向下。瓦片坐標最小等級為0級,此時平面地圖是一個像素為256*256的瓦片。在某一瓦片層級Level下,瓦片坐標的X軸和Y軸各有2^Level個瓦片編號,瓦片地圖上的瓦片總數為2^Level*2^Level。
高德地圖Level=2的瓦片坐標編號情況:
4,通過經緯度計算瓦片坐標
公式:(參考:Slippy map tilenames)
經緯度坐標(lon, lat)轉瓦片坐標(x, y),z為瓦片層級:
java代碼實現:
/** 功能描述: <br> * 〈高德地圖,Google Map、Open Street Map 經緯度 轉 瓦片坐標〉 * @Param: [lon(經度), lat(維度), level(瓦片層級)] * @return: int[] * @author: zl * @date: 2021/12/23 14:18 */ public static int[] getTileNumber(double lon, double lat, int level) { int xtile = (int)Math.floor( (lon + 180) / 360 * (1<<level) ) ; double ln = Math.log( Math.tan(lat*Math.PI/180) + (1 / Math.cos(lat*Math.PI/180)) ); int pow = (1<<(level-1)); int ytile = (int)Math.floor( (1 - ln/Math.PI) *pow ); if (xtile < 0) { xtile=0; } if (xtile >= (1<<level)) { xtile=((1<<level)-1); } if (ytile < 0) { ytile=0; } if (ytile >= (1<<level)) { ytile=((1<<level)-1); } return new int[]{xtile,ytile}; }
5,百度地圖瓦片坐標與坐標系定義
百度地圖的瓦片坐標系定義與高德地圖並不相同,其墨卡托投影的參數也不同。百度地圖瓦片坐標以墨卡托投影地圖中赤道與0º經線相交位置為原點,沿着赤道往左方向為X軸,沿着0º經線向上方向為Y軸。
百度瓦片坐標定義了另一種二維坐標系,稱為百度平面坐標系。百度平面坐標系的坐標原點與百度瓦片坐標原點相同,以瓦片等級18級為基准,規定18級時百度平面坐標的一個單位等於屏幕上的一個像素。平面坐標與地圖所展示的級別沒有關系,也就是說在1級和18級下,同一個經緯度坐標的百度平面坐標都是一致的。
百度地圖Level=2的瓦片坐標編號情況:
此時X方向和Y方向各有4個瓦片編號,但是外圍的某些瓦片只有部分區域有地圖或完全沒有地圖。沒有地圖的區域也可以認為其瓦片是無效的,即百度地圖中X方向或Y方向的有效瓦片不一定達到2^{Level}個。
中國大概位於百度瓦片坐標的(0,0)中。
百度經緯度坐標與百度平面坐標的相互轉換,並沒有公開的公式,需要通過百度地圖的API實現。
參考鏈接(這里)
6,其他投影模型和坐標系定義(天地圖)
天地圖的切片規則是這樣的,l=1時,整幅地圖(全球地圖)被切為兩片,如圖(l=1):
當l=2即以后,每個瓦片將被切位4片,如圖(l=2):
天地圖經緯度計算瓦片坐標java實現:
/** 功能描述: <br> * 〈天地圖 經緯度 轉 瓦片坐標〉 * @Param: [rectPts(左上角經緯度rectPts[0],rectPts[1] 和 左下角經緯度rectPts[2],rectPts[3])也就是兩個點, level(瓦片層級)] * @return: double[] * @author: zl * @date: 2021/12/23 14:18 */ public static double[] getTileNumber2(double[] rectPts, int level) { //瓦片的級別分辨率(1-18) double[] resolution = {5.36441802978515E-06, 1.07288360595703E-05, 2.1457672119140625E-05, 4.29153442382814E-05, 8.58306884765629E-05, 0.000171661376953125, 0.00034332275390625, 0.0006866455078125, 0.001373291015625, 0.00274658203125, 0.0054931640625, 0.010986328125, 0.02197265625, 0.0439453125, 0.087890625, 0.17578125, 0.3515625, 0.703125}; double startX = Math.floor((rectPts[0] + 180.0) / (resolution[18 - level] * 256)); double startY = Math.floor((90.0 - rectPts[1]) / (resolution[18 - level] * 256)); double endX = Math.ceil((rectPts[2] + 180.0) / (resolution[18 - level] * 256)); double endY = Math.ceil((90.0 - rectPts[3]) / (resolution[18 - level] * 256)); //左上角瓦片坐標和左下角瓦片坐標 double[] result = new double[]{startX, startY, endX, endY}; return result; }
7:,注意
- 雖然最小的瓦片等級是0,但是部分地圖並不提供0級或其他較小瓦片等級的地圖,因為此時的世界地圖將會很小,不能鋪滿用戶設備窗口。
-
墨卡托投影並不是一種坐標系,而是為了在二維平面上展示三維地球而進行的一種空間映射。所以在GIS地圖和互聯網地圖中,雖然用戶看到的地圖經過了墨卡托投影,但依然使用經緯度坐標來表示地球上點的位置。在地圖繪制和地圖可視化時,就需要將地圖數據使用投影的方式來呈現。
8,參考鏈接