diff --git a/docs/source/reference/io.rst b/docs/source/reference/io.rst index 1eebec5d7..72b69b756 100644 --- a/docs/source/reference/io.rst +++ b/docs/source/reference/io.rst @@ -63,6 +63,7 @@ automatically load the proper tile and resolution depending on the desired domai MapboxTiles OrdnanceSurvey QuadtreeTiles + StadiaMapsTiles Stamen Open Geospatial Consortium (OGC) diff --git a/lib/cartopy/io/img_tiles.py b/lib/cartopy/io/img_tiles.py index 76b939d65..fcc12f5d4 100644 --- a/lib/cartopy/io/img_tiles.py +++ b/lib/cartopy/io/img_tiles.py @@ -320,6 +320,66 @@ def _image_url(self, tile): return f'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png' +class StadiaMapsTiles(GoogleWTS): + """ + Retrieves tiles from stadiamaps.com. + + For a full reference on the styles available please see + https://docs.stadiamaps.com/themes/. A few of the specific styles + that are made available are ``alidade_smooth``, ``stamen_terrain`` and + ``osm_bright``. + + Using the Stadia Maps API requires including an attribution. Please see + https://docs.stadiamaps.com/attribution/ for details. + + For most styles that means including the following attribution: + + `© Stadia Maps `_ + `© OpenMapTiles `_ + `© OpenStreetMap contributors `_ + + with Stamen styles *additionally* requiring the following attribution: + + `© Stamen Design `_ + + Parameters + ---------- + apikey : str, required + The authentication key provided by Stadia Maps to query their APIs + style : str, optional + Name of the desired style. Defaults to ``alidade_smooth``. + See https://docs.stadiamaps.com/themes/ for a full list of styles. + resolution : str, optional + Resolution of the images to return. Defaults to an empty string, + standard resolution (256x256). You can also specify "@2x" for high + resolution (512x512) tiles. + cache : bool or str, optional + If True, the default cache directory is used. If False, no cache is + used. If a string, the string is used as the path to the cache. + """ + + def __init__(self, + apikey, + style="alidade_smooth", + resolution="", + cache=False): + super().__init__(cache=cache) + self.apikey = apikey + self.style = style + self.resolution = resolution + if style == "stamen_watercolor": + # Known style that has the jpg extension + self.extension = "jpg" + else: + self.extension = "png" + + def _image_url(self, tile): + x, y, z = tile + return ("http://tiles.stadiamaps.com/tiles/" + f"{self.style}/{z}/{x}/{y}{self.resolution}.{self.extension}" + f"?api_key={self.apikey}") + + class Stamen(GoogleWTS): """ Retrieves tiles from maps.stamen.com. Styles include @@ -351,6 +411,9 @@ class Stamen(GoogleWTS): def __init__(self, style='toner', desired_tile_form=None, cache=False): + warnings.warn("The Stamen styles are no longer served by Stamen and " + "are now served by Stadia Maps. Please use the " + "StadiaMapsTiles class instead.") # preset layer configuration layer_config = { diff --git a/lib/cartopy/tests/test_img_tiles.py b/lib/cartopy/tests/test_img_tiles.py index a7d4f0cd4..792a7be76 100644 --- a/lib/cartopy/tests/test_img_tiles.py +++ b/lib/cartopy/tests/test_img_tiles.py @@ -214,6 +214,22 @@ def test_mapbox_style_tiles_api_url(): assert url_str == exp_url +@pytest.mark.parametrize("style,extension,resolution", [ + ("alidade_smooth", "png", ""), + ("alidade_smooth", "png", "@2x"), + ("stamen_watercolor", "jpg", "")]) +def test_stadia_maps_tiles_api_url(style, extension, resolution): + apikey = 'foo' + tile = [0, 1, 2] + exp_url = ('http://tiles.stadiamaps.com/tiles/' + f'{style}/2/0/1{resolution}.{extension}' + '?api_key=foo') + + sample = cimgt.StadiaMapsTiles(apikey, style=style, resolution=resolution) + url_str = sample._image_url(tile) + assert url_str == exp_url + + def test_ordnance_survey_tile_styles(): """ Tests that setting the Ordnance Survey tile style works as expected.