iOS 火星坐标系 与 地球坐标系


在开发过程中,遇到一个问题,安卓和iOS传同样的经纬度给后台,但是后台给出的酒店 按照距离排序 两端确实不一致的。

原因:安卓使用的高德地图定位,直接定位的经纬度就是火星坐标系,而iOS使用的是苹果自带的定位系统,定位的坐标使用的是地球坐标系,没有转换。


解决方法:使用了架构组提供的方法,发现不准确,差大概500~600m的距离,尝试失败。

换另外一种方法: (高德提供的)

CLLocationCoordinate2D amapcoord = AMapCoordinateConvert(CLLocationCoordinate2DMake(39.989612,116.480972), AMapCoordinateType);

//将地球坐标系转成火星坐标系

self.currentLocation = AMapCoordinateConvert(CLLocationCoordinate2DMake([TNLocationManager sharedInstance].lat,[TNLocationManager sharedInstance].lng), AMapCoordinateTypeGPS);


效果比较好,差距在1m以内。架构组重新去更改转换的算法:)


--------------------------------下面部分为转载

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

名词总结:

地球坐标:指WGS84坐标系统

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

火星地图:指经过加密偏移后的,与火星坐标对应的地图

坐标系转换算法

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

[cpp]  view plain  copy
  1. // GCJ-02 坐标转换成 BD-09 坐标  
  2. + (CLLocationCoordinate2D)MarsGS2BaiduGS:(CLLocationCoordinate2D)coordinate  
  3. {  
  4.     double x_pi = PI * 3000.0 / 180.0;  
  5.     double x = coordinate.longitude, y = coordinate.latitude;  
  6.     double z = sqrt(x * x + y * y) + 0.00002 * sin(y * x_pi);  
  7.     double theta = atan2(y, x) + 0.000003 * cos(x * x_pi);  
  8.     double bd_lon = z * cos(theta) + 0.0065;  
  9.     double bd_lat = z * sin(theta) + 0.006;  
  10.     return CLLocationCoordinate2DMake(bd_lat, bd_lon);  
  11. }  
  12.   
  13. // BD-09 坐标转换成 GCJ-02 坐标  
  14. + (CLLocationCoordinate2D)BaiduGS2MarsGS:(CLLocationCoordinate2D)coordinate  
  15. {  
  16.     double x_pi = PI * 3000.0 / 180.0;  
  17.     double x = coordinate.longitude - 0.0065, y = coordinate.latitude - 0.006;  
  18.     double z = sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi);  
  19.     double theta = atan2(y, x) - 0.000003 * cos(x * x_pi);  
  20.     double gg_lon = z * cos(theta);  
  21.     double gg_lat = z * sin(theta);  
  22.     return CLLocationCoordinate2DMake(gg_lat, gg_lon);  
  23. }  

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

[cpp]  view plain  copy
  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坐标转换

[cpp]  view plain  copy
  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火星坐标和地球坐标转换

[cpp]  view plain  copy
  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  墨卡托 坐标转换

[cpp]  view plain  copy
  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. }  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值