美文网首页
解决坐标转换、坐标偏移问题

解决坐标转换、坐标偏移问题

作者: 长若执念 | 来源:发表于2020-12-19 18:58 被阅读0次

    一、坐标体系

    首先我们要明白,开发者能接触到哪些坐标体系呢?

    第一种分类:

    1、 GPS,WGS-84,原始坐标体系。

    一般用国际标准的GPS记录仪记录下来的坐标,都是GPS的坐标。很可惜,在中国,任何一个地图产品都不允许使用GPS坐标,据说是为了保密。GPS坐标形式如图,度分秒形式的经纬度:


    GPS经纬度.jpg
    2、 GCJ-02,国测局02年发布的坐标体系。又称“火星坐标”。

    在中国,必须至少使用GCJ-02的坐标体系。比如谷歌,腾讯,高德都在用这个坐标体系。GCJ-02也是国内最广泛使用的坐标体系。

    3、 其他坐标体系。

    一般都是由GCJ-02进过偏移算法得到的。这种体系就根据每个公司的不同,坐标体系都不一样了。比如,百度和搜狗就使用自己的坐标体系,与其他坐标体系不兼容。

    第二种分类:

    首先明白,所有坐标体系的原点,都是非洲。


    坐标系原点-非洲.jpg
    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_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
    (大家发现没,高德是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编码来保存。然后双击这个文件,就能打开网页了。

    <!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=6260f3e133c146a76f7c210c2786aec9"></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(5830) 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(xy); geocoder();}
        </script>
    
    </html>
    
    补充:

    关于iOS定位:
    火星坐标: MKMapView:展示在中国的地图上,获取的是 GCJ-02坐标系
    地球坐标:CLLocationManager:更国际化,获取的是 GPS,WGS-84坐标系。
    所以,在国内,如果定位有偏差,看看是不是用的CLLocationManager定位的,换成MKMapView定位,即可获得准确的经纬度

    参考文章:如何解决坐标转换、坐标偏移问题

    相关文章

      网友评论

          本文标题:解决坐标转换、坐标偏移问题

          本文链接:https://www.haomeiwen.com/subject/aiucnktx.html