【地圖API】為何您的座標不準?如何糾偏?

酸奶小妹發表於2014-03-27

摘要:各種座標體系之間如何轉換?到底有哪些座標體系?什麼是火星座標?為什麼我的座標,在地圖上顯示會有偏移?本文詳細解答以上問題。最後給出座標拾取工具。

---------------------------------------------------------------------------------------------------------------------------

一、座標體系

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

第一種分類:

1、  GPS,WGS-84,原始座標體系。一般用國際標準的GPS記錄儀記錄下來的座標,都是GPS的座標。很可惜,在中國,任何一個地圖產品都不允許使用GPS座標,據說是為了保密。GPS座標形式如圖,度分秒形式的經緯度:

 


2、  GCJ-02,國測局02年釋出的座標體系。又稱“火星座標”。在中國,必須至少使用GCJ-02的座標體系。比如谷歌,騰訊,高德都在用這個座標體系。GCJ-02也是國內最廣泛使用的座標體系

3、  其他座標體系。一般都是由GCJ-02進過偏移演算法得到的。這種體系就根據每個公司的不同,座標體系都不一樣了。比如,百度和搜狗就使用自己的座標體系,與其他座標體系不相容。

 

第二種分類:

首先明白,所有座標體系的原點,都是非洲。

 

1、  經緯度。這個是球面座標,對於北京來說,就是(116.388171,39.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_translate.html#late_intro

 

3、GCJ-02與BD-09之間互轉

國測局GCJ-02座標體系(谷歌、高德、騰訊),與百度座標BD-09體系的轉換,在CSDN上有很詳細的講解:

http://blog.csdn.net/coolypf/article/details/8569813

 

不過也有更簡單的演算法,線性演算法(lat和lng是經緯度,球面座標):

To_B是轉到百度,To_G是轉到GCJ-02。

var TO_BLNG = function(lng){return lng+0.0065;};

var TO_BLAT = function(lat){return lat+0.0060;};

var TO_GLNG = function(lng){return lng-0.0065;};

var TO_GLAT = function(lat){return lat-0.0060;};

 

4、經緯緯度轉成墨卡託

網上也有詳細講解:

http://bbs.esrichina-bj.cn/esri/viewthread.php?tid=78245

 

5、各家API公司座標轉換介面的申請

一般需要將您的公司名稱、專案名稱、專案簡介、聯絡人和聯絡方式,發郵件至地圖API公司的商務部,經過申請,才能使用。

下面是他們的聯絡方式:

高德地圖

api@autonavi.com

百度地圖

mapapi@baidu.com

騰訊地圖

mapapi@vip.qq.com

谷歌地圖

這個,國內沒有公交介面,大家應該不會再使用了吧。  

 

 

 

 

 

 

(大家發現沒,高德是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)。

 

四、座標拾取工具

既然在國內必須至少使用GCJ-02的座標系,而GCJ-02,“火星座標”是在國內最廣泛使用的座標體系。那麼,我們就來看看,如何直接獲取到GCJ-02座標唄。

請大家把這段程式碼儲存到記事本里,然後字尾名改為.html,記得用UTF-8編碼來儲存。然後雙擊這個檔案,就能開啟網頁了。

 

註冊你自己的key,填在原始碼裡哦:http://api.amap.com/key/index 

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>火星座標拾取</title>
<script language="javascript" src="http://webapi.amap.com/maps?v=1.2&key=您的key"></script>
<style>
#iMap{height:500px;width:600px;float:left;}
.info{float:left;margin:0 0 0 10px;}
label{width:80px;float:left;}
</style>
</head>
<body onLoad="mapInit()">
    <div id="iMap"></div>
    <div class="info">
        <p><label>火星座標:</label><span id="lnglat">&nbsp;</span></p>
        <p><label>地址:</label><span id="iAddress">&nbsp;</span></p>
        </br>
        <p>說明:</p>
        <p>1、滑鼠滾輪可以縮放地圖,拖動地圖。</p>
        <p>2、點選地圖,即可獲得GCJ-02的經緯度座標,地址。</p>
    </div>
</body>
<script language="javascript">
var mapObj;
var lnglatXY;
//初始化地圖
function mapInit(){
    var opt = {  
        level: 13, //設定地圖縮放級別    
        center: new AMap.LngLat(116.397428, 39.90923) //設定地圖中心點   
    }  
    mapObj = new AMap.Map("iMap", opt);  
    
    AMap.event.addListener(mapObj,'click',getLnglat); //點選事件
}
function geocoder() {
    var MGeocoder;
    //載入地理編碼外掛
    mapObj.plugin(["AMap.Geocoder"], function() {        
        MGeocoder = new AMap.Geocoder({ 
            radius: 1000,
            extensions: "all"
        });
        //返回地理編碼結果 
        AMap.event.addListener(MGeocoder, "complete", geocoder_CallBack); 
        //逆地理編碼
        MGeocoder.getAddress(lnglatXY); 
    });
    //加點
    var marker = new AMap.Marker({
        map:mapObj,
        icon: new AMap.Icon({
            image: "http://api.amap.com/Public/images/js/mark.png",
            size:new AMap.Size(58,30),
            imageOffset: new AMap.Pixel(-32, -0)
        }),
        position: lnglatXY,
        offset: new AMap.Pixel(-5,-30)
    });
    mapObj.setFitView();
}
//回撥函式
function geocoder_CallBack(data) {
    var address;
    //返回地址描述
    address = data.regeocode.formattedAddress;
    //返回結果拼接輸出
    document.getElementById("iAddress").innerHTML = address;
}  
//滑鼠點選,獲取經緯度座標  
function getLnglat(e){    
    mapObj.clearMap();
    var x = e.lnglat.getLng();
    var y = e.lnglat.getLat(); 
    document.getElementById("lnglat").innerHTML = x + "," + y;
    
    lnglatXY = new AMap.LngLat(x,y);
    geocoder();
}
</script>
</html>

 

開啟之後,是這樣的:

 

 點選一下地圖,即可獲得GCJ-02座標,地址:

 

 

demo地址:http://zhaoziang.com/amap/picpoint.html

 

 

2014-5-21 更新

高德官方座標拾取工具:http://api.amap.com/LngLatPicker

相關文章