首先咱們要明白,開發者能接觸到哪些座標體系呢?javascript
一、 GPS,WGS-84,原始座標體系。通常用國際標準的GPS記錄儀記錄下來的座標, 都是GPS的座標。很惋惜,在中國,任何一個地圖產品都不容許使用GPS座標, 聽說是爲了保密。GPS座標形式如圖,度分秒形式的經緯度。 二、 GCJ-02,國測局02年發佈的座標體系。又稱「火星座標」。 在中國,必須至少使用GCJ-02的座標體系。好比谷歌,騰訊,高德都在 用這個座標體系。GCJ-02也是國內最普遍使用的座標體系。 三、 其餘座標體系。通常都是由GCJ-02進過偏移算法獲得的。 這種體系就根據每一個公司的不一樣,座標體系都不同了。好比, 百度和搜狗就使用本身的座標體系,與其餘座標體系不兼容。
首先明白,全部座標體系的原點,都是非洲。 一、 經緯度。這個是球面座標,對於北京來講,就是(116.38817139.935961)這 樣的座標。好比騰訊、高德、百度都是這樣的經緯度座標。 谷歌是經緯度順序寫反的經緯度座標。若是是度分秒座標,須要進行轉換 ,才能獲得這樣的經緯度座標。詳見座標轉換。 二、 墨卡託座標。平面座標,至關因而直線距離,數字通常都比較大,像這樣的。 (215362.00021333335 99526.00034912192)墨卡託座標, 主要用於程序的後臺計算。直線距離嘛,加加減減幾乎計算方便。 搜狗地圖API就是直接使用的墨卡託座標。
在各類web端平臺,或者高德、騰訊、百度上取到的座標,都不是GPS座標, 都是GCJ-02座標,或者本身的偏移座標系。 好比,你在谷歌地圖API,高德地圖API,騰訊地圖API上取到的, 都是GCJ-02座標,他們三家都是通用的,也適用於大部分地圖API產品, 以及他們的地圖產品。 例外,百度API上取到的,是BD-09座標,只適用於百度地圖相關產品。 例外,搜狗API上取到的,是搜狗座標,只適用於搜狗地圖相關產品。 例外,谷歌地球,google earth上取到的,是GPS座標, 並且是度分秒形式的經緯度座標。在國內不容許使用。必須轉換爲GCJ-02座標。
度分秒座標轉換爲經緯度
好比,在GPS記錄儀,或者google earth上採集到的是39°31'20.51,那麼應該這樣換算,31分就是31/60度,20.51秒就是20.51/3600度,結果就是39 + 31/60 + 20.51/3600 度。php
GPS轉換爲GCJ-02座標
谷歌,高德,騰訊的地圖API官網上,都不直接提供這樣的座標轉換。若是要獲得GCJ-02座標,最好在他們的地圖上直接取點,或者經過地址解析獲得。不過,在網上搜到了這樣的接口,該接口的type=1就是GPS轉到GCJ-02的墨卡託座標。請你們對接口保密。詳見:http://map.sogou.com/api/documentation/javascript/api2.5/interface_tra...html
GCJ-02與BD-09之間互轉
國測局GCJ-02座標體系(谷歌、高德、騰訊),與百度座標BD-09體系的轉換,我今天想說的就是這個,後面有相關代碼!java
四、經緯緯度轉成墨卡託
網上也有詳細講解:http://bbs.esrichina-bj.cn/esri/viewthread.php?tid=78245(你們發現沒,高德是api,騰訊和百度是mapapi,說明什麼?)python
3、座標偏移git
若是您的座標在轉換以後,還有偏移,那麼考慮如下幾個方面。
A、原始座標系弄錯,好比覺得本身是GPS座標,但其實已是GCJ-02座標。
解決方案:請確保採集到的數據是哪一個座標體系,須要轉換到哪一個座標系,再進行座標轉換。
B、原始座標準確度不夠
解決方案:若是您是GPS座標,請確保採集GPS數據時,搜到至少4顆以上的衛星。而且GPS數據準不許,還取決於周圍建築物的高度,越高越不許,由於有遮擋。
若是原本就是GCJ-02座標,在不一樣地圖放大級別的時候,看到的地方可能不同。好比你在地圖級別4(國家)取到的座標,放大到地圖12級(街道)時,座標就偏了。請確保在地圖最大放大級別時,拾取座標。
C、度分秒的概念混淆
好比,在google earth上採集到的是39°31'20.51,那麼應該這樣換算,31分就是31/60度,20.51秒就是20.51/3600度,結果就是39 + 31/60 + 20.51/3600 度。
D、經緯度順序寫反了
有些公司(好比高德,百度,騰訊)是先經度,再緯度,即Point(lng lat)。但谷歌座標的順序剛好相反,是(lat lng)。github
百度地圖座標與蘋果自帶地圖經緯度之間的相互轉換方法: /// 百度座標轉高德座標 + (CLLocationCoordinate2D)GCJ02FromBD09:(CLLocationCoordinate2D)coor { CLLocationDegrees x_pi = 3.14159265358979324 * 3000.0 / 180.0; CLLocationDegrees x = coor.longitude - 0.0065, y = coor.latitude - 0.006; CLLocationDegrees z = sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi); CLLocationDegrees theta = atan2(y, x) - 0.000003 * cos(x * x_pi); CLLocationDegrees gg_lon = z * cos(theta); CLLocationDegrees gg_lat = z * sin(theta); return CLLocationCoordinate2DMake(gg_lat, gg_lon); } // 高德座標轉百度座標 + (CLLocationCoordinate2D)BD09FromGCJ02:(CLLocationCoordinate2D)coor { CLLocationDegrees x_pi = 3.14159265358979324 * 3000.0 / 180.0; CLLocationDegrees x = coor.longitude, y = coor.latitude; CLLocationDegrees z = sqrt(x * x + y * y) + 0.00002 * sin(y * x_pi); CLLocationDegrees theta = atan2(y, x) + 0.000003 * cos(x * x_pi); CLLocationDegrees bd_lon = z * cos(theta) + 0.0065; CLLocationDegrees bd_lat = z * sin(theta) + 0.006; return CLLocationCoordinate2DMake(bd_lat, bd_lon); }
https://github.com/JackZhouCn/JZLocationConverterweb
# -*- coding: utf-8 -*- import math x_pi = 3.14159265358979324 * 3000.0 / 180.0 def bd_encrypt(gg): x = gg["gg_lon"] y = gg["gg_lat"] z = math.sqrt(x * x + y * y) + 0.00002 * math.sin(y * x_pi) theta = math.atan2(y, x) + 0.000003 * math.cos(x * x_pi) bd_lon = z * math.cos(theta) + 0.0065 bd_lat = z * math.sin(theta) + 0.006 return {"bd_lon":bd_lon, "bd_lat":bd_lat} def bd_decrypt(bd): x = bd["bd_lon"] - 0.0065 y = bd["bd_lat"] - 0.006; z = sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi); theta = atan2(y, x) - 0.000003 * cos(x * x_pi); gg_lon = z * cos(theta); gg_lat = z * sin(theta); return {"gg_lon":gg_lon, "gg_lat":gg_lat}