zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    【crontab】误删crontab及其恢复
    New Concept English there (7)
    New Concept English there (6)
    New Concept English there (5)
    New Concept English there (4)
    New Concept English there (3)
    New Concept English there (2)Typing speed exercise
    New Concept English there (1)Typing speed exercise
    New Concept English Two 34 game over
    New Concept English Two 33 94
  • 原文地址:https://www.cnblogs.com/xiaopin/p/6429322.html
Copyright © 2011-2022 走看看