package org.yzh.commons.util;
|
|
/**
|
* WGS-84 GPS坐标(谷歌地图国外)
|
* GCJ-02 国测局坐标(谷歌地图国内、高德地图、腾讯地图)
|
* BD-09 百度坐标(百度地图)
|
* @author yezhihao
|
* https://gitee.com/yezhihao/jt808-server
|
*/
|
public class CoordTransform {
|
|
/** 长半轴(赤道半径,单位米,克拉索夫斯基椭球) */
|
public static final double A = 6378245;
|
|
/** 第一偏心率平方 */
|
private static final double EE = 0.00669342162296594323;
|
|
private static final double PI = Math.PI;
|
|
private static final double X_PI = Math.PI * 3000.0 / 180.0;
|
|
public static double[] wgs84tobd09(double[] lngLat) {
|
return wgs84tobd09(lngLat[0], lngLat[1], new double[2]);
|
}
|
|
public static double[] wgs84tobd09(double lng, double lat) {
|
return wgs84tobd09(lng, lat, new double[2]);
|
}
|
|
/** WGS-84 转 BD-09 */
|
public static double[] wgs84tobd09(double lng, double lat, double[] result) {
|
wgs84togcj02(lng, lat, result);
|
gcj02tobd09(result[0], result[1], result);
|
return result;
|
}
|
|
public static double[] bd09towgs84(double[] lngLat) {
|
return bd09towgs84(lngLat[0], lngLat[1], new double[2]);
|
}
|
|
public static double[] bd09towgs84(double lng, double lat) {
|
return bd09towgs84(lng, lat, new double[2]);
|
}
|
|
/** BD-09 转 WGS-84 */
|
public static double[] bd09towgs84(double lng, double lat, double[] result) {
|
bd09togcj02(lng, lat, result);
|
gcj02towgs84(result[0], result[1], result);
|
return result;
|
}
|
|
public static double[] bd09togcj02(double[] lngLat) {
|
return bd09togcj02(lngLat[0], lngLat[1], new double[2]);
|
}
|
|
public static double[] bd09togcj02(double lng, double lat) {
|
return bd09togcj02(lng, lat, new double[2]);
|
}
|
|
/** BD-09 转 GCJ-02 */
|
public static double[] bd09togcj02(double lng, double lat, double[] result) {
|
double x = lng - 0.0065;
|
double y = lat - 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);
|
result[0] = z * Math.cos(theta);
|
result[1] = z * Math.sin(theta);
|
return result;
|
}
|
|
public static double[] gcj02tobd09(double[] lngLat) {
|
return gcj02tobd09(lngLat[0], lngLat[1], new double[2]);
|
}
|
|
public static double[] gcj02tobd09(double lng, double lat) {
|
return gcj02tobd09(lng, lat, new double[2]);
|
}
|
|
/** GCJ-02 转 BD-09 */
|
public static double[] gcj02tobd09(double lng, double lat, double[] result) {
|
double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI);
|
double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI);
|
result[0] = z * Math.cos(theta) + 0.0065;
|
result[1] = z * Math.sin(theta) + 0.006;
|
return result;
|
}
|
|
public static double[] wgs84togcj02(double[] lngLat) {
|
return wgs84togcj02(lngLat[0], lngLat[1], new double[2]);
|
}
|
|
public static double[] wgs84togcj02(double lng, double lat) {
|
return wgs84togcj02(lng, lat, new double[2]);
|
}
|
|
/** WGS-84 转 GCJ-02 */
|
public static double[] wgs84togcj02(double lng, double lat, double[] result) {
|
if (inChina(lng, lat)) {
|
double dlat = transformlat(lng - 105.0, lat - 35.0);
|
double dlng = transformlng(lng - 105.0, lat - 35.0);
|
double radlat = lat * (PI / 180.0);
|
double magic = Math.sin(radlat);
|
magic = 1 - EE * magic * magic;
|
double sqrtmagic = Math.sqrt(magic);
|
dlat = (dlat * 180.0) / ((A * (1 - EE)) * PI / (magic * sqrtmagic));
|
dlng = (dlng * 180.0) / (A * PI / sqrtmagic * Math.cos(radlat));
|
result[0] = lng + dlng;
|
result[1] = lat + dlat;
|
return result;
|
} else {
|
result[0] = lng;
|
result[1] = lat;
|
return result;
|
}
|
}
|
|
public static double[] gcj02towgs84(double[] lngLat) {
|
return gcj02towgs84(lngLat[0], lngLat[1], new double[2]);
|
}
|
|
public static double[] gcj02towgs84(double lng, double lat) {
|
return gcj02towgs84(lng, lat, new double[2]);
|
}
|
|
/** GCJ-02 转 WGS-84 */
|
public static double[] gcj02towgs84(double lng, double lat, double[] result) {
|
if (inChina(lng, lat)) {
|
double dlat = transformlat(lng - 105.0, lat - 35.0);
|
double dlng = transformlng(lng - 105.0, lat - 35.0);
|
double radlat = lat * (PI / 180.0);
|
double magic = Math.sin(radlat);
|
magic = 1 - EE * magic * magic;
|
double sqrtmagic = Math.sqrt(magic);
|
dlat = (dlat * 180.0) / ((A * (1 - EE)) * PI / (magic * sqrtmagic));
|
dlng = (dlng * 180.0) / (A * PI / sqrtmagic * Math.cos(radlat));
|
result[0] = lng - dlng;
|
result[1] = lat - dlat;
|
return result;
|
} else {
|
result[0] = lng;
|
result[1] = lat;
|
return result;
|
}
|
}
|
|
private static double transformlat(double lng, double lat) {
|
double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
|
ret += (20.0 * Math.sin(PI * 6.0 * lng) + 20.0 * Math.sin(PI * 2.0 * lng)) * (2.0 / 3.0);
|
ret += (20.0 * Math.sin(PI * lat) + 40.0 * Math.sin(PI / 3.0 * lat)) * (2.0 / 3.0);
|
ret += (160.0 * Math.sin(lat / (12.0 / PI)) + 320 * Math.sin(lat * (PI / 30.0))) * (2.0 / 3.0);
|
return ret;
|
}
|
|
private static double transformlng(double lng, double lat) {
|
double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
|
ret += (20.0 * Math.sin(PI * 6.0 * lng) + 20.0 * Math.sin(PI * 2.0 * lng)) * (2.0 / 3.0);
|
ret += (20.0 * Math.sin(PI * lng) + 40.0 * Math.sin(PI / 3.0 * lng)) * (2.0 / 3.0);
|
ret += (150.0 * Math.sin(lng / (12.0 / PI)) + 300.0 * Math.sin(lng * (PI / 30.0))) * (2.0 / 3.0);
|
return ret;
|
}
|
|
/** 判断是否在国内,不在国内则不做偏移 */
|
public static boolean inChina(double lng, double lat) {
|
// 纬度3.86~53.55,经度73.66~135.05
|
return (lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
|
}
|
}
|