iOS开发火星坐标系与地球坐标系解析
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 plaincopy
//GCJ-02坐标转换成BD-09坐标
+(CLLocationCoordinate2D)MarsGS2BaiduGS:(CLLocationCoordinate2D)coordinate
{
doublex_pi=PI*3000.0/180.0;
doublex=coordinate.longitude,y=coordinate.latitude;
doublez=sqrt(x*x+y*y)+0.00002*sin(y*x_pi);
doubletheta=atan2(y,x)+0.000003*cos(x*x_pi);
doublebd_lon=z*cos(theta)+0.0065;
doublebd_lat=z*sin(theta)+0.006;
returnCLLocationCoordinate2DMake(bd_lat,bd_lon);
}
//BD-09坐标转换成GCJ-02坐标
+(CLLocationCoordinate2D)BaiduGS2MarsGS:(CLLocationCoordinate2D)coordinate
{
doublex_pi=PI*3000.0/180.0;
doublex=coordinate.longitude-0.0065,y=coordinate.latitude-0.006;
doublez=sqrt(x*x+y*y)-0.00002*sin(y*x_pi);
doubletheta=atan2(y,x)-0.000003*cos(x*x_pi);
doublegg_lon=z*cos(theta);
doublegg_lat=z*sin(theta);
returnCLLocationCoordinate2DMake(gg_lat,gg_lon);
}
2WGS-84(地球坐标系)和BD-09(百度坐标)转换
[cpp]view plaincopy
//WGS-84坐标转换成BD-09坐标
+(CLLocationCoordinate2D)WorldGS2BaiduGS:(CLLocationCoordinate2D)coordinate
{
CLLocationCoordinate2Dmars=[ALDGeocoderWorldGS2MarsGS:coordinate];
CLLocationCoordinate2Dbaidu=[ALDGeocoderMarsGS2BaiduGS:mars];
returnbaidu;
}
//BD-09坐标转换成WGS-84坐标
+(CLLocationCoordinate2D)BaiduGS2WorldGS:(CLLocationCoordinate2D)coordinate
{
CLLocationCoordinate2Dmars=[ALDGeocoderBaiduGS2MarsGS:coordinate];
CLLocationCoordinate2Dworld=[ALDGeocoderMarsGS2WorldGS:mars];
returnworld;
}
3.WGS-84和sogou坐标转换
[cpp]view plaincopy
//WGS-84坐标转换成Sogou坐标
+(CLLocationCoordinate2D)WorldGS2SogouGS:(CLLocationCoordinate2D)coordinate
{
constdoubleee=0.082271854224939184;
doublelon=coordinate.longitude;
doublelat=coordinate.latitude;
doubledlon=[ALDGeocoderrad:CLIP(lon,-360,360)];
doubledlat=[ALDGeocoderrad:CLIP(lat,-90,90)];
dlon=6378206.4*dlon;
doublesinphi=sin(dlat);
doubletemp1,temp2;
if((temp1=1.0+sinphi)==0.0){
dlat=-1000000000;
}elseif((temp2=1.0-sinphi)==0.0){
dlat=1000000000;
}else{
doubleesinphi=ee*sinphi;
dlat=3189103.2000000002*log((temp1/temp2)*pow((1.0-esinphi)/(1.0+esinphi),ee));
}
returnCLLocationCoordinate2DMake(dlat,dlon);
}
//Sogou坐标转换成WGS-84坐标
+(CLLocationCoordinate2D)SogouGS2WorldGS:(CLLocationCoordinate2D)coordinate
{
constdoubleee=1.5707963267948966;
constdoubleaa=0.0033938814110493522;
doublelon=coordinate.longitude;
doublelat=coordinate.latitude;
doubledlon=lon/6378206.4;
doubletemp=-lat/6378206.4;
doublechi;
if(temp<-307){
chi=ee;
}elseif(temp>308){
chi=-ee;
}else{
chi=ee-2*atan(exp(temp));
}
doublechi2=2*chi;
doublecoschi2=cos(chi2);
doubledlat=chi+sin(chi2)*(aa+coschi2*(1.3437644537757259E-005+coschi2*(7.2964865099246009E-008+coschi2*4.4551470401894685E-010)));
doublerlon=CLIP([ALDGeocoderdeg:dlon],-360,360);
doublerlat=CLIP([ALDGeocoderdeg:dlat],-90,90);
returnCLLocationCoordinate2DMake(rlat,rlon);
}
4火星坐标和地球坐标转换
[cpp]view plaincopy
//WorldGeodeticSystem==>MarsGeodeticSystem
+(CLLocationCoordinate2D)WorldGS2MarsGS:(CLLocationCoordinate2D)coordinate
{
//a=6378245.0,1/f=298.3
//b=a*(1-f)
//ee=(a^2-b^2)/a^2;
constdoublea=6378245.0;
constdoubleee=0.00669342162296594323;
if(outOfChina(coordinate.latitude,coordinate.longitude))
{
returncoordinate;
}
doublewgLat=coordinate.latitude;
doublewgLon=coordinate.longitude;
doubledLat=transformLat(wgLon-105.0,wgLat-35.0);
doubledLon=transformLon(wgLon-105.0,wgLat-35.0);
doubleradLat=wgLat/180.0*PI;
doublemagic=sin(radLat);
magic=1-ee*magic*magic;
doublesqrtMagic=sqrt(magic);
dLat=(dLat*180.0)/((a*(1-ee))/(magic*sqrtMagic)*PI);
dLon=(dLon*180.0)/(a/sqrtMagic*cos(radLat)*PI);
returnCLLocationCoordinate2DMake(wgLat+dLat,wgLon+dLon);
}
//MarsGeodeticSystem==>WorldGeodeticSystem
+(CLLocationCoordinate2D)MarsGS2WorldGS:(CLLocationCoordinate2D)coordinate
{
doublegLat=coordinate.latitude;
doublegLon=coordinate.longitude;
CLLocationCoordinate2DmarsCoor=[ALDGeocoderWorldGS2MarsGS:coordinate];
doubledLat=marsCoor.latitude-gLat;
doubledLon=marsCoor.longitude-gLon;
returnCLLocationCoordinate2DMake(gLat-dLat,gLon-dLon);
}
5WGS-84和墨卡托坐标转换
[cpp]view plaincopy
//WGS-84坐标转换成墨卡托坐标
+(CLLocationCoordinate2D)WorldGS2Mercator:(CLLocationCoordinate2D)coordinate
{
doublelon=coordinate.longitude*20037508.34/180;
doublelat=log(tan((90+coordinate.latitude)*M_PI/360))/(M_PI/180);
lat=lat*20037508.34/180;
returnCLLocationCoordinate2DMake(lat,lon);
}
//墨卡托坐标转换成WGS-84坐标
+(CLLocationCoordinate2D)Mercator2WorldGS:(CLLocationCoordinate2D)mercator
{
doublelon=mercator.longitude/20037508.34*180;
doublelat=mercator.latitude/20037508.34*180;
lat=180/M_PI*(2*atan(exp(lat*M_PI/180))-M_PI/2);
returnCLLocationCoordinate2DMake(lat,lon);
}
下一篇: C++ Virtual关键字详解