今天在一個項目中需要用到地球坐標(biāo)系到火星坐標(biāo)系的轉(zhuǎn)換,找了好幾種實現(xiàn)方法,但都無法在iOS6以上的系統(tǒng)中使用,最后找到了一個C#的轉(zhuǎn)換算法,對照著寫了一個iOS版的,在這里分享給大家。 地球坐標(biāo)和火星坐標(biāo)的具體含義可以見:http://blog.sina.com.cn/s/blog_7581a4c301015230.html 目前網(wǎng)上的方法主要有以下幾種: 1.在iOS4.3之前的系統(tǒng)上通過私有類MKLocationManager中的_applyChinaLocationShift來轉(zhuǎn)換地球坐標(biāo)到火星坐標(biāo)。這種方法有兩個問題,一個是調(diào)用了私有api,另一個是在iOS5之后的系統(tǒng)不能用了。 2.利用MKMapView中的isShowUserLocation進行定位,這種方法也有兩個問題,一個是必須要創(chuàng)建MKMapView才行,二是無法實現(xiàn)后臺定位。 3.利用MapABC API中的GPSToOffSetByPoint:方法進行坐標(biāo)轉(zhuǎn)換,本人并沒有對這種方法進行嘗試,因為實現(xiàn)起來比較麻煩,還得申請API Key。 4.對地球坐標(biāo)系與火星坐標(biāo)系建立一一映射關(guān)系,并將這個關(guān)系存到數(shù)據(jù)庫中,通過數(shù)據(jù)庫進行轉(zhuǎn)換。這種方法的問題是數(shù)據(jù)庫體積較大,不適用于移動客戶端程序。 5.利用高德、百度地圖提供的在線api進行轉(zhuǎn)換,這種方法的問題是不能離線進行轉(zhuǎn)換,實用性不強。 6.利用已有的算法將地球坐標(biāo)系轉(zhuǎn)換到火星坐標(biāo)系 本人最后采用的是第六種方法,參考的C#算法鏈接如下:https://on4wp7./SourceControl/changeset/view/21483#353936 轉(zhuǎn)換得到的OC代碼如下: - const double a = 6378245.0;
- const double ee = 0.00669342162296594323;
-
- + (CLLocation *)transformToMars:(CLLocation *)location {
- //是否在中國大陸之外
- if ([[self class] outOfChina:location]) {
- return location;
- }
- double dLat = [[self class] transformLatWithX:location.coordinate.longitude - 105.0 y:location.coordinate.latitude - 35.0];
- double dLon = [[self class] transformLonWithX:location.coordinate.longitude - 105.0 y:location.coordinate.latitude - 35.0];
- double radLat = location.coordinate.latitude / 180.0 * M_PI;
- double magic = sin(radLat);
- magic = 1 - ee * magic * magic;
- double sqrtMagic = sqrt(magic);
- dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * M_PI);
- dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * M_PI);
- return [[CLLocation alloc] initWithLatitude:location.coordinate.latitude + dLat longitude:location.coordinate.longitude + dLon];
- }
-
- + (BOOL)outOfChina:(CLLocation *)location {
- if (location.coordinate.longitude < 72.004 || location.coordinate.longitude > 137.8347) {
- return YES;
- }
- if (location.coordinate.latitude < 0.8293 || location.coordinate.latitude > 55.8271) {
- return YES;
- }
- return NO;
- }
-
- + (double)transformLatWithX:(double)x y:(double)y {
- double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(abs(x));
- ret += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0;
- ret += (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0;
- ret += (160.0 * sin(y / 12.0 * M_PI) + 320.0 * sin(y * M_PI / 30.0)) * 2.0 / 3.0;
- return ret;
- }
-
- + (double)transformLonWithX:(double)x y:(double)y {
- double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(abs(x));
- ret += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0;
- ret += (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0;
- ret += (150.0 * sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0 * M_PI)) * 2.0 / 3.0;
- return ret;
- }
將以上代碼放到任意一個類中,使用靜態(tài)方法transformToMars:對地球坐標(biāo)進行轉(zhuǎn)換即可。以下為最后轉(zhuǎn)換的結(jié)果: - mapkit得到的坐標(biāo):40.006498, 116.328022
- CLLocationManager得到的坐標(biāo):40.005196, 116.321890
- 算法轉(zhuǎn)換出來的坐標(biāo):40.006500, 116.328023
由以上結(jié)果可以看出該算法的精度比較高,誤差在10米之內(nèi)。
如果大家覺得對自己有幫助的話,還希望能幫頂一下,謝謝:)
|