forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtiling.py
More file actions
38 lines (31 loc) · 1.67 KB
/
Copy pathtiling.py
File metadata and controls
38 lines (31 loc) · 1.67 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
"""Web Mercator slippy-map (XYZ) tile math.
Hand-rolled rather than adding morecantile as a dependency - this is ~10
lines of standard formulas, and this project already keeps small custom
helpers in lib/ instead of pulling in a framework for something this size
(see arcgis.py).
"""
WEB_MERCATOR_HALF_WORLD = 20037508.342789244 # meters; half the EPSG:3857 world extent
def tile_bounds_merc(z: int, x: int, y: int) -> tuple[float, float, float, float]:
"""EPSG:3857 (minx, miny, maxx, maxy) bounds of XYZ tile (z, x, y)."""
n = 2**z
tile_size = 2 * WEB_MERCATOR_HALF_WORLD / n
minx = -WEB_MERCATOR_HALF_WORLD + x * tile_size
maxx = minx + tile_size
maxy = WEB_MERCATOR_HALF_WORLD - y * tile_size
miny = maxy - tile_size
return minx, miny, maxx, maxy
def tile_range_for_bounds(bounds_merc: tuple[float, float, float, float], z: int) -> tuple[int, int, int, int]:
"""Candidate (x0, x1, y0, y1) inclusive XYZ tile index range at zoom z
that could intersect the given EPSG:3857 bounds.
This is a cheap bounding-box filter, not a real intersection test - the
caller is expected to follow up with an actual polygon-intersection
check (e.g. against the real corridor shape) since this range is a
superset of the tiles that actually matter."""
minx, miny, maxx, maxy = bounds_merc
n = 2**z
tile_size = 2 * WEB_MERCATOR_HALF_WORLD / n
x0 = max(0, int((minx + WEB_MERCATOR_HALF_WORLD) // tile_size))
x1 = min(n - 1, int((maxx + WEB_MERCATOR_HALF_WORLD) // tile_size))
y0 = max(0, int((WEB_MERCATOR_HALF_WORLD - maxy) // tile_size))
y1 = min(n - 1, int((WEB_MERCATOR_HALF_WORLD - miny) // tile_size))
return x0, x1, y0, y1