-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OSM tiling #440
OSM tiling #440
Changes from 6 commits
9eaa699
5c348d2
297212d
f36b3dd
2278dd3
3e860b6
b377106
955e859
6bea417
9bc42d0
951d3e1
c1ab0e3
ed12d3d
149d420
da11a4e
bb08273
f884bbf
7836a40
08db166
1e8fa3f
a85d458
206b587
dc01c39
c15ee9b
d21e47a
3ed491a
6707107
371b71c
47ff64d
cbd1ff0
5f9c17b
45bf02e
f948149
e865cc0
5579d40
f603d8e
b9abc00
eef06e5
6d353fd
0c65f5d
1f1a0ed
d1f432e
56c4b4e
e6e1162
a0ba124
180f24f
8135548
2155a2f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2271,8 +2271,8 @@ def to_slippy_tiles( | |||||||||||||||||||||||||||||||||||
min_lvl: int = None, | ||||||||||||||||||||||||||||||||||||
max_lvl: int = None, | ||||||||||||||||||||||||||||||||||||
driver="png", | ||||||||||||||||||||||||||||||||||||
cmap=None, | ||||||||||||||||||||||||||||||||||||
norm=None, | ||||||||||||||||||||||||||||||||||||
cmap: str | object = None, | ||||||||||||||||||||||||||||||||||||
norm: object = None, | ||||||||||||||||||||||||||||||||||||
**kwargs, | ||||||||||||||||||||||||||||||||||||
): | ||||||||||||||||||||||||||||||||||||
"""Produce tiles in /zoom/x/y.<ext> structure (EPSG:3857). | ||||||||||||||||||||||||||||||||||||
|
@@ -2292,6 +2292,13 @@ def to_slippy_tiles( | |||||||||||||||||||||||||||||||||||
If None, the zoomlevels will be determined based on the data resolution | ||||||||||||||||||||||||||||||||||||
driver : str, optional | ||||||||||||||||||||||||||||||||||||
file output driver, one of 'png', 'netcdf4' or 'GTiff' | ||||||||||||||||||||||||||||||||||||
cmap : str | object, optional | ||||||||||||||||||||||||||||||||||||
A colormap, either defined by a string and imported from matplotlib | ||||||||||||||||||||||||||||||||||||
via that string or as a ListedColormap object from matplotlib itself. | ||||||||||||||||||||||||||||||||||||
norm : object, optional | ||||||||||||||||||||||||||||||||||||
A matplotlib Normalize object that defines a range between a maximum | ||||||||||||||||||||||||||||||||||||
and minimum value | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
**kwargs | ||||||||||||||||||||||||||||||||||||
Key-word arguments to write file | ||||||||||||||||||||||||||||||||||||
for netcdf4, these are passed to ~:py:meth:xarray.DataArray.to_netcdf: | ||||||||||||||||||||||||||||||||||||
|
@@ -2309,6 +2316,10 @@ def to_slippy_tiles( | |||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
# Fixed pixel size and CRS for XYZ tiles | ||||||||||||||||||||||||||||||||||||
pxs = 256 | ||||||||||||||||||||||||||||||||||||
# Extent in y-direction for pseudo mercator (EPSG:3857) | ||||||||||||||||||||||||||||||||||||
y_ext = math.atan(math.sinh(math.pi)) * (180 / math.pi) | ||||||||||||||||||||||||||||||||||||
y_ext_pm = mct.xy(0, y_ext)[1] | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
crs = CRS.from_epsg(3857) | ||||||||||||||||||||||||||||||||||||
ext = {"png": "png", "netcdf4": "nc", "gtiff": "tif"}.get(driver.lower(), None) | ||||||||||||||||||||||||||||||||||||
if ext is None: | ||||||||||||||||||||||||||||||||||||
|
@@ -2322,6 +2333,8 @@ def to_slippy_tiles( | |||||||||||||||||||||||||||||||||||
# make sure dataarray has a name | ||||||||||||||||||||||||||||||||||||
name = obj.name or "data" | ||||||||||||||||||||||||||||||||||||
obj.name = name | ||||||||||||||||||||||||||||||||||||
obj_res = obj.raster.res[0] | ||||||||||||||||||||||||||||||||||||
obj_bounds = list(obj.raster.bounds) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
# colormap output | ||||||||||||||||||||||||||||||||||||
if cmap is not None and driver != "png": | ||||||||||||||||||||||||||||||||||||
|
@@ -2340,28 +2353,61 @@ def to_slippy_tiles( | |||||||||||||||||||||||||||||||||||
}.get(driver.lower(), {}) | ||||||||||||||||||||||||||||||||||||
kwargs = {**kwargs0, **kwargs} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
# Setting up information for zoomlevel calculation and | ||||||||||||||||||||||||||||||||||||
# determination of tile windows | ||||||||||||||||||||||||||||||||||||
# This section is purely for the resolution | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this section be moved inside the if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||||||||||||||||||||||||||||||||
bounds_4326_clip = list(obj.raster.transform_bounds("EPSG:4326")) | ||||||||||||||||||||||||||||||||||||
bounds_4326_clip[:2] = map( | ||||||||||||||||||||||||||||||||||||
max, | ||||||||||||||||||||||||||||||||||||
zip(bounds_4326_clip[:2], (-180, -y_ext)), | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
bounds_4326_clip[2:] = map( | ||||||||||||||||||||||||||||||||||||
min, | ||||||||||||||||||||||||||||||||||||
zip(bounds_4326_clip[2:], (180, y_ext)), | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
obj_clipped_to_pseudo = obj.raster.clip_bbox( | ||||||||||||||||||||||||||||||||||||
bounds_4326_clip, | ||||||||||||||||||||||||||||||||||||
crs="EPSG:4326", | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this do the same? Or am I missing something?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I just wrote it way too explicitly..., kind of laughed when I saw this. |
||||||||||||||||||||||||||||||||||||
tr_3857 = rasterio.warp.calculate_default_transform( | ||||||||||||||||||||||||||||||||||||
obj_clipped_to_pseudo.raster.crs, | ||||||||||||||||||||||||||||||||||||
"EPSG:3857", | ||||||||||||||||||||||||||||||||||||
*obj_clipped_to_pseudo.shape, | ||||||||||||||||||||||||||||||||||||
*obj_clipped_to_pseudo.raster.bounds, | ||||||||||||||||||||||||||||||||||||
)[0] | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
del obj_clipped_to_pseudo | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
# This section is for dealing with rounding errors | ||||||||||||||||||||||||||||||||||||
obj_bounds_cor = [ | ||||||||||||||||||||||||||||||||||||
obj_bounds[0] + 0.5 * obj_res, | ||||||||||||||||||||||||||||||||||||
obj_bounds[1] + 0.5 * obj_res, | ||||||||||||||||||||||||||||||||||||
obj_bounds[2] - 0.5 * obj_res, | ||||||||||||||||||||||||||||||||||||
obj_bounds[3] - 0.5 * obj_res, | ||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||
bounds_4326 = rasterio.warp.transform_bounds( | ||||||||||||||||||||||||||||||||||||
obj.raster.crs, | ||||||||||||||||||||||||||||||||||||
"EPSG:4326", | ||||||||||||||||||||||||||||||||||||
*obj_bounds_cor, | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
# Calculate min/max zoomlevel based | ||||||||||||||||||||||||||||||||||||
bounds_wgsg84 = obj.raster.transform_bounds("EPSG:4326") | ||||||||||||||||||||||||||||||||||||
if max_lvl is None: # calculate max zoomlevel close to native resolution | ||||||||||||||||||||||||||||||||||||
max_lat = max(np.abs(bounds_wgsg84[1]), np.abs(bounds_wgsg84[3])) | ||||||||||||||||||||||||||||||||||||
if self.crs.is_projected and self.crs.axis_info[0].unit_name == "metre": | ||||||||||||||||||||||||||||||||||||
dx_m = obj.raster.res[0] | ||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||
dx_m = gis_utils.cellres(max_lat, *obj.raster.res)[0] | ||||||||||||||||||||||||||||||||||||
C = 2 * np.pi * 6378137 # circumference of the earth | ||||||||||||||||||||||||||||||||||||
# Determine the max number of zoom levels with the resolution | ||||||||||||||||||||||||||||||||||||
dres = tr_3857[0] | ||||||||||||||||||||||||||||||||||||
max_lvl = int( | ||||||||||||||||||||||||||||||||||||
np.ceil(np.log2(C * np.cos(np.deg2rad(max_lat)) / dx_m / pxs)) | ||||||||||||||||||||||||||||||||||||
math.ceil((math.log10((y_ext_pm * 2) / (dres * pxs)) / math.log10(2))) | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
if min_lvl is None: # calculate min zoomlevel based on the data extent | ||||||||||||||||||||||||||||||||||||
min_lvl = mct.bounding_tile(*bounds_wgsg84).z | ||||||||||||||||||||||||||||||||||||
min_lvl = mct.bounding_tile(*bounds_4326).z | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
# Loop through the zoom levels | ||||||||||||||||||||||||||||||||||||
zoom_levels = {} | ||||||||||||||||||||||||||||||||||||
logger.info(f"Producing tiles from zoomlevel {min_lvl} to {max_lvl}") | ||||||||||||||||||||||||||||||||||||
for zl in range(max_lvl, min_lvl - 1, -1): | ||||||||||||||||||||||||||||||||||||
fns = [] | ||||||||||||||||||||||||||||||||||||
# Go through the zoomlevels | ||||||||||||||||||||||||||||||||||||
for i, tile in enumerate(mct.tiles(*bounds_wgsg84, zl, truncate=True)): | ||||||||||||||||||||||||||||||||||||
for i, tile in enumerate(mct.tiles(*bounds_4326, zl, truncate=True)): | ||||||||||||||||||||||||||||||||||||
ssd = Path(root, str(zl), f"{tile.x}") | ||||||||||||||||||||||||||||||||||||
os.makedirs(ssd, exist_ok=True) | ||||||||||||||||||||||||||||||||||||
tile_bounds = mct.xy_bounds(tile) | ||||||||||||||||||||||||||||||||||||
|
@@ -2460,7 +2506,7 @@ def to_slippy_tiles( | |||||||||||||||||||||||||||||||||||
"zoom_levels": zoom_levels, | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
name = os.path.basename(root) | ||||||||||||||||||||||||||||||||||||
with open(join(root, "data.yml"), "w") as f: | ||||||||||||||||||||||||||||||||||||
with open(join(root, f"{name}.yml"), "w") as f: | ||||||||||||||||||||||||||||||||||||
yaml.dump({name: yml}, f, default_flow_style=False, sort_keys=False) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
def to_raster( | ||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The object is called a ListedColormap, but I will change it.