? ? ?火星坐標(biāo)?你在逗我玩兒探越?沒(méi)錯(cuò)狡赐,哈哈,在天朝總有一些詞我們要去學(xué)習(xí)的钦幔。
1.火星坐標(biāo)是個(gè)什么鬼枕屉?
? ? ?我們知道在具有地圖顯示的app里,一定會(huì)用到定位功能鲤氢,通常情況下搀擂,我們的手機(jī)都自帶GPS模塊,如果我們用GPS定位卷玉,你會(huì)發(fā)現(xiàn)哨颂,基本上都有一定的偏差。這是因?yàn)檎鲇诎踩紤]相种,沒(méi)有采用國(guó)際通用的WGS84坐標(biāo)系威恼,而是在標(biāo)準(zhǔn)坐標(biāo)系上加了一些偏移,這樣的坐標(biāo)系就被稱(chēng)為“火星坐標(biāo)系”。我們來(lái)詳細(xì)看一下在iOS地圖開(kāi)發(fā)中的這幾個(gè)名詞:
(1)地球坐標(biāo)(WGS84)
國(guó)際通用標(biāo)準(zhǔn)箫措,規(guī)定GPS 設(shè)備中取出的原始數(shù)據(jù)應(yīng)該是地球坐標(biāo)缭黔。
(2)火星坐標(biāo)(GCJ-02)
適用于國(guó)內(nèi),行貨iphone的 GPS模塊獲取的也是這個(gè)坐標(biāo)系蒂破。國(guó)內(nèi)地圖供應(yīng)商基本使用該坐標(biāo)系對(duì)位置進(jìn)行加密馏谨。
2.不同的坐標(biāo)系對(duì)工程師有什么影響?
? ? ?打個(gè)比方附迷,我們要開(kāi)發(fā)一款跑步的應(yīng)用惧互,比如咕咚,我們發(fā)現(xiàn)前幾個(gè)月運(yùn)動(dòng)的數(shù)據(jù)喇伯,在我們卸載重新安裝后仍然能展示出來(lái)喊儡。這里,咕咚將我們的運(yùn)動(dòng)記錄上傳到了服務(wù)器稻据,下次使用app的時(shí)候艾猜,會(huì)自動(dòng)將我們的舊數(shù)據(jù)同步到本地,避免數(shù)據(jù)丟失捻悯。
? ? ?那么在這種場(chǎng)景下匆赃,針對(duì)不同的平臺(tái),android和iOS今缚,如果雙方?jīng)]有約定好運(yùn)動(dòng)過(guò)程中GPS定位的點(diǎn)的格式算柳,就會(huì)出現(xiàn)偏移的現(xiàn)在,明明在android上面看的軌跡是一樣樣子姓言,在iOS上確發(fā)生了偏移瞬项,這種問(wèn)題就是不同坐標(biāo)系的典型影響,造成的直接后果就是用戶(hù)蒙圈了何荚,體驗(yàn)不太好囱淋。
3.iOS開(kāi)發(fā)中那些api會(huì)涉及?
? ? ?在使用iOS的定位功能主要使用CLLocationManager餐塘,從 CLLocationManager 取出來(lái)的經(jīng)緯度直接顯示到 MKMapView上妥衣,我們發(fā)現(xiàn)會(huì)有一定的偏差,這就是將地球坐標(biāo)(前者)直接塞到了火星坐標(biāo)(MKMapView)唠倦,導(dǎo)致軌跡點(diǎn)的偏移称鳞。
通過(guò)總結(jié)對(duì)比,我們發(fā)現(xiàn)iOS地圖稠鼻,以及國(guó)內(nèi)大部分地圖冈止,如高德、Gogole等顯示的經(jīng)緯度都是火星坐標(biāo)系候齿,除了百度使用自己的坐標(biāo)系熙暴,而google地圖則使用的是地球坐標(biāo)闺属。所以要兼顧android的地圖使用方式,將兩個(gè)平臺(tái)的坐標(biāo)進(jìn)行統(tǒng)一周霉。
4.平臺(tái)統(tǒng)一的方案
? ? ?為了確保不同的平臺(tái)掂器,最終顯示的效果是一致的,就需要二者上報(bào)到服務(wù)端的軌跡點(diǎn)的坐標(biāo)系是一致的俱箱。如果你的app只是在國(guó)內(nèi)使用国瓮,那情況相對(duì)簡(jiǎn)單,如果是國(guó)際化的app狞谱,則稍微復(fù)雜點(diǎn)乃摹。我們以前者為例,android使用高德地圖跟衅,采用的是火星坐標(biāo)系孵睬,iOS使用內(nèi)置地圖,同樣是高德地圖伶跷。
其中掰读,使用到的WGS84轉(zhuǎn)為GCJ-02的代碼實(shí)現(xiàn)如下,網(wǎng)上可以很容易搜索到:
+(CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLocation
{
CLLocationCoordinate2D adjustLoc;
if([selfisLocationOutOfChina:wgsLoc]){
adjustLoc = wgsLoc;
}else{
doubleadjustLat = [selftransformLatWithX:wgsLoc.longitude-105.0withY:wgsLoc.latitude-35.0];
doubleadjustLon = [selftransformLonWithX:wgsLoc.longitude-105.0withY:wgsLoc.latitude-35.0];
doubleradLat = wgsLoc.latitude/180.0* pi;
doublemagic = sin(radLat);
magic =1-ee*magic* magic;
doublesqrtMagic = sqrt(magic);
adjustLat = (adjustLat*180.0) / ((a* (1- ee)) / (magic* sqrtMagic) * pi);
adjustLon = (adjustLon*180.0) / (a /sqrtMagic* cos(radLat) * pi);
adjustLoc.latitude= wgsLoc.latitude+ adjustLat;
adjustLoc.longitude= wgsLoc.longitude+ adjustLon;
}
returnadjustLoc;
}
//判斷是不是在中國(guó)叭莫,如果app是國(guó)際版蹈集,可以用來(lái)判斷當(dāng)前定位是否在國(guó)內(nèi)
+(BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location
{
if(location.longitude<72.004|| location.longitude>137.8347|| location.latitude<0.8293|| location.latitude>55.8271)
returnYES;
returnNO;
}
+(double)transformLatWithX:(double)xwithY:(double)y
{
doublelat = -100.0+2.0* x +3.0* y +0.2*y* y +0.1*x* y +0.2* sqrt(abs(x));
lat += (20.0* sin(6.0*x* pi) +20.0*sin(2.0*x* pi)) *2.0/3.0;
lat += (20.0* sin(y* pi) +40.0* sin(y /3.0* pi)) *2.0/3.0;
lat += (160.0* sin(y /12.0* pi) +3320* sin(y* pi /30.0)) *2.0/3.0;
returnlat;
}
+(double)transformLonWithX:(double)xwithY:(double)y
{
doublelon =300.0+ x +2.0* y +0.1*x* x +0.1*x* y +0.1* sqrt(abs(x));
lon += (20.0* sin(6.0*x* pi) +20.0* sin(2.0*x* pi)) *2.0/3.0;
lon += (20.0* sin(x* pi) +40.0* sin(x /3.0* pi)) *2.0/3.0;
lon += (150.0* sin(x /12.0* pi) +300.0* sin(x /30.0* pi)) *2.0/3.0;
returnlon;
}
5.結(jié)語(yǔ)
? ? ? 通過(guò)以上的講解,想必大家對(duì)iOS定位功能的開(kāi)發(fā)已經(jīng)有了一定程度的理解食寡,多平臺(tái)的兼容性是我們開(kāi)發(fā)大型app的前提雾狈,方案一定要設(shè)計(jì)合理廓潜,提高容錯(cuò)能力抵皱,便于擴(kuò)充。在實(shí)際開(kāi)發(fā)中辩蛋,場(chǎng)景可能比這個(gè)更復(fù)雜呻畸,根據(jù)情況加以選擇,歡迎溝通交流悼院。
? ? ?如果您喜歡我們的文章伤为,點(diǎn)贊就好,您的認(rèn)可是我分享的最大動(dòng)力据途。