在百度地圖中,地址「哈爾濱市道里區通達街138號」的經緯度解析爲(126.616759, 45.74989),而在高德地圖中,相同地址的經緯度則解析爲(126.609207, 45.740142)。緣由是百度和高德採用的地理座標系統不一樣。javascript
本文介紹國內經常使用網絡地圖API座標系統特色,並提供不一樣座標間的批量轉換解決方案。css
地理數據的座標系通常有兩大類,一是地理座標系(GCS)、是經緯度單位的橢球座標系;二是投影座標系(PCS)、是平面直角座標系。html
投影座標系(PCS)的定義通常會包含兩方面的定義信息:java
基準面/Datum — 與GCS相應 投影方法/Projection Method
WGS-84座標體系又稱世界大地座標系或地球座標。git
國際通用標準,規定GPS 設備中取出的原始數據應該是地球座標。github
「 世界大地座標系是美國國防部製圖局(Defence Mapping Agency, DMA)爲統一世界大地座標系統,實現全球測量標準的一致性,定義用於製圖、大地、導航的座標基準。它包括標準地球座標框架、用於處理原始觀測數據的標準橢球參考面(即基準和參考橢球)和定義標準海平面的重力等勢面(大地水準面)。算法
定義一個座標系絕對是一個複雜浩大的數學工程。 咱們常常據說的 WGS 1984 (或 WGS 84)就是其中一個世界大地座標系統。咱們常用的 GPS 的座標參考系統也是它。通常用國際標準的GPS記錄儀記錄下來的座標,都是GPS的座標。很惋惜,在中國,任何一個地圖產品都不容許使用GPS座標,聽說是爲了保密。api
WGS 1984 是一個長半軸(a)爲6378137,短半軸(b)爲6356752.314245179 的橢球體,扁率(f)爲298.257223563,\(f=\frac{a-b}{a}\)。數組
GCJ-02國測局2002年發佈的座標體系,又稱「火星座標」。適用於國內,國內地圖供應商基本使用該座標系對位置進行加密。在中國,不少時候必須使用GCJ-02的座標體系。好比谷歌,騰訊,高德都在用這個座標體系。GCJ-02也是國內最普遍使用的座標體系。安全
火星座標系統的原理是這樣的:國測局開發了一個系統,能將實際的座標轉換成虛擬的座標。全部在中國銷售的數字地圖必須使用這個系統進行座標轉換以後方可上市。這是生產環節,這種電子地圖被稱爲火星地圖。在使用環節,GPS終端設備必須集成國測局提供的加密算法,把從GPS衛星那裏獲得的座標轉換成虛擬座標,而後再去火星地圖上查找,這樣就在火星座標系上完成了地圖的匹配。推出這個系統的名義是爲了國家安全。而後呢,能夠收取必定的費用。
通常都是由GCJ-02進過偏移算法獲得的。這種體系就根據每一個公司的不一樣,座標體系都不同了。好比,百度和搜狗就使用本身的座標體系,與其餘座標體系不兼容。
互聯網在線地圖使用的座標系
火星座標系:
iOS 地圖(實際上是高德) Gogole地圖 騰訊搜搜地圖 阿里雲地圖 高德地圖 搜狐搜狗地圖
百度座標系:
固然只有百度地圖
WGS84座標系(GPS原始座標系):
國際標準,谷歌國外地圖、osm地圖等國外的地圖
地理座標系(Geographic Coordinate System),是使用三維球面來定義地球表面位置,以實現經過經緯度對地球表面點位引用的座標系。一個地理座標系包括角度測量單位、本初子午線和參考橢球體三部分。
地理座標系爲球面座標。 參考平面地是橢球面,座標單位爲經緯度;投影座標系爲平面座標。參考平面地是水平面,座標單位爲米、公里等;地理座標轉換到投影座標的過程可理解爲投影。(投影:將不規則的地球曲面轉換爲平面)。
地理座標系能夠肯定地球上任何一點的位置。首先將地球抽象成一個規則的逼近原始天然地球表面的橢球體,稱爲參考橢球體,而後在參考橢球體上定義一系列的經線和緯線構成經緯網,從而達到經過經緯度來描述地表點位的目的。須要說明的是經緯地理座標系不是平面座標系,由於度不是標準的長度單位,不可用其直接量測面積長度。
經緯度一般分爲天文經緯度、大地經緯度和地心經緯度。經常使用的經度和緯度是從地心到地球表面上某點的測量角。一般以度或百分度爲單位來測量該角度。
在球面系統中,位於兩極點中間的緯線稱爲赤道。它定義的是零緯度線。零經度線稱爲本初子午線。對於絕大多數地理座標系,本初子午線是指經過英國格林尼治的經線。其餘國家/地區使用經過伯爾尼、波哥大和巴黎的經線做爲本初子午線。經緯網的原點 (0,0) 定義在赤道和本初子午線的交點處。這樣,地球就被分爲了四個地理象限,它們均基於與原點所成的羅盤方位角。南和北分別位於赤道的下方和上方,而西和東分別位於本初子午線的左側和右側。
一般,經度和緯度值以十進制度爲單位或以度、分和秒 (DMS) 爲單位進行測量。緯度值相對於赤道進行測量,其範圍是 -90°(南極點)到 +90°(北極點)。經度值相對於本初子午線進行測量。其範圍是 -180°(向西行進時)到 180°(向東行進時)。若是本初子午線是格林尼治子午線,則對於位於赤道南部和格林尼治東部的澳大利亞,其經度爲正值,緯度爲負值。
將球面座標轉化爲平面座標的過程便稱爲投影。
投影座標系在二維平面中進行定義。與地理座標系不一樣,在二維空間範圍內,投影座標系的長度、角度和麪積恆定。投影座標系始終基於地理座標系,然後者則是基於球體或旋轉橢球體的。在投影座標系中,經過格網上的 x,y 座標來標識位置,其原點位於格網中心。每一個位置均具備兩個值,這兩個值是相對於該中心位置的座標。一個指定其水平位置,另外一個指定其垂直位置。這兩個值稱爲 x 座標和 y 座標。採用此標記法,原點座標是 x = 0 和 y = 0。
在等間隔水平線和垂直線的格網化網絡中,中央水平線稱爲 x 軸,而中央垂直線稱爲 y 軸。在 x 和 y 的整個範圍內,單位保持不變且間隔相等。原點上方的水平線和原點右側的垂直線具備正值;下方或左側的線具備負值。四個象限分別表示正負 X 座標和 Y 座標的四種可能組合。在地理座標系中處理數據時,有時用 X 軸表示經度值並用 Y 軸表示緯度值頗有用。
墨卡託投影,是正軸等角圓柱投影。由荷蘭地圖學家墨卡託(G.Mercator)於1569年創立。假想一個與地軸方向一致的圓柱切或割於地球,按等角條件,將經緯網投影到圓柱面上,將圓柱面展爲平面後,即得本投影。墨卡託投影在切圓柱投影與割圓柱投影中,最先也是最經常使用的是切圓柱投影。
假設地球被圍在一中空的圓柱裏,其基準緯線與圓柱相切(赤道)接觸,而後再假想地球中心有一盞燈,把球面上的圖形投影到圓柱體上,再把圓柱體展開,這就是一幅選定基準緯線上的「墨卡託投影」繪製出的地圖。 墨卡託投影沒有角度變形,由每一點向各方向的長度比相等,它的經緯線都是平行直線,且相交成直角,經線間隔相等,緯線間隔從基準緯線處向兩極逐漸增大。墨卡託投影的地圖上長度和麪積變形明顯,但基準緯線處無變形,從基準緯線處向兩極變形逐漸增大,但由於它具備各個方向均等擴大的特性,保持了方向和相互位置關係的正確。在地圖上保持方向和角度的正確是墨卡託投影的優勢,墨卡託投影地圖經常使用做航海圖和航空圖,若是循着墨卡託投影圖上兩點間的直線航行,方向不變能夠一直到達目的地,所以它對船艦在航行中定位、肯定航向都具備有利條件,給航海者帶來很大方便。
墨卡託投影座標系取零子午線或自定義原點經線(L0)與赤道交點的投影爲原點,零子午線或自定義原點經線的投影爲縱座標X軸,赤道的投影爲橫座標Y軸,構成墨卡託平面直角座標系。
當您得到的經緯度座標和使用的地理信息系統不一致時,如使用的是百度地圖,但經緯度數據卻不是百度經緯度,這時必須首先將其它經緯度座標系轉換爲百度座標系,反之亦然。
屬於火星座標的地理信息系統主要有高德、Gogole地圖、搜搜地圖等。
注:輸入火星座標經緯度,點擊「座標轉換」按鈕,可得到百度經緯度。火星座標經緯度(126.609207, 45.740142)樣例
代碼樣例
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微軟雅黑";} </style> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的密鑰"></script> <title>google轉百度</title> </head> <body> <div id="allmap"></div> </body> </html> <script type="text/javascript"> // 百度地圖API功能 //谷歌座標 var x = 116.32715863448607; var y = 39.990912172420714; var ggPoint = new BMap.Point(x,y); //地圖初始化 var bm = new BMap.Map("allmap"); bm.centerAndZoom(ggPoint, 15); bm.addControl(new BMap.NavigationControl()); //添加谷歌marker和label var markergg = new BMap.Marker(ggPoint); bm.addOverlay(markergg); //添加谷歌marker var labelgg = new BMap.Label("未轉換的谷歌標註(錯誤)",{offset:new BMap.Size(20,-10)}); markergg.setLabel(labelgg); //添加谷歌label //座標轉換完以後的回調函數 translateCallback = function (data){ if(data.status === 0) { var marker = new BMap.Marker(data.points[0]); bm.addOverlay(marker); var label = new BMap.Label("轉換後的百度標註(正確)",{offset:new BMap.Size(20,-10)}); marker.setLabel(label); //添加百度label bm.setCenter(data.points[0]); } } setTimeout(function(){ var convertor = new BMap.Convertor(); var pointArr = []; pointArr.push(ggPoint); convertor.translate(pointArr, 3, 5, translateCallback) }, 1000); </script>
注:代碼樣例代碼摘自百度地圖API示例文檔
注:代碼樣例和火星座標轉百度座標代碼相同,最後一行代碼修改成:
「convertor.translate(pointArr, 1, 5, translateCallback)」
火星座標 原始座標
注:按數組格式批量添加經緯度,而後運行「批量座標轉換」按鈕。每次最多轉換10組經緯度
代碼樣例
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微軟雅黑";} </style> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的密鑰"></script> <title>批量轉換</title> </head> <body> <div id="allmap"></div> </body> </html> <script type="text/javascript"> var points = [new BMap.Point(116.3786889372559,39.90762965106183), new BMap.Point(116.38632786853032,39.90795884517671), new BMap.Point(116.39534009082035,39.907432133833574), new BMap.Point(116.40624058825688,39.90789300648029), new BMap.Point(116.41413701159672,39.90795884517671) ]; //地圖初始化 var bm = new BMap.Map("allmap"); bm.centerAndZoom(new BMap.Point(116.378688937,39.9076296510), 15); //座標轉換完以後的回調函數 translateCallback = function (data){ if(data.status === 0) { for (var i = 0; i < data.points.length; i++) { bm.addOverlay(new BMap.Marker(data.points[i])); bm.setCenter(data.points[i]); } } } setTimeout(function(){ var convertor = new BMap.Convertor(); convertor.translate(points, 1, 5, translateCallback) }, 1000); </script>
注:代碼樣例代碼摘自百度地圖API示例文檔
在百度地圖API中,墨卡託座標(平面座標)是以最大級別18級爲基準的。在18級條件下,平 面座標的一個單位就表明了屏幕上的1個像素。平面座標與地圖所展現的級別沒有關係,也就是說在1級和18級下,天安門位置的平面座標都是一致的。
分級地圖展現示例以下:
注:在級別下拉框中選擇1-18級觀察地圖變化效果
百度經緯度轉換爲摩卡託
var pt = new BMap.Point(116.316163,39.997753); var projection = map.getMapType().getProjection(); var worldCoordinate = projection.lngLatToPoint(pt);
worldCoordinate.x和worldCoordinate.y就是平面(墨卡託)座標的x和y。
摩卡託轉換爲百度經緯度
var xy = new BMap.Pixel(12948396.92,4837893.73); var projection = map.getMapType().getProjection(); var LngLat = projection.pointToLngLat(xy);
LngLat.lng和LngLat.lat就是經緯度。
平面座標系的原點與經緯度的原點一致,即赤道與0度經線相交的位置。對於地球上某一個固定的點(如天安門:經度116.40387五、緯度39.915168),在不一樣級別地圖圖片上該點到平面座標原點的像素座標是不一樣的。在第18級下,直接將平面座標向下取整就獲得了像素座標,而在其餘級別下能夠經過以下公式進行換算(這裏取整爲向下取整):
\[像素座標 = |平面座標\times 2^{zoom - 18}|\]
例如,通過計算,在第4級天安門位置的像素座標是:790, 294。
天安門的經度爲116.40387五、緯度爲39.915168,轉換爲墨卡託座標爲X=12958161.0九、Y=4825948.05。
在第18級地圖中,直接將平面座標向下取整就獲得了像素座標,即(12958161,4825948)。
在第4級地圖中,
\[像素座標X = |12958161.09\times 2^{4 - 18}| = |790.9034|=790\]
\[像素座標Y = |4825948.05\times 2^{4 - 18}| = |295.5525|=294\]
注:計算結果向下取整
百度地圖API在展現地圖時是將整個地圖圖片切割成若干圖塊來顯示的,當地圖初始化或是地圖級別、中心點位置發生變化時,地圖API會根據當前像素座標計算出視野內須要的圖塊座標(也叫圖塊編號),從而加載對應的圖塊用以顯示地圖。一般,百度地圖分辨率越高、顯示級別越大,須要的地圖圖片就越多。
百度地圖的圖塊座標原點與平面座標一致,從原點向右上方開始編號爲0, 0:
如何知道某個位置的圖塊座標呢?經過以下公式計算便可(這裏爲向下取整):
圖塊座標 = |像素座標 ÷ 256|
256其實是每一個圖塊的像素寬度和高度,咱們用像素座標除以這個數就知道圖塊座標了。
還以天安門爲例,在第4級下天安門所在的圖塊編號爲(3,1):
\[圖塊座標X = |790 ÷ 256| = |3.086| = 3 (px)\]
\[圖塊座標Y = |294 ÷ 256| = |1.1484| = 1 (px)\]
而在第18級下,圖塊編號爲(50617, 18851)
\[圖塊座標X = |12958161 ÷ 256| = |50617.82| = 50617 (px)\]
\[圖塊座標Y = |4825948 ÷ 256| = |18851.36| = 18851 (px)\]
前面給出的國測局座標(火星座標,GCJ02)、和GPS座標(原始座標,WGS84)轉換爲百度座標(BD09)的方法由百度地圖API提供。下面的Javascript代碼能夠更方便地進行不一樣座標系的轉換。項目細節參考GitHub地址:https://github.com/wandergis/coordtransform。
注:按數組格式批量添加經緯度,選擇相互轉換的座標,而後運行「批量座標轉換」按鈕。每次轉換數量不受限制,可進行大批量地址轉換。
本文提供的各類座標轉換工具僅用於我的學習或教學研究用途,不支持大批量商業用途座標轉換(因爲百度地圖key的限制)。