Source code for sensai.geoanalytics.map_tiles

"""
Utility functions and classes for geographic coordinates
"""

import math
from typing import Tuple, List, Generator

from ._globalmaptiles import GlobalMercator
from .geo_coords import GeoRect

EARTH_RADIUS = 6371000
EARTH_CIRCUMFERENCE = 2 * math.pi * EARTH_RADIUS
LATITUDE_PER_METRE = 360.0 / EARTH_CIRCUMFERENCE


[docs]class MapTile: def __init__(self, tx: int, ty: int, rect: GeoRect, zoom: int): self.tx = tx self.ty = ty self.rect = rect self.zoom = zoom
[docs]class MapTiles: def __init__(self, zoom=13): self.zoom = zoom self._mercator = GlobalMercator() self._tiles = {} def _get_tile(self, tx, ty): key = (tx, ty) tile = self._tiles.get(key) if tile is None: tile = MapTile(tx, ty, GeoRect(*self._mercator.TileLatLonBounds(tx, ty, self.zoom)), self.zoom) self._tiles[key] = tile return tile
[docs] def iter_tile_coordinates_in_rect(self, rect: GeoRect) -> Generator[Tuple[int, int], None, None]: tx1, ty1 = self._mercator.LatLonToTile(rect.minLat, rect.minLon, self.zoom) tx2, ty2 = self._mercator.LatLonToTile(rect.maxLat, rect.maxLon, self.zoom) tx_min = min(tx1, tx2) tx_max = max(tx1, tx2) ty_min = min(ty1, ty2) ty_max = max(ty1, ty2) for tx in range(tx_min, tx_max+1): for ty in range(ty_min, ty_max+1): yield tx, ty
[docs] def get_tiles_in_rect(self, rect: GeoRect) -> List[MapTile]: return [self._get_tile(tx, ty) for tx, ty in self.iter_tile_coordinates_in_rect(rect)]
[docs] def get_tile(self, lat: float, lon: float) -> MapTile: return self._get_tile(*self.get_tile_coordinates(lat, lon))
[docs] def get_tile_coordinates(self, lat: float, lon: float) -> Tuple[int, int]: return self._mercator.LatLonToTile(lat, lon, self.zoom)