1const PI: f64 = std::f64::consts::PI;
2const X_PI: f64 = PI * 3000.0 / 180.0;
3const OFFSET: f64 = 0.00669342162296594323;
4const AXIS: f64 = 6378245.0;
5
6pub fn bd09_to_gcj02(lon: f64, lat: f64) -> (f64, f64) {
9 let x = lon - 0.0065;
10 let y = lat - 0.006;
11
12 let z = (x * x + y * y).sqrt() - 0.00002 * (y * X_PI).sin();
13 let theta = y.atan2(x) - 0.000003 * (x * X_PI).cos();
14
15 let g_lon = z * theta.cos();
16 let g_lat = z * theta.sin();
17
18 (g_lon, g_lat)
19}
20
21pub fn gcj02_to_bd09(lon: f64, lat: f64) -> (f64, f64) {
24 let z = (lon * lon + lat * lat).sqrt() + 0.00002 * (lat * X_PI).sin();
25 let theta = lat.atan2(lon) + 0.000003 * (lon * X_PI).cos();
26
27 let bd_lon = z * theta.cos() + 0.0065;
28 let bd_lat = z * theta.sin() + 0.006;
29
30 (bd_lon, bd_lat)
31}
32
33pub fn wgs84_to_gcj02(lon: f64, lat: f64) -> (f64, f64) {
36 if is_out_of_china(lon, lat) {
37 return (lon, lat);
38 }
39
40 let (mg_lon, mg_lat) = delta(lon, lat);
41
42 (mg_lon, mg_lat)
43}
44
45pub fn gcj02_to_wgs84(lon: f64, lat: f64) -> (f64, f64) {
48 if is_out_of_china(lon, lat) {
49 return (lon, lat);
50 }
51
52 let (mg_lon, mg_lat) = delta(lon, lat);
53
54 (lon * 2.0 - mg_lon, lat * 2.0 - mg_lat)
55}
56
57pub fn bd09_to_wgs84(lon: f64, lat: f64) -> (f64, f64) {
60 let (lon, lat) = bd09_to_gcj02(lon, lat);
61 gcj02_to_wgs84(lon, lat)
62}
63
64pub fn wgs84_to_bd09(lon: f64, lat: f64) -> (f64, f64) {
67 let (lon, lat) = wgs84_to_gcj02(lon, lat);
68 gcj02_to_bd09(lon, lat)
69}
70
71fn delta(lon: f64, lat: f64) -> (f64, f64) {
72 let (mut d_lat, mut d_lon) = transform(lon - 105.0, lat - 35.0);
73 let rad_lat = lat / 180.0 * PI;
74 let mut magic = rad_lat.sin();
75 magic = 1.0 - OFFSET * magic * magic;
76 let sqrt_magic = magic.sqrt();
77
78 d_lat = (d_lat * 180.0) / ((AXIS * (1.0 - OFFSET)) / (magic * sqrt_magic) * PI);
79 d_lon = (d_lon * 180.0) / (AXIS / sqrt_magic * rad_lat.cos() * PI);
80
81 let mg_lat = lat + d_lat;
82 let mg_lon = lon + d_lon;
83
84 (mg_lon, mg_lat)
85}
86
87fn transform(lon: f64, lat: f64) -> (f64, f64) {
88 let lon_lat = lon * lat;
89 let abs_x = lon.abs().sqrt();
90 let lon_pi = lon * PI;
91 let lat_pi = lat * PI;
92 let d = 20.0 * (6.0 * lon_pi).sin() + 20.0 * (2.0 * lon_pi).sin();
93 let mut x = d;
94 let mut y = d;
95 x += 20.0 * lat_pi.sin() + 40.0 * (lat_pi / 3.0).sin();
96 y += 20.0 * lon_pi.sin() + 40.0 * (lon_pi / 3.0).sin();
97 x += 160.0 * (lat_pi / 12.0).sin() + 320.0 * (lat_pi / 30.0).sin();
98 y += 150.0 * (lon_pi / 12.0).sin() + 300.0 * (lon_pi / 30.0).sin();
99 x *= 2.0 / 3.0;
100 y *= 2.0 / 3.0;
101 x += -100.0 + 2.0 * lon + 3.0 * lat + 0.2 * lat * lat + 0.1 * lon_lat + 0.2 * abs_x;
102 y += 300.0 + lon + 2.0 * lat + 0.1 * lon * lon + 0.1 * lon_lat + 0.1 * abs_x;
103 (x, y)
104}
105
106fn is_out_of_china(lon: f64, lat: f64) -> bool {
107 lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271
108}