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
use std::f64::consts::PI;
#[derive(Debug, Clone)]
pub struct GlobalMercator {
tile_size: u32,
initial_resolution: f64,
origin_shift: f64,
}
impl Default for GlobalMercator {
fn default() -> Self {
GlobalMercator::new(256)
}
}
impl GlobalMercator {
pub fn new(tile_size: u32) -> GlobalMercator {
GlobalMercator {
tile_size,
initial_resolution: 2.0 * PI * 6378137.0 / tile_size as f64,
origin_shift: 2.0 * PI * 6378137.0 / 2.0,
}
}
pub fn tile_size(&self) -> u32 {
self.tile_size
}
pub fn lat_lon_to_meters(&self, lat: f64, lon: f64) -> (f64, f64) {
let mx = lon * self.origin_shift / 180.0;
let my = f64::log2(f64::tan((90.0 + lat) * PI / 360.0)) / (PI / 180.0);
let my = my * self.origin_shift / 180.0;
return (mx, my);
}
pub fn meters_to_lat_lon(&self, mx: f64, my: f64) -> (f64, f64) {
let lon = (mx / self.origin_shift) * 180.0;
let lat = (my / self.origin_shift) * 180.0;
let lat = 180.0 / PI * (2.0 * f64::atan(f64::exp(lat * PI / 180.0)) - PI / 2.0);
return (lat, lon);
}
pub fn pixels_to_meters(&self, px: f64, py: f64, zoom: u32) -> (f64, f64) {
let res = self.resolution(zoom);
let mx = px * res - self.origin_shift;
let my = py * res - self.origin_shift;
return (mx, my);
}
pub fn meters_to_pixels(&self, mx: f64, my: f64, zoom: u32) -> (f64, f64) {
let res = self.resolution(zoom);
let px = (mx + self.origin_shift) / res;
let py = (my + self.origin_shift) / res;
return (px, py);
}
pub fn pixels_to_tile(&self, px: f64, py: f64) -> (i32, i32) {
let tx = f64::ceil(px / self.tile_size as f64) as i32 - 1;
let ty = f64::ceil(py / self.tile_size as f64) as i32 - 1;
return (tx, ty);
}
pub fn pixels_to_raster(&self, px: f64, py: f64, zoom: u32) -> (f64, f64) {
let map_size = self.tile_size << zoom;
return (px, map_size as f64 - py);
}
pub fn meters_to_tile(&self, mx: f64, my: f64, zoom: u32) -> (i32, i32) {
let (px, py) = self.meters_to_pixels(mx, my, zoom);
return self.pixels_to_tile(px, py);
}
pub fn tile_bounds(&self, tx: i32, ty: i32, zoom: u32) -> (f64, f64, f64, f64) {
let (minx, miny) = self.pixels_to_meters((tx * self.tile_size as i32) as f64, (ty * self.tile_size as i32) as f64, zoom);
let (maxx, maxy) = self.pixels_to_meters(((tx + 1) * self.tile_size as i32) as f64, ((ty + 1) * self.tile_size as i32) as f64, zoom);
return (minx, miny, maxx, maxy);
}
pub fn tile_lat_lon_bounds(&self, tx: i32, ty: i32, zoom: u32) -> (f64, f64, f64, f64) {
let (minx, miny, maxx, maxy) = self.tile_bounds(tx, ty, zoom);
let (min_lat, min_lon) = self.meters_to_lat_lon(minx, miny);
let (max_lat, max_lon) = self.meters_to_lat_lon(maxx, maxy);
return (min_lat, min_lon, max_lat, max_lon);
}
pub fn resolution(&self, zoom: u32) -> f64 {
return self.initial_resolution / (f64::powi(2.0, zoom as i32));
}
pub fn zoom_for_pixel_size(&self, pixel_size: f64) -> u32 {
for i in 0..30 {
if pixel_size > self.resolution(i) {
return if i != 0 {
i - 1
} else {
0
};
}
}
panic!("Invalid pixel_size: {}", pixel_size);
}
pub fn google_tile(&self, tx: i32, ty: i32, zoom: u32) -> (i32, i32) {
return (tx, (f64::powi(2.0, zoom as i32) as i32 - 1) - ty);
}
pub fn quad_tree(&self, tx: i32, ty: i32, zoom: u32) -> String {
let mut quad_key = String::new();
let ty = (f64::powi(2.0, zoom as i32) - 1.0) as i32 - ty;
for i in (0..zoom as i32).rev() {
let mut digit = 0;
let mask = 1 << (i - 1);
if (tx & mask) != 0 {
digit += 1;
}
if (ty & mask) != 0 {
digit += 2;
}
quad_key.push_str(format!("{}", digit).as_str());
}
return quad_key;
}
}