Note
Go to the end to download the full example code.
Slippy map tiles#
Standard web-map tiles (OpenStreetMap z/x/y) in Web Mercator. Square in the projected plane; the de-facto grid for tile servers and map caches.
The interactive explorer below is rendered with
deck.gl and behaves like the
h3geo.org map: the tile zoom follows the map zoom and
tiles are generated in the browser for whatever is in view. Two neighbouring
zooms are shown at once — the current level with a darker, heavier border and
the next finer level with a lighter, thinner one — so the quadtree nesting stays
visible. The z/x/y tile maths is the exact one in m3s.slippy, reproduced
in JavaScript so the tile ids and edges match M3S. GIS-native (lon, lat)
order is used throughout.
Why Slippy?#
Because everything else already speaks it: OpenStreetMap, tile servers, map caches and CDNs all address the world as z/x/y Web-Mercator tiles. If your cells end up feeding a tile pipeline, this is the zero-friction choice. The geometry is identical to Quadkey grid; only the id differs (a z/x/y triplet here, a prefix string there). The caveats are shared too: tile area shrinks toward the poles and coverage stops at ±85.05°. When cells must have comparable ground areas, use EA-Quad grid instead.
Usage#
Encode a point and tile a small bounding box around Paris — same result in Python and JavaScript (both call the shared core):
import m3s
cell = m3s.Slippy.from_geometry((2.35, 48.86)) # (lon, lat)
cells = m3s.Slippy.from_geometry((2.2, 48.8, 2.4, 48.9)) # bbox
print(cell.id, len(cells))
import * as m3s from "m3s";
await m3s.ready();
const cell = m3s.Slippy.fromPoint(2.35, 48.86); // (lon, lat)
const cells = m3s.Slippy.fromBbox([2.2, 48.8, 2.4, 48.9]); // bbox
console.log(cell.id, cells.length);
from _deckmap import DeckExplorer, read_grid_js
DeckExplorer(
center=(9.5, 48.5),
zoom=5,
grid_js=read_grid_js("slippy"),
hover="#44AA99",
wasm=True,
)
Total running time of the script: (0 minutes 0.011 seconds)