2013年01月31日 ⁄ 綜合 ⁄ 共 2595字 ⁄ 字號 小 中 大 ⁄ 評論關閉html
今天在一個項目中須要用到地球座標系到火星座標系的轉換,找了好幾種實現方法,但都沒法在iOS6以上的系統中使用,最後找到了一個C#的轉換算法,對照着寫了一個iOS版的,在這裏分享給你們。git
地球座標和火星座標的具體含義能夠見:http://blog.sina.com.cn/s/blog_7581a4c301015230.html算法
目前網上的方法主要有如下幾種:數據庫
1.在iOS4.3以前的系統上經過私有類MKLocationManager中的_applyChinaLocationShift來轉換地球座標到火星座標。這種方法有兩個問題,一個是調用了私有api,另外一個是在iOS5以後的系統不能用了。api
2.利用MKMapView中的isShowUserLocation進行定位,這種方法也有兩個問題,一個是必需要建立MKMapView才行,二是沒法實現後臺定位。app
3.利用MapABC API中的GPSToOffSetByPoint:方法進行座標轉換,本人並無對這種方法進行嘗試,由於實現起來比較麻煩,還得申請API Key。spa
4.對地球座標系與火星座標系創建一一映射關係,並將這個關係存到數據庫中,經過數據庫進行轉換。這種方法的問題是數據庫體積較大,不適用於移動客戶端程序。.net
5.利用高德、百度地圖提供的在線api進行轉換,這種方法的問題是不能離線進行轉換,實用性不強。code
6.利用已有的算法將地球座標系轉換到火星座標系orm
本人最後採用的是第六種方法,參考的C#算法連接以下:https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936
轉換獲得的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 * 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; }
將以上代碼放到任意一個類中,使用靜態方法transformToMars:對地球座標進行轉換便可。
如下爲最後轉換的結果:
mapkit獲得的座標:40.006498, 116.328022 CLLocationManager獲得的座標:40.005196, 116.321890 算法轉換出來的座標:40.006500, 116.328023
由以上結果能夠看出該算法的精度比較高,偏差在10米以內。
若是你們以爲對本身有幫助的話,還但願能幫頂一下,謝謝:)
我的博客:http://blog.csdn.net/zhaoxy2850
本文地址:http://blog.csdn.net/zhaoxy_thu/article/details/17033347
轉載請註明出處,謝謝!