"""Reference (non data-driven) layers.
Basemap, tiles, raster and graticule. Each delegates rendering to the
matching drawing helper on :class:`~mappyng.Map`.
"""
from __future__ import annotations
from typing import Any, Optional
from .base import Layer, RenderContext, register_layer, collect_set, _UNSET
[docs]
@register_layer
class BasemapLayer(Layer):
"""Plain background drawn from the map's main GeoDataFrame.
Parameters
----------
fill : str, optional
Fill colour as ``#RRGGBB`` (default from style or the map's
basemap colour override).
stroke : str, optional
Outline colour (default from style).
stroke_width : float, optional
Outline width (default from style).
z_index : int, optional
Render order (default 0).
visible : bool, optional
Whether the layer is drawn (default True).
Examples
--------
>>> m.add(BasemapLayer(fill="#f2efe9", stroke="#999999"))
"""
kind = "basemap"
requires_gdf = False
[docs]
def __init__(
self,
gdf: Optional[Any] = None,
*,
fill: Any = _UNSET,
stroke: Any = _UNSET,
stroke_width: Any = _UNSET,
z_index: int = 0,
visible: bool = True,
) -> None:
super().__init__(
gdf, z_index=z_index, visible=visible,
**collect_set(fill=fill, stroke=stroke, stroke_width=stroke_width),
)
[docs]
def render(self, ctx: RenderContext) -> None:
ctx.map._render_basemap(**dict(self.params))
self._rendered = True
[docs]
@register_layer
class TileLayer(Layer):
"""XYZ raster tile backdrop.
Parameters
----------
source : str, optional
Provider alias (e.g. ``"cartodb_positron"``, ``"osm"``,
``"satellite"``) or a URL template with ``{x}``, ``{y}``, ``{z}``
placeholders.
zoom : int or str, optional
Zoom level, or ``"auto"`` (default) to derive it from the bbox.
zoom_offset : int, optional
Added to the auto-calculated zoom (e.g. ``-1`` for lighter tiles).
opacity : float, optional
Tile opacity in ``[0, 1]`` (default 1).
z_order : int, optional
SVG stacking order (default below the basemap).
timeout : float, optional
HTTP request timeout in seconds (default 10).
cache : bool, optional
Cache tiles on disk (default True).
cache_dir : str, optional
Cache directory (default ``~/.cache/mappyng/tiles``).
on_cartouches : bool, optional
Draw on cartouche viewports (default True).
on_zoom : bool, optional
Draw on the zoom viewport (default True).
max_tiles : int, optional
Safety cap on tiles downloaded per viewport (default 64).
warp_scale : float, optional
Output resolution relative to the content area (default 1.5).
extra_zoom_levels : int, optional
Number of coarser zoom levels to also fetch and blend (default 0).
z_index : int, optional
Render order among layers (default 0).
visible : bool, optional
Whether the layer is drawn (default True).
Examples
--------
>>> m.add(TileLayer())
>>> m.add(TileLayer(source="satellite", opacity=0.7))
"""
kind = "tile"
requires_gdf = False
[docs]
def __init__(
self,
gdf: Optional[Any] = None,
*,
source: Any = _UNSET,
zoom: Any = _UNSET,
zoom_offset: Any = _UNSET,
opacity: Any = _UNSET,
z_order: Any = _UNSET,
timeout: Any = _UNSET,
cache: Any = _UNSET,
cache_dir: Any = _UNSET,
on_cartouches: Any = _UNSET,
on_zoom: Any = _UNSET,
max_tiles: Any = _UNSET,
warp_scale: Any = _UNSET,
extra_zoom_levels: Any = _UNSET,
z_index: int = 0,
visible: bool = True,
) -> None:
super().__init__(
gdf, z_index=z_index, visible=visible,
**collect_set(
source=source, zoom=zoom, zoom_offset=zoom_offset,
opacity=opacity, z_order=z_order, timeout=timeout,
cache=cache, cache_dir=cache_dir, on_cartouches=on_cartouches,
on_zoom=on_zoom, max_tiles=max_tiles, warp_scale=warp_scale,
extra_zoom_levels=extra_zoom_levels,
),
)
[docs]
def render(self, ctx: RenderContext) -> None:
ctx.map._render_tile(dict(self.params))
self._rendered = True
[docs]
@register_layer
class RasterLayer(Layer):
"""Raster image overlay.
Parameters
----------
paths : dict
Mapping of region name to GeoTIFF path (required). Each viewport
picks the raster whose footprint overlaps its bbox.
opacity : float, optional
Raster opacity in ``[0, 1]`` (default 1).
on_zoom : bool, optional
Draw on the zoom viewport (default True).
on_cartouches : bool, optional
Draw on cartouche viewports (default True).
z_index : int, optional
Render order among layers (default 0).
visible : bool, optional
Whether the layer is drawn (default True).
Examples
--------
>>> m.add(RasterLayer(paths={"metropole": "data/dem.tif"}, opacity=0.8))
"""
kind = "raster"
requires_gdf = False
[docs]
def __init__(
self,
gdf: Optional[Any] = None,
*,
paths: Any = _UNSET,
opacity: Any = _UNSET,
on_zoom: Any = _UNSET,
on_cartouches: Any = _UNSET,
z_index: int = 0,
visible: bool = True,
) -> None:
super().__init__(
gdf, z_index=z_index, visible=visible,
**collect_set(
paths=paths, opacity=opacity, on_zoom=on_zoom,
on_cartouches=on_cartouches,
),
)
[docs]
def validate(self) -> None:
if not self.params:
raise ValueError(
"RasterLayer needs parameters describing the raster to "
"draw (e.g. a path or array); none were given, so there "
"is nothing to overlay."
)
[docs]
def render(self, ctx: RenderContext) -> None:
ctx.map._render_raster(dict(self.params))
self._rendered = True
[docs]
@register_layer
class GraticuleLayer(Layer):
"""Latitude/longitude grid.
Parameters
----------
step : float, optional
Spacing between lines in degrees (default 10).
stroke : str, optional
Line colour as ``#RRGGBB`` (default ``"#aaaaaa"``).
opacity : float, optional
Stroke opacity in ``[0, 1]`` (default 0.5).
stroke_width : float, optional
Line width (default 0.5).
dash : str, optional
SVG dash pattern (default ``"4 2"``).
position : str, optional
``"background"`` (default) draws the grid above the ocean but
below the data; ``"top"`` draws it over everything, which suits
globe-style maps.
z : int, optional
Explicit stacking order, overriding ``position``.
z_index : int, optional
Render order among layers (default 0).
visible : bool, optional
Whether the layer is drawn (default True).
Examples
--------
>>> m.add(GraticuleLayer(step=5.0, stroke="#888888", opacity=0.4))
"""
kind = "graticule"
requires_gdf = False
[docs]
def __init__(
self,
gdf: Optional[Any] = None,
*,
step: Any = _UNSET,
stroke: Any = _UNSET,
opacity: Any = _UNSET,
stroke_width: Any = _UNSET,
dash: Any = _UNSET,
position: Any = _UNSET,
z: Any = _UNSET,
z_index: int = 0,
visible: bool = True,
) -> None:
super().__init__(
gdf, z_index=z_index, visible=visible,
**collect_set(
step=step, stroke=stroke, opacity=opacity,
stroke_width=stroke_width, dash=dash, position=position, z=z,
),
)
[docs]
def render(self, ctx: RenderContext) -> None:
ctx.map._render_graticule(dict(self.params))
self._rendered = True