9
9
import pandas as pd
10
10
import rasterio as rio
11
11
from PIL import Image
12
- from cartopy .io .img_tiles import _merge_tiles as merge_tiles
13
12
from rasterio .transform import from_origin
14
13
from . import tile_providers as sources
15
14
@@ -146,6 +145,7 @@ def bounds2img(w, s, e, n, zoom='auto',
146
145
if zoom == 'auto' :
147
146
zoom = _calculate_zoom (w , e , s , n )
148
147
tiles = []
148
+ arrays = []
149
149
for t in mt .tiles (w , s , e , n , [zoom ]):
150
150
x , y , z = t .x , t .y , t .z
151
151
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',
155
155
image = Image .open (image_stream ).convert ('RGB' )
156
156
image = np .asarray (image )
157
157
# ---
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 )
163
161
# 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
169
167
170
168
171
169
def _retryer (tile_url , wait , max_retries ):
@@ -332,3 +330,31 @@ def _calculate_zoom(w, s, e, n):
332
330
zoom_lat = np .ceil (np .log2 (360 * 2. / lat_length ))
333
331
zoom = np .max ([zoom_lon , zoom_lat ])
334
332
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