经纬度坐标的转换在地理信息系统(GIS)和许多应用中都非常重要。中国的坐标系统比较复杂,主要有 CGCS2000、WGS-84(GPS 坐标)、GCJ-02(火星坐标)、BD-09(百度坐标)等。本文将介绍这几种坐标的含义及其相互转换,附上Java代码示例。
一、坐标系统简介
-
CGCS2000:是为了解决地理信息共享和协调而制定的中国国家大地坐标系,基于大地测量数据,是主要用于中国境内的坐标系统。
-
WGS-84:即世界大地测量系统1984,广泛用于GPS定位,适用于全球坐标,是一种标准的地理坐标系统。
-
GCJ-02:又称为“火星坐标系”,是由中国政府为了保护地理信息安全对WGS-84坐标进行加密后的坐标系统。因此,使用官方地图服务时,往往会用到该坐标系。
-
BD-09:是百度地图所使用的坐标系统,基于GCJ-02进行进一步加密和偏移。
二、坐标转换原理
坐标转换的核心在于计算不同算法下的偏移。通常,GCJ-02与WGS-84转换需要使用一定的数学公式,而BD-09则是在GCJ-02基础上进行偏移。
三、Java实现代码示例
下面的Java代码实现了WGS-84与GCJ-02、GCJ-02与BD-09之间的转换。这些代码包含了基本的数学计算。
public class CoordinateConverter {
private static final double PI = 3.1415926535897932384626;
private static final double A = 6378245.0; // WGS-84 椭球体长半轴
private static final double EE = 0.00669342162296594323; // WGS-84 椭球体偏心率平方
public static void main(String[] args) {
double[] wgs84 = {39.90960456049752, 116.3972282409668}; // 示例:北京天安门经纬度
double[] gcj02 = wgs84ToGcj02(wgs84[0], wgs84[1]);
double[] bd09 = gcj02ToBd09(gcj02[0], gcj02[1]);
System.out.println("WGS-84: " + wgs84[0] + ", " + wgs84[1]);
System.out.println("GCJ-02: " + gcj02[0] + ", " + gcj02[1]);
System.out.println("BD-09: " + bd09[0] + ", " + bd09[1]);
}
public static double[] wgs84ToGcj02(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new double[]{lat, lon};
}
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 gLat = lat + dLat;
double gLon = lon + dLon;
return new double[]{gLat, gLon};
}
public static double[] gcj02ToBd09(double lat, double lon) {
double x = lon, y = lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * PI);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * PI);
double bdLon = z * Math.cos(theta) + 0.0065;
double bdLat = z * Math.sin(theta) + 0.006;
return new double[]{bdLat, bdLon};
}
private static boolean outOfChina(double lat, double lon) {
return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271;
}
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.0 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
return ret;
}
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;
}
}
四、总结
上述代码实现了从WGS-84到GCJ-02,再到BD-09的转换过程。对于在中国大陆使用GPS服务,通常需要将WGS-84坐标转换为GCJ-02坐标,以便在各种地图应用中正确显示。通过这个示例,希望可以帮助开发者理解和实现经纬度的坐标转换。