iOS 之地圖坐標體系和轉換


一、坐標體系

首先我們要明白,開發者能接觸到哪些坐標體系呢?

第一種分類:

1、  GPS,WGS-84,原始坐標體系。一般用國際標准的GPS記錄儀記錄下來的坐標,
都是GPS的坐標。很可惜,在中國,任何一個地圖產品都不允許使用GPS坐標,
據說是為了保密。GPS坐標形式如圖,度分秒形式的經緯度。
2、  GCJ-02,國測局02年發布的坐標體系。又稱“火星坐標”。
在中國,必須至少使用GCJ-02的坐標體系。比如谷歌,騰訊,高德都在
用這個坐標體系。GCJ-02也是國內最廣泛使用的坐標體系。
3、  其他坐標體系。一般都是由GCJ-02進過偏移算法得到的。
這種體系就根據每個公司的不同,坐標體系都不一樣了。比如,
百度和搜狗就使用自己的坐標體系,與其他坐標體系不兼容。

  

第二種分類:

首先明白,所有坐標體系的原點,都是非洲。
1、  經緯度。這個是球面坐標,對於北京來說,就是(116.38817139.935961)這
樣的坐標。比如騰訊、高德、百度都是這樣的經緯度坐標。
谷歌是經緯度順序寫反的經緯度坐標。如果是度分秒坐標,需要進行轉換
,才能得到這樣的經緯度坐標。詳見坐標轉換。
2、  墨卡托坐標。平面坐標,相當於是直線距離,數字一般都比較大,像這樣的。
(215362.00021333335 99526.00034912192)墨卡托坐標,
主要用於程序的后台計算。直線距離嘛,加加減減幾乎計算方便。
搜狗地圖API就是直接使用的墨卡托坐標。

  

二、坐標轉換

在各種web端平台,或者高德、騰訊、百度上取到的坐標,都不是GPS坐標,
都是GCJ-02坐標,或者自己的偏移坐標系。
比如,你在谷歌地圖API,高德地圖API,騰訊地圖API上取到的,
都是GCJ-02坐標,他們三家都是通用的,也適用於大部分地圖API產品,
以及他們的地圖產品。
例外,百度API上取到的,是BD-09坐標,只適用於百度地圖相關產品。
例外,搜狗API上取到的,是搜狗坐標,只適用於搜狗地圖相關產品。
例外,谷歌地球,google earth上取到的,是GPS坐標,
而且是度分秒形式的經緯度坐標。在國內不允許使用。必須轉換為GCJ-02坐標。

  

  1. 度分秒坐標轉換為經緯度 比如,在GPS記錄儀,或者google earth上采集到的是39°31'20.51,那么應該這樣換算,31分就是31/60度,20.51秒就是20.51/3600度,結果就是39 + 31/60 + 20.51/3600 度。

  2. GPS轉換為GCJ-02坐標
    谷歌,高德,騰訊的地圖API官網上,都不直接提供這樣的坐標轉換。如果要得到GCJ-02坐標,最好在他們的地圖上直接取點,或者通過地址解析得到。不過,在網上搜到了這樣的接口,該接口的type=1就是GPS轉到GCJ-02的墨卡托坐標。請大家對接口保密。詳見:http://map.sogou.com/api/documentation/javascript/api2.5/interface_tra...

  3. GCJ-02與BD-09之間互轉 國測局GCJ-02坐標體系(谷歌、高德、騰訊),與百度坐標BD-09體系的轉換,我今天想說的就是這個,后面有相關代碼!

4、經緯緯度轉成墨卡托
網上也有詳細講解:http://bbs.esrichina-bj.cn/esri/viewthread.php?tid=78245(大家發現沒,高德是api,騰訊和百度是mapapi,說明什么?)

三、坐標偏移

如果您的坐標在轉換之后,還有偏移,那么考慮以下幾個方面。
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)。

百度地圖坐標與蘋果自帶地圖經緯度之間的相互轉換方法:

/// 百度坐標轉高德坐標
+ (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);
}

  

開源項目

JZLocationConverter:

https://github.com/JackZhouCn/JZLocationConverter

python版本

# -*- 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}

收藏學習,轉自:https://segmentfault.com/a/1190000003023989 

其他參考:

http://www.jianshu.com/p/abdb35b0ba78


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM