# Copyright 2023-2024 Amazon.com, Inc. or its affiliates.
from math import degrees, floor, radians
from typing import Optional
from .coordinates import GeodeticWorldCoordinate
from .digital_elevation_model import DigitalElevationModelTileSet
[docs]
class GenericDEMTileSet(DigitalElevationModelTileSet):
"""
A generalizable tile set with a naming convention that can be described as a format string.
"""
def __init__(
self,
format_spec: str = "%od%oh/%ld%lh.dt2",
min_latitude_degrees: float = -90.0,
max_latitude_degrees: float = 90.0,
min_longitude_degrees: float = -180.0,
max_longitude_degrees: float = 180.0,
) -> None:
"""
Construct a tile set from a limited collection of configurable parameters. This implementation uses the
custom formatting directives %od (longitude degrees), %oh (longitude hemisphere), %ld (latitude degrees),
and %lh (latitude hemisphere) to allow users to create tile IDs that match a variety of situations.
For example the default format_spec of '%od%oh/%ld%lh.dt2' will generate tile ids like: '115e/45s.dt2'
which would match some common 1-degree cell based DEM file hierarchies.
:param format_spec: the format specification for the GeodeteticWorldCoordinate
:return: None
"""
super().__init__()
self.format_string = format_spec
self.min_latitude_degrees = min_latitude_degrees
self.max_latitude_degrees = max_latitude_degrees
self.min_longitude_degrees = min_longitude_degrees
self.max_longitude_degrees = max_longitude_degrees
[docs]
def find_tile_id(self, geodetic_world_coordinate: GeodeticWorldCoordinate) -> Optional[str]:
"""
This method creates tile IDs that based on the format string provided.
:param geodetic_world_coordinate: the world coordinate of interest
:return: the tile path or None if the DEM does not have coverage for this location
"""
longitude_degrees = floor(degrees(geodetic_world_coordinate.longitude))
latitude_degrees = floor(degrees(geodetic_world_coordinate.latitude))
# The SRTM mission only covers latitudes N59 through S56 so if the requested location is outside those
# ranges we know there is no file available for it.
if (
latitude_degrees > self.max_latitude_degrees
or latitude_degrees < self.min_latitude_degrees
or longitude_degrees > self.max_longitude_degrees
or longitude_degrees < self.min_longitude_degrees
):
return None
ul_coordinate = GeodeticWorldCoordinate([radians(longitude_degrees), radians(latitude_degrees), 0.0])
return f"{ul_coordinate:{self.format_string}}"