· 5 years ago · Jun 02, 2020, 02:36 PM
1from collections import defaultdict
2from typing import Tuple, List
3
4import mercantile
5import requests
6from rasterio import coords
7
8
9def get_tiles_from_field_metadata(key, channel, zooms) -> List[List[int]]:
10 # Tiles per defined zoom level with mercantile API.
11 response = requests.get(f"http://localhost:5000/metadata/{key}/{channel}")
12 west, south, east, north = response.json()['bounds']
13 tiles = list(mercantile.tiles(west, south, east, north, zooms))
14 final_tiles = [[tile.x, tile.y, tile.z] for tile in tiles]
15 return final_tiles
16
17
18def get_resulting_image_shape(key, channel, zooms, tile_size=(256, 256)) -> Tuple[int, int]:
19 # Final resulting image shape (height, width).
20 tiles = get_tiles_from_field_metadata(key, channel, zooms)
21 initial_x = tiles[0][0]
22 combined_arrays_by_x = defaultdict(list)
23 for tile in tiles:
24 local_x = tile[0]
25 if local_x == initial_x:
26 xyz_array = [tile[0], tile[1], tile[2]]
27 combined_arrays_by_x[local_x].append(xyz_array)
28 else:
29 initial_x = local_x
30 xyz_array = [tile[0], tile[1], tile[2]]
31 combined_arrays_by_x[initial_x].append(xyz_array)
32
33 image_height, image_width = len(combined_arrays_by_x.keys()) * tile_size[0], None
34 for key in combined_arrays_by_x:
35 image_width = len(combined_arrays_by_x[key]) * tile_size[1]
36 break
37 return image_height, image_width
38
39
40def get_tile_bounds(tile):
41 return coords.BoundingBox(*mercantile.xy_bounds(tile))
42
43
44def get_resulting_image_boundary(key, channel, zooms):
45 # Final resulting image boundary (x_min, y_min, x_max, y_max).
46 tiles = get_tiles_from_field_metadata(key, channel, zooms)
47 x_min, y_min, x_max, y_max = [], [], [], []
48 for index, tile in enumerate(tiles):
49 bbox = get_tile_bounds(tiles[index])
50 x_min.append(bbox.left)
51 y_min.append(bbox.bottom)
52 x_max.append(bbox.right)
53 y_max.append(bbox.top)
54
55 return min(x_min), min(y_min), max(x_max), max(y_max)