IOS7 WGS-84轉(zhuǎn)GCJ-02(火星坐標)
CLLocationManager類可以實時的獲得我們位置的經(jīng)緯度拂封,并且可以通過經(jīng)緯度在MapView上定位:
[objc]view plaincopy
//創(chuàng)建CLLocationManager對象
CLLocationManager*locationManager?=?[[CLLocationManageralloc]init];
//設(shè)置委托對象為自己
[locationManagersetDelegate:self];
//要求CLLocationManager對象返回全部結(jié)果
[locationManagersetDistanceFilter:kCLDistanceFilterNone];
//要求CLLocationManager對象的返回結(jié)果盡可能的精準
[locationManagersetDesiredAccuracy:kCLLocationAccuracyBest];
//要求CLLocationManager對象開始工作鹦蠕,定位設(shè)備位置
[locationManagerstartUpdatingLocation];
通過下面的CLLocationManager的委托方法可以得到或者更新locationManager的經(jīng)緯度,并且顯示到MapView上
[objc]view plaincopy
//CLLocationManager委托方法
-(void)locationManager:(CLLocationManager*)managerdidUpdateLocations:(NSArray*)locations{
//得到newLocation
CLLocation*loc?=?[locationsobjectAtIndex:0];
}
但是對于國內(nèi)地圖而言钟病,使用LocationManager定位所獲得經(jīng)緯度萧恕,是有一段較大距離的偏移的。
這是為什么呢肠阱?票唆?這幾天一直在查這方面的資料,各種google屹徘、baidu論壇里給出的答案也各有不同:
wifi 熱點 基站 gps等等所導(dǎo)致的都有惰说,最后查找還是找到了問題所在,原來國內(nèi)地圖使用的坐標系統(tǒng)是GCJ-02而ios sdk中所用到的是國際標準的坐標系統(tǒng)WGS-84缘回。
因為國內(nèi)使用的是加密后的坐標系GCJ-02就是網(wǎng)絡(luò)上叫的火星坐標典挑。
locationManager就是因為得到的是火星坐標偏移后的經(jīng)緯度酥宴,所以導(dǎo)致在MapView上有很大的偏差,而在MKMapView上通過定位自己位置所獲得的經(jīng)緯度有是準確您觉,因為apple已經(jīng)對國內(nèi)地圖做了偏移優(yōu)化拙寡。
1、那么臨時的解決方法:想要獲得自己準確的經(jīng)緯度可以直接通過MKMapView中對自身定位來獲得:
[objc]view plaincopy
//定義一個MKMapView?并且調(diào)用setShowUserLocation:YES來獲得自身的位置
[self.mapViewsetShowsUserLocation:YES];
//如果不想要顯示這個MKMapView就將其隱藏
[self.mapViewsetHidden:YES];
然后通過MKMapView的委托方法來獲取準確的經(jīng)緯度:
[objc]view plaincopy
-(void)mapView:(MKMapView*)mapViewdidUpdateUserLocation:(MKUserLocation*)userLocation{
CLLocationCoordinate2D?coord?=?[userLocationcoordinate];
NSLog(@"經(jīng)度:%f,緯度:%f",coord.latitude,coord.longitude);
}
這個方法雖然簡單琳水,也可以實時的獲取自己的位置而且基本上都是準確的位置肆糕,但是也就無法使用locationManager中的一些功能了。
那么有沒有更好的解方法可以讓我們在火星坐標上使用locationManager來獲得準確的位置呢在孝? 看了幾篇博客給出的答案是相似的诚啃,就是調(diào)用apple的私有模塊類中得方法來對經(jīng)緯度做一個偏移修正:
http://blog.csdn.net/zhibudefeng/article/details/8495837
http://yach.me/blog/2011/11/09/huo-xing-zuo-biao-xi-wen-ti-zai-iosxia-de-xiu/
上面兩篇文章中都提到了使用apple的私有模塊MKLocationManager來修正偏移,不過遺憾的是如果使用了私有模塊會導(dǎo)致AppStore審核失敗,但是幸運的是這種方式只能在IOS5以前的系統(tǒng)中使用私沮。始赎。。。造垛。魔招。至少今天我們不用擔心該不該使用這個方式。
接下來就是正題了:最后我找到了一份android的?火星坐標轉(zhuǎn)換的算法五辽,然后自己改寫成了以下將WGS-84坐標系統(tǒng)轉(zhuǎn)為GCJ-02的Objective-C代碼办斑,這樣就能方便的使用CLLocationManager這個類了。
2杆逗、將WGS-84轉(zhuǎn)為GCJ-02(火星坐標):
新建一個類“WGS84TOGCJ02”乡翅,在.h頭文件中定義:
[objc]view plaincopy
//??Copyright?(c)?2013年?swinglife.?All?rights?reserved.
//
#import?
#import?
@interfaceWGS84TOGCJ02:?NSObject
//判斷是否已經(jīng)超出中國范圍
+(BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location;
//轉(zhuǎn)GCJ-02
+(CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc;
@end
在WGS84TOGCJ02.m文件中:
[objc]view plaincopy
//??Copyright?(c)?2013年?swinglife.?All?rights?reserved.
//
#import?"WGS84TOGCJ02.h"
constdoublea?=6378245.0;
constdoubleee?=0.00669342162296594323;
constdoublepi?=3.14159265358979324;
@implementationWGS84TOGCJ02
+(CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc
{
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;
}
//判斷是不是在中國
+(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;
}
@end
最后我們通過判斷isLocationOutOfChina 然后調(diào)用transformLatWithX方法就能獲取轉(zhuǎn)換后的 CLLocationCoordinate2D結(jié)構(gòu)類型
[objc]view plaincopy
//CLLocationManager委托方法
-(void)locationManager:(CLLocationManager*)managerdidUpdateLocations:(NSArray*)locations{
//得到newLocation
CLLocation*loc?=?[locationsobjectAtIndex:0];
//判斷是不是屬于國內(nèi)范圍
if(![WGS84TOGCJ02isLocationOutOfChina:[loccoordinate]])?{
//轉(zhuǎn)換后的coord
CLLocationCoordinate2D?coord?=?[WGS84TOGCJ02transformFromWGSToGCJ:[loccoordinate]];
}