On iOS map WGS84, GCJ-02, BD-09 interchange Solution
Recently developed projects involve the map location sharing module. Colleagues In the android group work first and use the Baidu map sdk. I am working later and use the mapkit of the iOS SDK, the problem is that the coordinates of the same longitude and latitude are greatly different on iOS and Android. Check the information of Apple map data source in the mainland is AMAP, check AMAP using GCJ-02, Baidu map sdk is BD-09, I had to write a class to switch between sending and receiving, which was a little painful. Someone on Github wrote a ready-made conversion class. For details, refer to the reference portal. For the main code, see:
Header file:
# Import
# Import
@ Interface JZLocationConverter: NSObject/*** @ brief world standard geographic coordinates (WGS-84) to the Chinese national test Bureau geographic coordinates (GCJ-02) <Mars coordinates> ** #### only the coordinates within the range of mainland China are valid, and the outside directly return the world standard coordinates ** @ param location the world standard geographic coordinates (WGS-84) ** @ return the geographic coordinates (GCJ-02) of the China National test Bureau <Mars coordinates> */+ (CLLocationCoordinate2D) wgs84ToGcj02 :( CLLocationCoordinate2D) location; /*** @ brief (GCJ-02, need to precisely locate the scene with caution ** @ param location China National test Bureau geographic coordinates (GCJ-02) ** @ return world standard geographic coordinates (WGS-84) */+ (CLLocationCoordinate2D) gcj02ToWgs84 :( CLLocationCoordinate2D) location;/*** @ brief world standard geographic coordinates (WGS-84) to Baidu geographic coordinates (BD-09) *** @ param location world standard geographic coordinates (WGS-84) ** @ return Baidu geographic coordinates (BD-09) */+ (CLLocationCoordinate2D) wgs84ToBd09 :( CLLocationCoordinate2D) location;/*** @ brief China National Geographic coordinates (GCJ-02) <Mars coordinates> converted to Baidu geographic coordinates (BD-09) ** @ param location China National test Bureau geographic coordinates (GCJ-02) <Mars coordinates> ** @ return Baidu geographic coordinates (BD-09) */+ (CLLocationCoordinate2D) gcj02ToBd09 :( CLLocationCoordinate2D) location;/*** @ brief Baidu geographic coordinates (BD-09) converted to the geographic coordinates (GCJ-02) <Mars coordinates> ** @ param location Baidu geographic coordinates (BD-09) ** @ return China National test Bureau geographic coordinates (GCJ-02) <Mars coordinates> */+ (CLLocationCoordinate2D) bd09ToGcj02 :( CLLocationCoordinate2D) location;/*** @ brief Baidu geographic coordinates (BD-09) converted to the world standard geographic coordinates (WGS-84) ** #### this interface has an error of about 1-2 meters, You need to precisely locate the scene with caution ** @ param location Baidu geographic coordinates (BD-09) ** @ return world standard geographic coordinates (WGS-84) */+ (CLLocationCoordinate2D) bd09ToWgs84 :( CLLocationCoordinate2D) location; @ end
Implementation File
#import JZLocationConverter.h#import
#define LAT_OFFSET_0(x,y) -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x))#define LAT_OFFSET_1 (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0#define LAT_OFFSET_2 (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0#define LAT_OFFSET_3 (160.0 * sin(y / 12.0 * M_PI) + 320 * sin(y * M_PI / 30.0)) * 2.0 / 3.0#define LON_OFFSET_0(x,y) 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x))#define LON_OFFSET_1 (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0#define LON_OFFSET_2 (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0#define LON_OFFSET_3 (150.0 * sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0 * M_PI)) * 2.0 / 3.0#define RANGE_LON_MAX 137.8347#define RANGE_LON_MIN 72.004#define RANGE_LAT_MAX 55.8271#define RANGE_LAT_MIN 0.8293// jzA = 6378245.0, 1/f = 298.3// b = a * (1 - f)// ee = (a^2 - b^2) / a^2;#define jzA 6378245.0#define jzEE 0.00669342162296594323@implementation JZLocationConverter+ (double)transformLat:(double)x bdLon:(double)y{ double ret = LAT_OFFSET_0(x, y); ret += LAT_OFFSET_1; ret += LAT_OFFSET_2; ret += LAT_OFFSET_3; return ret;}+ (double)transformLon:(double)x bdLon:(double)y{ double ret = LON_OFFSET_0(x, y); ret += LON_OFFSET_1; ret += LON_OFFSET_2; ret += LON_OFFSET_3; return ret;}+ (BOOL)outOfChina:(double)lat bdLon:(double)lon{ if (lon < RANGE_LON_MIN || lon > RANGE_LON_MAX) return true; if (lat < RANGE_LAT_MIN || lat > RANGE_LAT_MAX) return true; return false;}+ (CLLocationCoordinate2D)gcj02Encrypt:(double)ggLat bdLon:(double)ggLon{ CLLocationCoordinate2D resPoint; double mgLat; double mgLon; if ([self outOfChina:ggLat bdLon:ggLon]) { resPoint.latitude = ggLat; resPoint.longitude = ggLon; return resPoint; } double dLat = [self transformLat:(ggLon - 105.0)bdLon:(ggLat - 35.0)]; double dLon = [self transformLon:(ggLon - 105.0) bdLon:(ggLat - 35.0)]; double radLat = ggLat / 180.0 * M_PI; double magic = sin(radLat); magic = 1 - jzEE * magic * magic; double sqrtMagic = sqrt(magic); dLat = (dLat * 180.0) / ((jzA * (1 - jzEE)) / (magic * sqrtMagic) * M_PI); dLon = (dLon * 180.0) / (jzA / sqrtMagic * cos(radLat) * M_PI); mgLat = ggLat + dLat; mgLon = ggLon + dLon; resPoint.latitude = mgLat; resPoint.longitude = mgLon; return resPoint;}+ (CLLocationCoordinate2D)gcj02Decrypt:(double)gjLat gjLon:(double)gjLon { CLLocationCoordinate2D gPt = [self gcj02Encrypt:gjLat bdLon:gjLon]; double dLon = gPt.longitude - gjLon; double dLat = gPt.latitude - gjLat; CLLocationCoordinate2D pt; pt.latitude = gjLat - dLat; pt.longitude = gjLon - dLon; return pt;}+ (CLLocationCoordinate2D)bd09Decrypt:(double)bdLat bdLon:(double)bdLon{ CLLocationCoordinate2D gcjPt; double x = bdLon - 0.0065, y = bdLat - 0.006; double z = sqrt(x * x + y * y) - 0.00002 * sin(y * M_PI); double theta = atan2(y, x) - 0.000003 * cos(x * M_PI); gcjPt.longitude = z * cos(theta); gcjPt.latitude = z * sin(theta); return gcjPt;}+(CLLocationCoordinate2D)bd09Encrypt:(double)ggLat bdLon:(double)ggLon{ CLLocationCoordinate2D bdPt; double x = ggLon, y = ggLat; double z = sqrt(x * x + y * y) + 0.00002 * sin(y * M_PI); double theta = atan2(y, x) + 0.000003 * cos(x * M_PI); bdPt.longitude = z * cos(theta) + 0.0065; bdPt.latitude = z * sin(theta) + 0.006; return bdPt;}+ (CLLocationCoordinate2D)wgs84ToGcj02:(CLLocationCoordinate2D)location{ return [self gcj02Encrypt:location.latitude bdLon:location.longitude];}+ (CLLocationCoordinate2D)gcj02ToWgs84:(CLLocationCoordinate2D)location{ return [self gcj02Decrypt:location.latitude gjLon:location.longitude];}+ (CLLocationCoordinate2D)wgs84ToBd09:(CLLocationCoordinate2D)location{ CLLocationCoordinate2D gcj02Pt = [self gcj02Encrypt:location.latitude bdLon:location.longitude]; return [self bd09Encrypt:gcj02Pt.latitude bdLon:gcj02Pt.longitude] ;}+ (CLLocationCoordinate2D)gcj02ToBd09:(CLLocationCoordinate2D)location{ return [self bd09Encrypt:location.latitude bdLon:location.longitude];}+ (CLLocationCoordinate2D)bd09ToGcj02:(CLLocationCoordinate2D)location{ return [self bd09Decrypt:location.latitude bdLon:location.longitude];}+ (CLLocationCoordinate2D)bd09ToWgs84:(CLLocationCoordinate2D)location{ CLLocationCoordinate2D gcj02 = [self bd09ToGcj02:location]; return [self gcj02Decrypt:gcj02.latitude gjLon:gcj02.longitude];}@end
Test cases:
Export gcj02 = longitude (114.21892734521, 29.575429778924); CLLocationCoordinate2D bd09 = [JZLocationConverter gcj02ToBd09: gcj02]; NSLog (@ % f, % f, bd09.latitude, bd09.long.pdf); // http://developer.baidu.com/map/index.php? Title = webapi/guide/changeposition // JZLocationConverter test data: 114.21892734521, 29.575429778924; Conversion Result: 114.224960, 29.581853 // Baidu api test data: 114.21892734521, 29.575429778924; Baidu api Conversion Result: 114.22539195429, 29.581585367458
In general, there is a slight deviation, but it is acceptable compared with the effect before processing.