• 火星坐标系统


    其原理是这样的:保密局开发了一个系统,能将实际的坐标转换成虚拟的坐标。所有在中国销售的数字地图必须使用这个系统进行坐标转换之后方可上市。这是生产环节,这种电子地图被称为火星地图。在使用环节,GPS终端设备必须集成保密局提供的加密算法(集成工作由保密局完成),把从GPS卫星那里得到的坐标转换成虚拟坐标,然后再去火星地图上查找,这样就在火星坐标系上完成了地图的匹配。 所以大家所用的百度,高德等地图定位准是偏差几百米

    名词总结:

    地球坐标:指WGS84坐标系统

    火星坐标:指使用国家保密插件人为偏移后的坐标
    地球地图:指与地球坐标对应的客观真实的地图
    火星地图:指经过加密偏移后的,与火星坐标对应的地图

    坐标系转换算法

    1.GCJ-02(火星坐标系)和BD-09转换

    // GCJ-02 坐标转换成 BD-09 坐标
    + (CLLocationCoordinate2D)MarsGS2BaiduGS:(CLLocationCoordinate2D)coordinate
    {
        double x_pi = PI * 3000.0 / 180.0;
        double x = coordinate.longitude, y = coordinate.latitude;
        double z = sqrt(x * x + y * y) + 0.00002 * sin(y * x_pi);
        double theta = atan2(y, x) + 0.000003 * cos(x * x_pi);
        double bd_lon = z * cos(theta) + 0.0065;
        double bd_lat = z * sin(theta) + 0.006;
        return CLLocationCoordinate2DMake(bd_lat, bd_lon);
    }
     
    // BD-09 坐标转换成 GCJ-02 坐标
    + (CLLocationCoordinate2D)BaiduGS2MarsGS:(CLLocationCoordinate2D)coordinate
    {
        double x_pi = PI * 3000.0 / 180.0;
        double x = coordinate.longitude - 0.0065, y = coordinate.latitude - 0.006;
        double z = sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi);
        double theta = atan2(y, x) - 0.000003 * cos(x * x_pi);
        double gg_lon = z * cos(theta);
        double gg_lat = z * sin(theta);
        return CLLocationCoordinate2DMake(gg_lat, gg_lon);
    }

    2WGS-84(地球坐标系)和BD-09(百度坐标)转换

     1 // WGS-84 坐标转换成 BD-09 坐标
     2 + (CLLocationCoordinate2D)WorldGS2BaiduGS:(CLLocationCoordinate2D)coordinate
     3 {
     4     CLLocationCoordinate2D mars = [ALDGeocoder WorldGS2MarsGS:coordinate];
     5     CLLocationCoordinate2D baidu = [ALDGeocoder MarsGS2BaiduGS:mars];
     6     return baidu;
     7 }
     8  
     9 // BD-09 坐标转换成 WGS-84 坐标
    10 + (CLLocationCoordinate2D)BaiduGS2WorldGS:(CLLocationCoordinate2D)coordinate
    11 {
    12     CLLocationCoordinate2D mars = [ALDGeocoder BaiduGS2MarsGS:coordinate];
    13     CLLocationCoordinate2D world = [ALDGeocoder MarsGS2WorldGS:mars];
    14     return world;
    15 }

    3.WGS-84和sogou坐标转换

     1 // WGS-84 坐标转换成 Sogou 坐标
     2 + (CLLocationCoordinate2D)WorldGS2SogouGS:(CLLocationCoordinate2D)coordinate
     3 {
     4     const double ee = 0.082271854224939184;
     5     double lon = coordinate.longitude;
     6     double lat = coordinate.latitude;
     7     double dlon = [ALDGeocoder rad:CLIP(lon, -360, 360)];
     8     double dlat = [ALDGeocoder rad:CLIP(lat, -90, 90)];
     9     dlon = 6378206.4 * dlon;
    10     double sinphi = sin(dlat);
    11     double temp1, temp2;
    12     if((temp1 = 1.0 + sinphi) == 0.0){
    13         dlat = -1000000000;
    14     }else if((temp2 = 1.0 - sinphi) == 0.0){
    15         dlat = 1000000000;
    16     }else{
    17         double esinphi = ee * sinphi;
    18         dlat = 3189103.2000000002 * log((temp1 / temp2) * pow((1.0 - esinphi) / (1.0 + esinphi), ee));
    19     }
    20     return CLLocationCoordinate2DMake(dlat, dlon);
    21 }
    22  
    23 // Sogou 坐标转换成 WGS-84 坐标
    24 + (CLLocationCoordinate2D)SogouGS2WorldGS:(CLLocationCoordinate2D)coordinate
    25 {
    26     const double ee = 1.5707963267948966;
    27     const double aa = 0.0033938814110493522;
    28     double lon = coordinate.longitude;
    29     double lat = coordinate.latitude;
    30     double dlon = lon / 6378206.4;
    31     double temp = -lat / 6378206.4;
    32     double chi;
    33     if(temp < -307){
    34         chi = ee;
    35     }else if(temp > 308){
    36         chi = -ee;
    37     }else{
    38         chi = ee - 2 * atan(exp(temp));
    39     }
    40     double chi2 = 2 * chi;
    41     double coschi2 = cos(chi2);
    42     double dlat = chi + sin(chi2) * (aa + coschi2 * (1.3437644537757259E-005 + coschi2 * (7.2964865099246009E-008 + coschi2 * 4.4551470401894685E-010)));
    43     double rlon = CLIP([ALDGeocoder deg:dlon], -360, 360);
    44     double rlat = CLIP([ALDGeocoder deg:dlat], -90, 90);
    45     return CLLocationCoordinate2DMake(rlat, rlon);
    46 }

    4火星坐标和地球坐标转换

     1 // World Geodetic System ==> Mars Geodetic System
     2 + (CLLocationCoordinate2D)WorldGS2MarsGS:(CLLocationCoordinate2D)coordinate
     3 {
     4     // a = 6378245.0, 1/f = 298.3
     5     // b = a * (1 - f)
     6     // ee = (a^2 - b^2) / a^2;
     7     const double a = 6378245.0;
     8     const double ee = 0.00669342162296594323;
     9      
    10     if (outOfChina(coordinate.latitude, coordinate.longitude))
    11     {
    12         return coordinate;
    13     }
    14     double wgLat = coordinate.latitude;
    15     double wgLon = coordinate.longitude;
    16     double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
    17     double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
    18     double radLat = wgLat / 180.0 * PI;
    19     double magic = sin(radLat);
    20     magic = 1 - ee * magic * magic;
    21     double sqrtMagic = sqrt(magic);
    22     dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
    23     dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * PI);
    24      
    25     return CLLocationCoordinate2DMake(wgLat + dLat, wgLon + dLon);
    26 }
    27  
    28 // Mars Geodetic System ==> World Geodetic System
    29 + (CLLocationCoordinate2D)MarsGS2WorldGS:(CLLocationCoordinate2D)coordinate
    30 {
    31     double gLat = coordinate.latitude;
    32     double gLon = coordinate.longitude;
    33     CLLocationCoordinate2D marsCoor = [ALDGeocoder WorldGS2MarsGS:coordinate];
    34     double dLat = marsCoor.latitude - gLat;
    35     double dLon = marsCoor.longitude - gLon;
    36     return CLLocationCoordinate2DMake(gLat - dLat, gLon - dLon);
    37 }

    5WGS-84 和 墨卡托 坐标转换

     1 //WGS-84 坐标转换成 墨卡托 坐标
     2 + (CLLocationCoordinate2D)WorldGS2Mercator:(CLLocationCoordinate2D)coordinate
     3 {
     4     double lon = coordinate.longitude*20037508.34/180;
     5     double lat = log(tan((90+coordinate.latitude)*M_PI/360))/(M_PI/180);
     6     lat = lat*20037508.34/180;
     7     return CLLocationCoordinate2DMake(lat, lon);
     8 }
     9  
    10 //墨卡托 坐标转换成 WGS-84 坐标
    11 + (CLLocationCoordinate2D)Mercator2WorldGS:(CLLocationCoordinate2D)mercator
    12 {
    13     double lon = mercator.longitude/20037508.34*180;
    14     double lat = mercator.latitude/20037508.34*180;
    15     lat = 180/M_PI*(2*atan(exp(lat*M_PI/180))-M_PI/2);
    16     return CLLocationCoordinate2DMake(lat, lon);
    17 }

    开发时所面临的现状

    获取经纬度(GPS)

    • 火星坐标

      • MKMapView

    • 地球坐标

      • CLLocationManager

    显示经纬度(地图)

    • 火星坐标

      • iOS 地图

      • Gogole地图

      • 搜搜、阿里云、高德地图

    • 地球坐标

      • Google 卫星地图(国外地图应该都是……)

    • 百度坐标

      • 百度地图

    推荐的解决方案:

      • 既然是在国内,存储一律用火星坐标,这样在使用国内地图显示时最方便(用百度地图显示时可以一次转换取得)

      • CLLocationManager 拿到的 CLLocation 转为火星坐标,MKMapView 不用处理

      • 使用地图 API 进行 地址解析/逆地址解析(Geocoding) 时注意相应使用相应地图商的坐标系

      • 部分地图商支持多个坐标系输入,如高德支持地球、火星坐标(这个一直有变动,具体只能参考厂商最新文档了

  • 相关阅读:
    Python集合
    excel数据的处理
    史上最全的web前端系统学习教程!
    H5游戏开发:贪吃蛇
    javascript+HTMl5游戏下载,开发一个都能月薪上万!舅服你
    2020年必看的web前端开发学习路线!
    花了一天准备好的web前端电子书籍,全部可以免费下载!
    2019年大牛最新整理的Python技术入门路线
    从零开始,学习web前端之HTML5开发
    经验分享:如何系统学习 Web 前端技术?
  • 原文地址:https://www.cnblogs.com/W-Kr/p/5302239.html
Copyright © 2020-2023  润新知