iOS 火星坐标系 与 地球坐标系
阅读原文时间:2021年04月21日阅读:1

在开发过程中,遇到一个问题,安卓和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. // BD-09 坐标转换成 GCJ-02 坐标

  13. + (CLLocationCoordinate2D)BaiduGS2MarsGS:(CLLocationCoordinate2D)coordinate

  14. {

  15. double x_pi = PI * 3000.0 / 180.0;

  16. double x = coordinate.longitude - 0.0065, y = coordinate.latitude - 0.006;

  17. double z = sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi);

  18. double theta = atan2(y, x) - 0.000003 * cos(x * x_pi);

  19. double gg_lon = z * cos(theta);

  20. double gg_lat = z * sin(theta);

  21. return CLLocationCoordinate2DMake(gg_lat, gg_lon);

  22. }

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. // BD-09 坐标转换成 WGS-84 坐标

  9. + (CLLocationCoordinate2D)BaiduGS2WorldGS:(CLLocationCoordinate2D)coordinate

  10. {

  11. CLLocationCoordinate2D mars = [ALDGeocoder BaiduGS2MarsGS:coordinate];

  12. CLLocationCoordinate2D world = [ALDGeocoder MarsGS2WorldGS:mars];

  13. return world;

  14. }

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. // Sogou 坐标转换成 WGS-84 坐标

  23. + (CLLocationCoordinate2D)SogouGS2WorldGS:(CLLocationCoordinate2D)coordinate

  24. {

  25. const double ee = 1.5707963267948966;

  26. const double aa = 0.0033938814110493522;

  27. double lon = coordinate.longitude;

  28. double lat = coordinate.latitude;

  29. double dlon = lon / 6378206.4;

  30. double temp = -lat / 6378206.4;

  31. double chi;

  32. if(temp < -307){

  33. chi = ee;

  34. }else if(temp > 308){

  35. chi = -ee;

  36. }else{

  37. chi = ee - 2 * atan(exp(temp));

  38. }

  39. double chi2 = 2 * chi;

  40. double coschi2 = cos(chi2);

  41. double dlat = chi + sin(chi2) * (aa + coschi2 * (1.3437644537757259E-005 + coschi2 * (7.2964865099246009E-008 + coschi2 * 4.4551470401894685E-010)));

  42. double rlon = CLIP([ALDGeocoder deg:dlon], -360, 360);

  43. double rlat = CLIP([ALDGeocoder deg:dlat], -90, 90);

  44. return CLLocationCoordinate2DMake(rlat, rlon);

  45. }

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. if (outOfChina(coordinate.latitude, coordinate.longitude))

  10. {

  11. return coordinate;

  12. }

  13. double wgLat = coordinate.latitude;

  14. double wgLon = coordinate.longitude;

  15. double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);

  16. double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);

  17. double radLat = wgLat / 180.0 * PI;

  18. double magic = sin(radLat);

  19. magic = 1 - ee * magic * magic;

  20. double sqrtMagic = sqrt(magic);

  21. dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);

  22. dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * PI);

  23. return CLLocationCoordinate2DMake(wgLat + dLat, wgLon + dLon);

  24. }

  25. // Mars Geodetic System ==> World Geodetic System

  26. + (CLLocationCoordinate2D)MarsGS2WorldGS:(CLLocationCoordinate2D)coordinate

  27. {

  28. double gLat = coordinate.latitude;

  29. double gLon = coordinate.longitude;

  30. CLLocationCoordinate2D marsCoor = [ALDGeocoder WorldGS2MarsGS:coordinate];

  31. double dLat = marsCoor.latitude - gLat;

  32. double dLon = marsCoor.longitude - gLon;

  33. return CLLocationCoordinate2DMake(gLat - dLat, gLon - dLon);

  34. }

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. //墨卡托 坐标转换成 WGS-84 坐标

  10. + (CLLocationCoordinate2D)Mercator2WorldGS:(CLLocationCoordinate2D)mercator

  11. {

  12. double lon = mercator.longitude/20037508.34*180;

  13. double lat = mercator.latitude/20037508.34*180;

  14. lat = 180/M_PI*(2*atan(exp(lat*M_PI/180))-M_PI/2);

  15. return CLLocationCoordinate2DMake(lat, lon);

  16. }

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器