import com.dhtech.tools.dhcore.exception.BusinessException;
import org.springframework.util.StringUtils;
import java.text.DecimalFormat;
import java.util.Objects;
/**
* <b>百度地图相关工具类</b><br>
* 1、包含坐标转换<br>
* 2、百度地图计算两点间距离
* WGS-84:是国际标准,GPS坐标(Google Earth使用、或者GPS模块)
* GCJ-02:中国坐标偏移标准,Google Map、高德、腾讯使用
* BD-09:百度坐标偏移标准,Baidu Map使用
*
* @author 李龙
* @version [2016年8月15日]
*/
public class MapUtils {
//public static final String BAIDU_LBS_TYPE = "bd09ll";
/***
*
*/
public static final String CODES = "0123456789abcdefghijkmnpqrstuvwxyz";
public static final double X_PI = 3.1415926535897932384626;
public static final double PI = 3.14159265358979324 * 3000.0 / 180.0;
public static final double A = 6378245.0;
public static final double EE = 0.00669342162296594323;
/**
* wgs84转GCj02
*
* @param lat
* @param lon
* @return
*/
public static Gps gps84_To_Gcj02(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 * X_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) * X_PI);
dLon = (dLon * 180.0) / (A / sqrtMagic * Math.cos(radLat) * X_PI);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new Gps(mgLat, mgLon);
}
/**
* GCj02转wgs84
*
* @param lat
* @param lon
* @return
*/
public static Gps gcj_To_Gps84(double lat, double lon) {
Gps gps = transform(lat, lon);
double lontitude = lon * 2 - gps.getLng();
double latitude = lat * 2 - gps.getLat();
return new Gps(latitude, lontitude);
}
/**
* GCj02转百度地图坐标
*
* @param gg_lat
* @param gg_lon
* @return
*/
public static Gps gcj02_To_Bd09(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 * PI);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(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);
}
/**
* 百度地图坐标转GCj02
*
* @param bd_lat
* @param bd_lon
* @return
*/
public static Gps bd09_To_Gcj02(double bd_lat, double bd_lon) {
double x = bd_lon - 0.0065, y = bd_lat - 0.006;
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 gg_lon = z * Math.cos(theta);
double gg_lat = z * Math.sin(theta);
return new Gps(gg_lat, gg_lon);
}
/**
* 百度坐标转WGs84 (百度坐标转原始坐标)
*
* @param bd_lat
* @param bd_lon
* @return
*/
public static Gps bd09_To_Gps84(double bd_lat, double bd_lon) {
Gps gcj02 = bd09_To_Gcj02(bd_lat, bd_lon);
Gps map84 = gcj_To_Gps84(gcj02.getLat(), gcj02.getLng());
return map84;
}
/**
* WGs84转百度坐标 (原始坐标转百度坐标)
*
* @param lat
* @param lon
* @return
*/
public static Gps Gps84_To_bd09(double lat, double lon) {
Gps gcj02 = gps84_To_Gcj02(lat, lon);
if (Objects.isNull(gcj02)) {
throw new BusinessException(505, "请输入正确的经纬度");
}
Gps bd09 = gcj02_To_Bd09(gcj02.getLat(), gcj02.getLng());
return bd09;
}
/**
* 凯立德转百度坐标
*/
public Gps kld_To_bd09(double kld_lat, double kld_lon) {
String k = kld_To_K(Double.valueOf(kld_lon), Double.valueOf(kld_lat));
Gps kGJC = k_To_Gcj02(k);
Gps result = gcj02_To_Bd09(kGJC.getLat(), kGJC.getLng());
return result;
}
/**
* 百度地图计算两点间距离
*
* @param a
* @param b
* @return
*/
public static double getBaiduDistance(Gps a, Gps b) {
double c = wv(a, b);
return c;
}
/**
* K码转Gcj02经度
*
* @param k
* @return
*/
public static Gps k_To_Gcj02(String k) {
double lat = __decode(k.substring(5, 9));
if (k.charAt(0) <= '6') {
lat += 35000000;
}
lat += 5000000;
double lon = __decode(k.substring(1, 5));
if (k.charAt(0) == '5' || k.charAt(0) == '8') {
lon += 35000000;
}
lon += 70000000;
return new Gps(lat / 1000000.0, lon / 1000000.0);
}
/**
* GCJ02转成K码
*
* @param gg_lat
* @param gg_lon
* @return
*/
public String gcj02_To_K(double gg_lat, double gg_lon) {
int lat = Integer.parseInt(new DecimalFormat("0").format((gg_lat)));
int lon = Integer.parseInt(new DecimalFormat("0").format((gg_lon)));
String k;
lon -= 70000000;
lat -= 5000000;
if (lat > 35000000) {
if (lon <= 35000000) {
k = "6";
} else {
k = "5";
}
} else {
if (lon <= 35000000) {
k = "7";
} else {
k = "8";
}
}
if (lon > 35000000) {
lon -= 35000000;
}
if (lat > 35000000) {
lat -= 35000000;
}
k += __encode(lon);
k += __encode(lat);
return k;
}
/**
* 凯立德坐标转成K码
*
* @param kld_lat
* @param kld_lon
* @return
*/
public String kld_To_K(double kld_lat, double kld_lon) {
String k = "";
double a = kld_lat;
double b = kld_lon;
char[] c = new char[10];
double d, e, f, h, i;
a = Math.round(a / 100 - 3337);
b = Math.round(b / 100 - 2373);
if (a < 2520000 || a > 5040000 || b < 180000 || b > 2700000) {
return "100000000";
}
d = a - 2520000;
e = b - 180000;
if (d > 1260000) {
d -= 1260000;
if (e > 1260000) {
e -= 1260000;
f = 1;
} else {
f = 4;
}
} else if (e > 1260000) {
e -= 1260000;
f = 2;
} else {
f = 3;
}
c[0] = (char) ((int) ("4".charAt(0)) + f);
f = d;
d = 1;
for (i = 0; f > 0 && i < 4; ) {
h = f % 34;
c[(int) d] = h < 10 ? (char) ((int) ("0".charAt(0)) + h)
: h < 21 ? (char) ((int) ("A".charAt(0)) + h - 10)
: h < 23 ? (char) ((int) ("M".charAt(0)) + h - 21)
: (char) ((int) ("P".charAt(0)) + h - 23);
d++;
i++;
f /= 34;
}
for (f = i; f < 4; f++) {
c[(int) d] = "0".charAt(0);
d++;
}
f = e;
for (i = 0; f > 0 && i < 4; ) {
h = f % 34;
c[(int) d] = h < 10 ? (char) ((int) ("0".charAt(0)) + h)
: h < 21 ? (char) ((int) ("A".charAt(0)) + h - 10)
: h < 23 ? (char) ("M".charAt(0) + h - 21) : (char) ((int) ("P".charAt(0)) + h - 23);
d++;
i++;
f /= 34;
}
for (f = i; f < 4; f++) {
c[(int) d] = "0".charAt(0);
d++;
}
c[(int) d] = 0;
for (char str : c) {
k += str;
}
return k.substring(0, 9).toLowerCase();
}
private static double wv(Gps a, Gps b) {
if (StringUtils.isEmpty(a.getLat()) || StringUtils.isEmpty(a.getLng()) || StringUtils.isEmpty(b.getLat())
|| StringUtils.isEmpty(b.getLng())) {
return 0;
}
double alat = a.getLat(), alon = a.getLng(), blat = b.getLat(), blon = b.getLng();
alon = ew(alon, -180, 180);
alat = lw(alat, -74, 74);
blon = ew(blon, -180, 180);
blat = lw(blat, -74, 74);
return Td(oi(alon), oi(blon), oi(alat), oi(blat));
}
private static double lw(double a, int b, int c) {
a = a > b ? a : b;
a = a > c ? c : a;
return a;
}
private static double ew(double a, int b, int c) {
if (a > c) {
a -= c - b;
}
if (a < b) {
a += c - b;
}
return a;
}
private static double oi(double a) {
return Math.PI * a / 180;
}
private static double Td(double a, double b, double c, double d) {
return 6370996.81 * Math.acos(Math.sin(c) * Math.sin(d) + Math.cos(c) * Math.cos(d) * Math.cos(b - a));
}
private static String __encode(int v) {
String pch = "";
v = v * 9 / 250;
for (int i = 0; i < 4; ++i) {
pch += CODES.charAt(v % 34);
v /= 34;
}
return pch;
}
private static Gps transform(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new Gps(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 * X_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) * X_PI);
dLon = (dLon * 180.0) / (A / sqrtMagic * Math.cos(radLat) * X_PI);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new Gps(mgLat, mgLon);
}
private static boolean outOfChina(double lat, double lon) {
if (lon < 72.004 || lon > 137.8347) {
return true;
}
return 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 * X_PI) + 20.0 * Math.sin(2.0 * x * X_PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * X_PI) + 40.0 * Math.sin(y / 3.0 * X_PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * X_PI) + 320 * Math.sin(y * X_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 * X_PI) + 20.0 * Math.sin(2.0 * x * X_PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * X_PI) + 40.0 * Math.sin(x / 3.0 * X_PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * X_PI) + 300.0 * Math.sin(x / 30.0 * X_PI)) * 2.0 / 3.0;
return ret;
}
private static double __decode(String k) {
double v = 0;
for (int i = 3; i >= 0; --i) {
v = v * 34 + (CODES.indexOf(k.charAt(i)));
}
v = v * 250 / 9;
return v;
}
}
Gps类
@Data
public class Gps {
/**
* 纬度
*/
private double lat;
/**
* 经度
*/
private double lng;
public Gps(double lat, double lng) {
this.lat = lat;
this.lng = lng;
}
@Override
public String toString() {
return "Gps [lat=" + lat + ", lng=" + lng + "]";
}
}