开发中经常会遇到坐标系之间互相转换的需求,下面分享一个坐标转化工具类:
public class GpsTransformUtil {
/**
* 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
* 即 百度 转 谷歌、高德
*
* @param bdLon
* @param bdLat
* @return Double[lon, lat]
*/
public static Double[] BD09ToGCJ02(Double bdLon, Double bdLat) {
double x = bdLon - 0.0065;
double y = bdLat - 0.006;
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[] arr = new Double[2];
arr[0] = z * Math.cos(theta);
arr[1] = z * Math.sin(theta);
return arr;
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
* 即谷歌、高德 转 百度
*
* @param gcjLon
* @param gcjLat
* @return Double[lon, lat]
*/
public static Double[] GCJ02ToBD09(Double gcjLon, Double gcjLat) {
double z = Math.sqrt(gcjLon * gcjLon + gcjLat * gcjLat) + 0.00002 * Math.sin(gcjLat * x_PI);
double theta = Math.atan2(gcjLat, gcjLon) + 0.000003 * Math.cos(gcjLon * x_PI);
Double[] arr = new Double[2];
arr[0] = z * Math.cos(theta) + 0.0065;
arr[1] = z * Math.sin(theta) + 0.006;
return arr;
}
/**
* WGS84转GCJ02(火星坐标系)
*
* @param wgsLon
* @param wgsLat
* @return Double[lon, lat]
*/
public static Double[] WGS84ToGCJ02(Double wgsLon, Double wgsLat) {
if (outOfChina(wgsLon, wgsLat)) {
return new Double[]{wgsLon, wgsLat};
}
double dlat = transformLatitude(wgsLon - 105.0, wgsLat - 35.0);
double dlng = transformLongitude(wgsLon - 105.0, wgsLat - 35.0);
double radLat = wgsLat / 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);
dlng = (dlng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
Double[] arr = new Double[2];
arr[0] = wgsLon + dlng;
arr[1] = wgsLat + dlat;
return arr;
}
/**
* GCJ02转WGS84
*
* @param gcjLon
* @param gcjLat
* @return Double[lon, lat]
*/
public static Double[] GCJ02ToWGS84(Double gcjLon, Double gcjLat) {
if (outOfChina(gcjLon, gcjLat)) {
return new Double[]{gcjLon, gcjLat};
}
double dlat = transformLatitude(gcjLon - 105.0, gcjLat - 35.0);
double dlng = transformLongitude(gcjLon - 105.0, gcjLat - 35.0);
double radLat = gcjLat / 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);
dlng = (dlng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
double mgLat = gcjLat + dlat;
double mgLng = gcjLon + dlng;
return new Double[]{gcjLon * 2 - mgLng, gcjLat * 2 - mgLat};
}
/**
* WGS84=>GCJ02 地球坐标系=>火星坐标系
*
* @param lng 经度
* @param lat 纬度
* @return 转化结果
*/
public static Double[] wgs84ToGcj02(double lng, double lat) {
if (outOfChina(lng, lat)) {
return new Double[]{lng, lat};
}
double[] offset = offset(lng, lat);
double mglng = lng + offset[0];
double mglat = lat + offset[1];
return new Double[]{mglng, mglat};
}
/**
* GCJ02=>WGS84[精确]
*
* @param lng 经度
* @param lat 纬度
* @param threshold 精度
* @return Double[lon, lat]
*/
public static Double[] gcj02ToWgs84Exactly(double lng, double lat, Double threshold) {
if (outOfChina(lng, lat)) {
return new Double[]{lng, lat};
}
double initDelta = 0.01;
threshold = Optional.ofNullable(threshold).orElse(0.000000001);
double dLat = initDelta, dLon = initDelta;
double mLat = lat - dLat, mLon = lng - dLon;
double pLat = lat + dLat, pLon = lng + dLon;
double wgsLat, wgsLng, i = 0;
while (true) {
wgsLat = (mLat + pLat) / 2;
wgsLng = (mLon + pLon) / 2;
Double[] wgs84ToGcj02 = wgs84ToGcj02(wgsLng, wgsLat);
dLon = wgs84ToGcj02[0] - lng;
dLat = wgs84ToGcj02[1] - lat;
if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold)) {
break;
}
if (dLat > 0) {
pLat = wgsLat;
} else {
mLat = wgsLat;
}
if (dLon > 0) {
pLon = wgsLng;
} else {
mLon = wgsLng;
}
if (++i > 10000) {
break;
}
}
return new Double[]{wgsLng, wgsLat};
}
}
拿去不谢,欢迎评论区交流,点赞收藏。