什么是地图坐标系转换?
目前常用的地图坐标系有多种标准,几家主流地图(如百度地图,高德地图和QQ地图等)使用的坐标系标准也各不相同。
假如您有GPS坐标,想在百度地图上显示;或者有百度地图的坐标,但想在微信地图上显示,这时就需要使用一些算法或通过官方的API来转换坐标,在目标地图上正确显示。
主流地图坐标系说明
1、WGS84坐标系
WGS-84坐标系为一种大地坐标系(地心坐标系,GPS原始坐标体系),也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。对应工
具“输入坐标类型”里的GPS坐标。
2、GCJ02坐标系
GCJ-02坐标系:国测局坐标,又名火星坐标系。
国测局02年发布的坐标体系,它是一种对经纬度数据的加密算法,即加入随机的偏差。
是国内最广泛使用的坐标体系,高德地图、腾讯地图都使用它
3、BD09坐标系
为百度地图坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标。
4、CGCS2000坐标系
国家大地坐标系。该坐标系是通过中国GPS 连续运行基准站、 空间大地控制网以及天文大地网与空间地网联合平差建立的地心大地坐标系统。
说明下、百度的地图加密原始gps地理坐标是这样的:百度地图加密的是 火星坐标系 (GCJ-02),而GCJ-02加密的是原始gps坐标系。所以从原始gps坐标,到百度地图坐标,顺序是WGS-84 --> GCJ-02 --> BD-09
public class BdMapUtil { /** 圆周率 */ public static double pi = 3.1415926535897932384626; public static double a = 6378245.0; public static double ee = 0.00669342162296594323; private static double x_pi = 3.14159265358979324 * 3000.0 / 180.0; /** * 得到百度地图经纬度 * * @author zr * @date 2019-09-09 * @param lat WGS-84 gps的纬度 * @param lon WGS-84 gps的经度 * @return com.construn.vehicle.message.util.Gps */ public static Gps getBd09( double lat, double lon) { //得到火星坐标经纬度 Gps gps = gps84ToGcj02(lat, lon); if (gps == null ) { return null ; } //得到百度坐标经纬度 return gcj02ToBd09(gps.getWgLat(), gps.getWgLon()); } /** * 火星坐标系 (GCJ-02)转百度地图坐标系 * * @author zr * @date 2019-09-09 * @param * @param gg_lat * @param gg_lon * @return void */ private static Gps gcj02ToBd09( double gg_lat, double gg_lon) { double x = gg_lon, y = gg_lat; double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * x_pi); double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * x_pi); double bd_lon = z * Math.Cos(theta) + 0.0065; double bd_lat = z * Math.Sin(theta) + 0.006; return new Gps(bd_lat, bd_lon); } /** * 84 to 火星坐标系 (GCJ-02) * * @author zr * @date 2019-09-09 * @param * @param lat * @param lon * @return void */ private static Gps gps84ToGcj02( double lat, double lon) { if (outOfChina(lat, lon)) { return null ; } double dLat = transformLat(lon - 105.0, lat - 35.0); double dLon = transformLon(lon - 105.0, lat - 35.0); double radLat = lat / 180.0 * pi; double magic = Math.Sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.Sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * pi); double mgLat = lat + dLat; double mgLon = lon + dLon; return new Gps(mgLat, mgLon); } /** * 判断有没有超过中国区 * * @author zr * @date 2019-09-09 * @param * @param lat * @param lon * @return boolean */ private static bool outOfChina( double lat, double lon) { if (lon < 72.004 || lon > 137.8347) { return true ; } if (lat < 0.8293 || lat > 55.8271) { return true ; } return false ; } /** * 处理纬度 * * @author zr * @date 2019-09-09 * @param * @param x * @param y * @return double */ private static double transformLat( double x, double y) { double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x)); ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0; ret += (20.0 * Math.Sin(y * pi) + 40.0 * Math.Sin(y / 3.0 * pi)) * 2.0 / 3.0; ret += (160.0 * Math.Sin(y / 12.0 * pi) + 320 * Math.Sin(y * pi / 30.0)) * 2.0 / 3.0; return ret; } /** * 处理经度 * * @author zr * @date 2019-09-09 * @param * @param x * @param y * @return double */ private static double transformLon( double x, double y) { double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x)); ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0; ret += (20.0 * Math.Sin(x * pi) + 40.0 * Math.Sin(x / 3.0 * pi)) * 2.0 / 3.0; ret += (150.0 * Math.Sin(x / 12.0 * pi) + 300.0 * Math.Sin(x / 30.0 * pi)) * 2.0 / 3.0; return ret; } } public class Gps { private double wgLat; private double wgLon; public Gps() { } public Gps( double _wgLat, double _wgLon) { wgLat = _wgLat; wgLon = _wgLon; } public double getWgLat() { return wgLat; } public double getWgLon() { return wgLon; } public String toString() { return "Gps{" + "wgLat=" + wgLat + ", wgLon=" + wgLon + '}' ; } }