最近在做一個(gè)地圖定位的功能,遇到一個(gè)問(wèn)題:就是定位的坐標(biāo)始終有偏差大概幾百米距離。
查閱資料了解到是坐標(biāo)系問(wèn)題。目前常見(jiàn)的坐標(biāo)系有三種:地球坐標(biāo)(WGS84,國(guó)際公認(rèn)坐標(biāo)),火星坐標(biāo)(GCJ02,國(guó)家標(biāo)準(zhǔn),適用于高德百度地圖大陸+港澳部分、Google地圖大陸部分),百度坐標(biāo)(BD09,適用于百度地圖大陸+港澳臺(tái)部分)。坐標(biāo)系需要和地圖關(guān)連才有意義,只有正確匹配地圖坐標(biāo)系的坐標(biāo)才能在該地圖上完美標(biāo)識(shí)位置,否則就會(huì)存在偏移。
iOS系統(tǒng)上通過(guò)定位服務(wù)CLLocation相關(guān)接口獲取定位信息時(shí),獲取的經(jīng)緯度坐標(biāo)系是WGS84地球坐標(biāo),如果直接將該坐標(biāo)系在iOS系統(tǒng)地圖中打點(diǎn),會(huì)發(fā)現(xiàn)存在偏移,因?yàn)閕OS系統(tǒng)地圖查看國(guó)內(nèi)時(shí)使用的是高德地圖數(shù)據(jù),因此只接受GCJ02火星坐標(biāo)。所以如果我們是直接使用系統(tǒng)的定位服務(wù),而不是第三方SDK的話,就需要將WGS84編碼轉(zhuǎn)成GCJ02就好了
const double a = 6378245.0;
const double ee = 0.00669342162296594323;
const double pi = 3.14159265358979324;
+ (CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc {
CLLocationCoordinate2D adjustLoc;
if ([self isLocationOutOfChina:wgsLoc]) {
adjustLoc = wgsLoc;
} else {
double adjustLat = [self transformLatWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0];
double adjustLon = [self transformLonWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0];
double radLat = wgsLoc.latitude / 180.0 * pi;
double magic = sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = 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;
}
return adjustLoc;
}
// 判斷是不是在中國(guó)
+ (BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location {
if (location.longitude < 72.004 || location.longitude > 137.8347 || location.latitude < 0.8293 || location.latitude > 55.8271) {
return YES;
}
return NO;
}
+ (double)transformLatWithX:(double)x withY:(double)y {
double lat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(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;
return lat;
}
+ (double)transformLonWithX:(double)x withY:(double)y {
double lon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(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;
return lon;
}
參考大神文章 http://blog.csdn.net/zhengang007/article/details/52858198