CoordinateTransformUtil.java
5.82 KB
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package cn.fw.hestia.common.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具
* <p>
* create at 2018-10-09
*
* @author kurisu
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class CoordinateTransformUtil {
// π
private static double PI = Math.PI;
private static double X_PI = PI * 3000.0 / 180.0;
// 长半轴
private static double A = 6378245.0;
// 扁率
private static double EE = 0.00669342162296594323;
/**
* 百度坐标系(BD-09)转WGS坐标
*
* @param lng 百度坐标纬度
* @param lat 百度坐标经度
* @return WGS84坐标数组
*/
public static double[] bd09toWgs84(double lng, double lat) {
double[] gcj = bd09toGcj02(lng, lat);
return gcj02toWgs84(gcj[0], gcj[1]);
}
/**
* WGS坐标转百度坐标系(BD-09)
*
* @param lng WGS84坐标系的经度
* @param lat WGS84坐标系的纬度
* @return 百度坐标数组
*/
public static double[] wgs84toBd09(double lng, double lat) {
double[] gcj = wgs84toGcj02(lng, lat);
return gcj02toBd09(gcj[0], gcj[1]);
}
/**
* 火星坐标系(GCJ-02)转百度坐标系(BD-09)
* 谷歌、高德——>百度
*
* @param lng 火星坐标经度
* @param lat 火星坐标纬度
* @return 百度坐标数组
*/
public static double[] gcj02toBd09(double lng, double lat) {
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);
double bd_lng = z * Math.cos(theta) + 0.0065;
double bd_lat = z * Math.sin(theta) + 0.006;
return new double[]{bd_lng, bd_lat};
}
/**
* 百度坐标系(BD-09)转火星坐标系(GCJ-02)
* 百度——>谷歌、高德
*
* @param bd_lon 百度坐标纬度
* @param bd_lat 百度坐标经度
* @return 火星坐标数组
*/
public static double[] bd09toGcj02(double bd_lon, double bd_lat) {
double x = bd_lon - 0.0065;
double y = bd_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);
double gg_lng = z * Math.cos(theta);
double gg_lat = z * Math.sin(theta);
return new double[]{gg_lng, gg_lat};
}
/**
* WGS84转GCJ02(火星坐标系)
*
* @param lng WGS84坐标系的经度
* @param lat WGS84坐标系的纬度
* @return 火星坐标数组
*/
public static double[] wgs84toGcj02(double lng, double lat) {
if (out_of_china(lng, lat)) {
return new double[]{lng, lat};
}
double dlat = transformLat(lng - 105.0, lat - 35.0);
double dlng = transformLng(lng - 105.0, lat - 35.0);
double radlat = lat / 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 = lat + dlat;
double mglng = lng + dlng;
return new double[]{mglng, mglat};
}
/**
* GCJ02(火星坐标系)转GPS84
*
* @param lng 火星坐标系的经度
* @param lat 火星坐标系纬度
* @return WGS84坐标数组
*/
public static double[] gcj02toWgs84(double lng, double lat) {
if (out_of_china(lng, lat)) {
return new double[]{lng, lat};
}
double dlat = transformLat(lng - 105.0, lat - 35.0);
double dlng = transformLng(lng - 105.0, lat - 35.0);
double radlat = lat / 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 = lat + dlat;
double mglng = lng + dlng;
return new double[]{lng * 2 - mglng, lat * 2 - mglat};
}
/**
* 纬度转换
*
* @param lng 经度
* @param lat 纬度
* @return 纬度
*/
public 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(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 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;
}
/**
* 经度转换
*
* @param lng 经度
* @param lat 纬度
* @return 经度
*/
public 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(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
return ret;
}
/**
* 判断是否在国内,不在国内不做偏移
*
* @param lng 经度
* @param lat 纬度
* @return 是否
*/
public static boolean out_of_china(double lng, double lat) {
if (lng < 72.004 || lng > 137.8347) {
return true;
} else {
return lat < 0.8293 || lat > 55.8271;
}
}
}