最近一直研究地图,包括高德、google、百度、google earth地图,经常使用地图的也会发现,其实高德地图、百度地图、google地图和GPS获取的坐标差异很大,那怎么转换呢,我们一步一步分析:
坐标体系
1、GPS,WGS-84,原始坐标体系。一般用国际标准的GPS记录仪记录下来的坐标,都是GPS的坐标。很可惜,在中国,任何一个地图产品都不允许使用GPS坐标,据说是为了保密。
2、 GCJ-02,国测局02年发布的坐标体系。又称“火星坐标”。在中国,必须至少使用GCJ-02的坐标体系。比如谷歌,腾讯,高德都在用这个坐标体系。GCJ-02也是国内最广泛使用的坐标体系。
3、其他坐标体系。一般都是由GCJ-02进过偏移算法得到的。这种体系就根据每个公司的不同,坐标体系都不一样了。比如,百度和搜狗就使用自己的坐标体系,与其他坐标体系不兼容
注解:所有坐标系的原点都是非洲
从上面三种坐标系我们就可以大概知道为啥地图之前和google earth地图有差异(google earth地图和GPS获取的坐标一致)
在各种web端平台,或者高德、腾讯、百度上取到的坐标,都不是GPS坐标,都是GCJ-02坐标,或者自己的偏移坐标系。
比如,你在谷歌地图API,高德地图API,腾讯地图API上取到的,都是GCJ-02坐标,他们三家都是通用的,也适用于大部分地图API产品,以及他们的地图产品。
例外,百度API上取到的,是BD-09坐标,只适用于百度地图相关产品。
例外,搜狗API上取到的,是搜狗坐标,只适用于搜狗地图相关产品。
例外,谷歌地球,google earth上取到的,是GPS坐标,而且是度分秒形式的经纬度坐标。在国内不允许使用。必须转换为GCJ-02坐标。
所以接下来我们就看看怎么将GCJ-02坐标转换为GPS的WGS-84坐标:
static double pointA = 6378245.0;
static double pi = 3.14159265358979324;
static double ee = 0.00669342162296594323;
- (CLLocationCoordinate2D )changePointToWGS84PointwithLatitude:(double)latitude longitude:(double)longitude
{
CLLocationCoordinate2D dev = [self calDevWithwgLon:longitude wglat:latitude];
double retLat = latitude - dev.latitude;
double retLon = longitude - dev.longitude;
dev = [self calDevWithwgLon:retLon wglat:retLat];
retLat = latitude - dev.latitude;
retLon = longitude - dev.longitude;
return CLLocationCoordinate2DMake(retLat, retLon);
}
- (CLLocationCoordinate2D )calDevWithwgLon:(double)wglon wglat:(double)wglat
{
if ([self isOutOfChinaWithlat:wglat lon:wglon]) {
return CLLocationCoordinate2DMake(0, 0);
}
double dLat = [self calLatWithX:wglon - 105.0 Y:wglat - 35.0];
double dLon = [self calLonWithX:wglon - 105.0 Y:wglat - 35.0];
double radLat = wglat / 180.0 * pi;
double magic = sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = sqrt(magic);
dLat = (dLat * 180.0) / ((pointA * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (pointA / sqrtMagic * cos(radLat) * pi);
return CLLocationCoordinate2DMake(dLat, dLon);
}
- (BOOL)isOutOfChinaWithlat:(double)lat lon:(double)lon
{
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
- (double)calLatWithX:(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(fabs(x));
ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * sin(y * pi) + 40.0 * sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * sin(y / 12.0 * pi) + 320 * sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
- (double)calLonWithX:(double)x Y:(double)y
{
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x));
ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * sin(x * pi) + 40.0 * sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * sin(x / 12.0 * pi) + 300.0 * sin(x / 30.0 * pi)) * 2.0 / 3.0;
return ret;
}
OK了、这样就成功将GCJ-02坐标转换为WGS-84坐标了,顺便附上查询坐标验证网址,大家可以试试:http://www.gpsspg.com/maps.htm
如有错误麻烦指点一二。对于WGS-84转换为GCJ-02将在之后更新。