Skip to content

Commit f05e9e3

Browse files
Re-implementation of tile merging based on mercantile
1 parent cb7a4a0 commit f05e9e3

File tree

1 file changed

+37
-11
lines changed

1 file changed

+37
-11
lines changed

contextily/tile.py

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import pandas as pd
1010
import rasterio as rio
1111
from PIL import Image
12-
from cartopy.io.img_tiles import _merge_tiles as merge_tiles
1312
from rasterio.transform import from_origin
1413
from . import tile_providers as sources
1514

@@ -146,6 +145,7 @@ def bounds2img(w, s, e, n, zoom='auto',
146145
if zoom == 'auto':
147146
zoom = _calculate_zoom(w, e, s, n)
148147
tiles = []
148+
arrays = []
149149
for t in mt.tiles(w, s, e, n, [zoom]):
150150
x, y, z = t.x, t.y, t.z
151151
tile_url = url.replace('tileX', str(x)).replace('tileY', str(y)).replace('tileZ', str(z))
@@ -155,17 +155,15 @@ def bounds2img(w, s, e, n, zoom='auto',
155155
image = Image.open(image_stream).convert('RGB')
156156
image = np.asarray(image)
157157
# ---
158-
wt, st, et, nt = mt.bounds(t)
159-
xr = np.linspace(wt, et, image.shape[0])
160-
yr = np.linspace(st, nt, image.shape[1])
161-
tiles.append([image, xr, yr, 'lower'])
162-
merged, extent = merge_tiles(tiles)[:2]
158+
tiles.append(t)
159+
arrays.append(image)
160+
merged, extent = _merge_tiles(tiles, arrays)
163161
# lon/lat extent --> Spheric Mercator
164-
minX, maxX, minY, maxY = extent
165-
w, s = mt.xy(minX, minY)
166-
e, n = mt.xy(maxX, maxY)
167-
extent = w, e, s, n
168-
return merged[::-1], extent
162+
west, south, east, north = extent
163+
left, bottom = mt.xy(west, south)
164+
right, top = mt.xy(east, north)
165+
extent = left, right, bottom, top
166+
return merged, extent
169167

170168

171169
def _retryer(tile_url, wait, max_retries):
@@ -332,3 +330,31 @@ def _calculate_zoom(w, s, e, n):
332330
zoom_lat = np.ceil(np.log2(360 * 2. / lat_length))
333331
zoom = np.max([zoom_lon, zoom_lat])
334332
return int(zoom)
333+
334+
335+
def _merge_tiles(tiles, arrays):
336+
# create n_tilesx2 array with column of x and y coordinates
337+
tile_xys = np.array([(t.x, t.y) for t in tiles])
338+
339+
# get indices starting at zero
340+
indices = tile_xys - tile_xys.min(axis=0)
341+
342+
# the shape of individual tile images
343+
h, w, d = arrays[0].shape
344+
345+
# number of rows and columns in the merged tile
346+
n0, n1 = (indices+1).max(axis=0)
347+
348+
# empty merged tiles array to be filled in
349+
img = np.zeros((h*n0, w*n1, d), dtype=np.uint8)
350+
351+
for ind, arr in zip(indices, arrays):
352+
x, y = ind
353+
img[y*h:(y+1)*h, x*w:(x+1)*w, :] = arr
354+
355+
bounds = np.array([mt.bounds(t) for t in tiles])
356+
west, south, east, north = (
357+
min(bounds[:, 0]), min(bounds[:, 1]),
358+
max(bounds[:, 2]), max(bounds[:, 3]))
359+
360+
return img, (west, south, east, north)

0 commit comments

Comments
 (0)