mcp_banner

Java地图坐标系转换工具类

话不多说,直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import java.util.HashMap;
import java.util.Map;

/**
* 坐标转换工具类
* 天地图使用的是地球坐标系(WGS84); 高德地图使用的是火星坐标系(GCJ02);百度地图使用的是百度坐标(bd09II)
*/
public class CoordinateTransformUtil {

private static final double X_PI = 3.14159265358979324 * 3000.0 / 180.0;
private static final double PI = 3.14159265358979324;
// 卫星椭球坐标投影到平面地图坐标系的投影因子。 地球长半径
private static final double EARTH_MAJOR_RADIUS = 6378245.0;
// 椭球的偏心率。
private static final double ECCENTRICITY_RATIO = 0.00669342162296594323;

/**
* 百度坐标(bd09II)转火星坐标(GCJ02)
* @param lat 百度坐标纬度
* @param lng 百度坐标经度
*/
public static Map<String, Double> baiduToMars(double lat, double lng) {
Map<String, Double> mars_point = new HashMap<>();
mars_point.put("lng", 0D);
mars_point.put("lat", 0D);

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);
mars_point.put("lng", z * Math.cos(theta));
mars_point.put("lat", z * Math.sin(theta));
return mars_point;
}

/**
* 火星坐标系(GCJ02)转百度坐标系(bd09II)
* @param gcjLat 火星坐标纬度
* @param gcjLng 火星坐标经度
*/
public static Map<String, Double> marsTobaidu(double gcjLat, double gcjLng) {
HashMap<String, Double> baidu_point = new HashMap<>();
baidu_point.put("lng", 0D);
baidu_point.put("lat", 0D);

double x = gcjLng;
double y = gcjLat;
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);
baidu_point.put("lng", z * Math.cos(theta) + 0.0065);
baidu_point.put("lat", z * Math.sin(theta) + 0.006);
return baidu_point;
}

/**
* 火星坐标系(GCJ02)转地球坐标系(WGS84)
* @param gcjLat 火星坐标纬度
* @param gcjLng 火星坐标经度
*/
public static Map<String, Double> transformGCJ2WGS(double gcjLat, double gcjLng) {
Map<String, Double> map = delta(gcjLat, gcjLng);
double lat = map.get("lat");
double lng = map.get("lng");
map.put("lat", gcjLat - lat);
map.put("lng", gcjLng - lng);
return map;
}

private static Map<String, Double> delta(double lat, double lng) {
double dLat = transformLat(lng - 105.0, lat - 35.0, PI);
double dlng = transformlng(lng - 105.0, lat - 35.0, PI);
double radLat = lat / 180.0 * PI;
double magic = Math.sin(radLat);
magic = 1 - ECCENTRICITY_RATIO * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((EARTH_MAJOR_RADIUS * (1 - ECCENTRICITY_RATIO)) / (magic * sqrtMagic) * PI);
dlng = (dlng * 180.0) / (EARTH_MAJOR_RADIUS / sqrtMagic * Math.cos(radLat) * PI);

Map<String, Double> map = new HashMap<>();
map.put("lat", dLat);
map.put("lng", dlng);
return map;
}

/**
* 地球坐标系(WGS - 84)转火星坐标系(GCJ)
* @param wgLat 地球坐标纬度
* @param wgLng 地球坐标经度
*/
public static Map<String, Double> transform(double wgLat, double wgLng) {
HashMap<String, Double> mars_point = new HashMap<>();
mars_point.put("lng", 0D);
mars_point.put("lat", 0D);
// 如果是国外坐标点,则直接返回传进来的坐标点
if (outOfChina(wgLng, wgLat)) {
mars_point.put("lng", wgLng);
mars_point.put("lat", wgLat);
return mars_point;
}
// 如果为国内坐标点,则计算偏移量
double dLat = transformLat(wgLng - 105.0, wgLat - 35.0, PI);
double dlng = transformlng(wgLng - 105.0, wgLat - 35.0, PI);
double radLat = wgLat / 180.0 * PI;
double magic = Math.sin(radLat);
magic = 1 - ECCENTRICITY_RATIO * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((EARTH_MAJOR_RADIUS * (1 - ECCENTRICITY_RATIO)) / (magic * sqrtMagic) * PI);
dlng = (dlng * 180.0) / (EARTH_MAJOR_RADIUS / sqrtMagic * Math.cos(radLat) * PI);
mars_point.put("lng", wgLng + dlng);
mars_point.put("lat", wgLat + dLat);

return mars_point;
}

/**
* 判断是否在国内,不在国内则不做偏移
* @param lng 经度
* @param lat 纬度
*/
private static boolean outOfChina(double lng, double lat) {
return (lng < 72.004 || lng > 137.8347) && (lat < 0.8293 || lat > 55.8271);
}

private static double transformLat(double x, double y, double pi) {
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 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}

private static double transformlng(double x, double y, double pi) {
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;
}

}