轉載:http://blog.csdn.net/wudiazu/article/details/76597294 javascript
本文將介紹瓦片座標相關知識,並提供高德地圖、百度地圖、谷歌地圖的經緯度座標與瓦片座標的相互轉換方法和類庫。 html
互聯網地圖服務商的在線地圖都經過瓦片的方式提供,稱爲瓦片地圖服務。最多見的地圖瓦片是圖片格式的,如今有的地圖服務商也提供了矢量的瓦片數據,而後在用戶端使用Canvas渲染成圖片,如node-canvas實現百度地圖個性化底圖繪製。
在進行地圖開發時,爲獲取特定經緯度所在區域的瓦片和獲取瓦片上像素點對應的經緯度,常常須要進行經緯度座標與瓦片座標、像素座標的相互轉換。本文將介紹瓦片座標相關知識,並提供高德地圖、百度地圖、谷歌地圖的經緯度座標與瓦片座標的相互轉換方法和轉換類庫--tile-lnglat-transform。 node
國際標準的經緯度座標是WGS84,Open Street Map、外國版的Google Map都是採用WGS84;高德地圖使用的座標系是GCJ-02;百度地圖使用的座標系是BD-09。高德地圖和百度地圖都提供了在線的單向座標轉換接口,將其餘座標系換化到本身的座標系,但這種轉換受限於http url請求字段長度和網絡請求延遲,批量處理並不實用。離線相互轉換能夠經過開源JavaScript庫coordtransform實現,偏差在10米左右。
雖然各地圖服務商經緯度座標系不一樣,但某一互聯網地圖的經緯度座標與瓦片座標相互轉換隻與該地圖商的墨卡託投影和瓦片編號的定義有關,跟地圖商採用的大地座標系標準無關。 github
使用經緯度表示位置的大地座標系雖然能夠描述地球上點的位置,可是對於地圖地理數據在二維平面內展現的場景,須要經過投影的方式將三維空間中的點映射到二維空間中。地圖投影須要創建地球表面點與投影平面點的一一對應關係,在互聯網地圖中常使用墨卡託投影。墨卡託投影是荷蘭地理學家墨卡託於1569年提出的一種地球投影方法,該方法是圓柱投影的一種。投影的更多內容,能夠查看地圖投影的N種姿式。 api
墨卡託投影示意圖.jpg 網絡
據我瞭解,各大地圖服務商都採用了Web Mercator進行投影,瓦片座標系的不一樣主要是投影截取的地球範圍不一樣、瓦片座標起點不一樣。 app
墨卡託投影並非一種座標系,而是爲了在二維平面上展現三維地球而進行的一種空間映射。因此在GIS地圖和互聯網地圖中,雖然用戶看到的地圖通過了墨卡託投影,但依然使用經緯度座標來表示地球上點的位置。
在地圖繪製和地圖可視化時,就須要將地圖數據使用投影的方式來呈現。
對於通過墨卡託投影爲平面的世界地圖,在不一樣的地圖分辨率(整個世界地圖的像素大小)下,經過切割的方式將世界地圖劃分爲像素爲$256\times256$的地圖單元,劃分紅的每一塊地圖單元稱爲地圖瓦片。
地圖瓦片具備如下特色:
具備惟一的瓦片等級(Level)和瓦片座標編號(tileX, tileY)。
瓦片分辨率爲256*256。
最小的地圖等級是0,此時世界地圖只由一張瓦片組成。
瓦片等級越高,組成世界地圖的瓦片數越多,能夠展現的地圖越詳細。
某一瓦片等級地圖的瓦片是由低一級的各瓦片切割成的4個瓦片組成,造成了瓦片金字塔。
瓦片切割(瓦片金字塔).jpg
高德地圖瓦片座標與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的瓦片座標編號狀況.jpg
如上圖所示,此時X方向和Y方向各有4個瓦片編號,總瓦片數爲16。中國大概位於高德瓦片座標的(3,1)中。
高德地圖座標轉換圖解.png
從高德地圖座標轉換圖解中能夠看出,高德地圖的座標轉換具備如下特色:
全部座標轉換都在某一瓦片等級下進行,不一樣瓦片等級下的轉換結果不一樣。
經緯度座標能夠直接轉換爲瓦片座標和瓦片像素座標。
瓦片像素座標須要結合其瓦片座標才能獲得該像素座標的經緯度座標。
方法參考:Slippy map tilenames
經緯度座標(lng, lat)轉瓦片座標(tileX, tileY):
經緯度座標(lng, lat)轉像素座標(pixelX, pixelY)
瓦片(tileX, tileY)的像素座標(pixelX, pixelY)轉經緯度座標(lng, lat)
百度地圖的瓦片座標系定義與高德地圖並不相同,其墨卡託投影的參數也不一樣。百度地圖瓦片座標以墨卡託投影地圖中赤道與0º經線相交位置爲原點,沿着赤道往左方向爲X軸,沿着0º經線向上方向爲Y軸。
百度瓦片座標定義了另外一種二維座標系,稱爲百度平面座標系。百度平面座標系的座標原點與百度瓦片座標原點相同,以瓦片等級18級爲基準,規定18級時百度平面座標的一個單位等於屏幕上的一個像素。平面座標與地圖所展現的級別沒有關係,也就是說在1級和18級下,同一個經緯度座標的百度平面座標都是一致的。
百度地圖Level=2的瓦片座標編號狀況.jpg
此時X方向和Y方向各有4個瓦片編號,可是外圍的某些瓦片只有部分區域有地圖或徹底沒有地圖。沒有地圖的區域也能夠認爲其瓦片是無效的,即百度地圖中X方向或Y方向的有效瓦片不必定達到2^{Level}個。
中國大概位於百度瓦片座標的(0,0)中。
百度地圖座標轉換圖解.png
從百度地圖座標轉換圖解中能夠看出,百度地圖的座標轉換具備如下特色:
百度經緯度座標與百度平面座標能夠直接相互轉換,而且與瓦片地圖等級無關。
經緯度座標須要先轉換爲平面座標,而後才能在某一瓦片等級下轉換爲瓦片座標和瓦片像素座標。
瓦片像素座標須要結合其瓦片座標才能獲得該像素座標的平面座標,而後再轉換爲經緯度座標。
方法參考:百度地圖API詳解之地圖座標系統
發現百度javascript API的一個bug:百度JavaScript API中經緯度座標轉瓦片座標bug
經緯度座標(lng, lat)轉平面座標(pointX, pointY)
百度經緯度座標與百度平面座標的相互轉換,並無公開的公式,須要經過百度地圖的API實現。
主要代碼爲:
// Bmap爲百度JavaScript API V2.0的地圖對象
lnglatToPoint(longitude, latitude) {
let projection = new BMap.MercatorProjection();
let lnglat = new BMap.Point(longitude, latitude);
let point = projection.lngLatToPoint(lnglat);
return {
pointX: point.x,
pointY: point.y
};
}
平面座標(pointX, pointY)轉經緯度座標(lng, lat)
也須要經過百度地圖的API實現。
主要代碼爲:
pointToLnglat(pointX, pointY) {
let projection = new BMap.MercatorProjection();
let point = new BMap.Pixel(pointX, pointY);
let lnglat = projection.pointToLngLat(point);
return {
lng: lnglat.lng,
lat: lnglat.lat
};
}
平面座標(pointX, pointY)轉瓦片座標(tileX, tileY)
平面座標(pointX, pointY)轉像素座標(pixelX, pixelY)
瓦片(tileX, tileY)的像素座標(pixelX, pixelY)轉平面座標(pointX, pointY)
經緯度座標與瓦片座標、像素座標的相互轉換,以平面座標爲中間量進行轉換。
百度地圖JavaScript的代碼很是奇葩,很是迷惑:
經緯度類是Point,平面座標類是Pixel。
經緯度轉平面座標是lngLatToPoint,接收一個Point對象,返回一個Pixel對象。
平面座標轉經緯度座標是在pointToLngLat,接收Pixel對象,返回一個Point對象。
WTF!
本文筆者根據前文介紹的經緯度座標與瓦片座標、像素座標相互轉換規則,編寫了一個javascript類庫--tile-lnglat-transform,提供了高德地圖、百度地圖、谷歌地圖的經緯度座標與瓦片座標的相互轉換。該模塊是使用了UMD模塊打包方式,能夠在node和broswer中使用。
類庫地址:https://github.com/CntChen/tile-lnglat-transform
該類庫的詳細信息及使用方法請在項目主頁中查看。
瓦片地圖等級範圍反映了地圖可縮放的程度。
雖然最小的瓦片等級是0,可是部分地圖並不提供0級或其餘較小瓦片等級的地圖,由於此時的世界地圖將會很小,不能鋪滿用戶設備窗口。
百度圖片瓦片的層級是[3~18]
http://online1.map.bdimg.com/onlinelabel/?qt=tile&x=49310&y=10242&z=18
百度主頁的層級是[3~19]
高德圖片瓦片的層級是[1~19]
http://wprd03.is.autonavi.com/appmaptile?style=7&x=427289&y=227618&z=19
高德地圖官網介紹的高德地圖層級:
獲取當前地圖縮放級別,在PC上,默認取值範圍爲[3,18];在移動設備上,默認取值範圍爲[3-19]
谷歌地圖瓦片層級是[0~21]
http://mt2.google.cn/vt/lyrs=m@167000000&hl=zh-CN&gl=cn&x=1709157&y=910472&z=21&s=Galil
瓦片像素座標的起始點
高德地圖、谷歌地圖的瓦片座標起點在左上角,像素座標(pixelX, pixelY)在瓦片中的起點爲左上角。
百度地圖中,像素座標(pixelX, pixelY)的起點爲左下角。
天地圖的切片規則是這樣的,l=1時,整幅地圖(全球地圖)被切爲兩片,如圖(l=1):
當l=2即之後,每一個瓦片將被切位4片,如圖(l=2):
瓦片地圖服務
https://en.wikipedia.org/wiki/Tile_Map_Service
node-canvas實現百度地圖個性化底圖繪製
http://www.cnblogs.com/well1010/articles/baidu-map-node-canvas.html
tile-lnglat-transform
https://github.com/CntChen/tile-lnglat-transform
coordtransform
https://github.com/wandergis/coordtransform
地圖投影的N種姿式
http://blog.sina.com.cn/s/blog_517eed9f0102w4rm.html
Web Mercator
https://en.wikipedia.org/wiki/Web_Mercator
Slippy map tilenames
http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
百度地圖API詳解之地圖座標系統
http://www.cnblogs.com/jz1108/archive/2011/07/02/2095376.html
百度JavaScript API中經緯度座標轉瓦片座標bug
http://cntchen.github.io/2016/05/09/百度JavaScirpt%20%20API中經緯度座標轉瓦片座標bug/
高德地圖層級