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); } }