iOS開發火星座標系與地球座標系解析,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);
}