Skip to main content

Tile Matrix Sets

What a tile matrix set is

A tile matrix set — OGC's name for a tiling scheme — defines, for every zoom level, the coordinate reference system, how many columns and rows the world is cut into, and where the origin sits. Two servers agree on what 10/511/340 means only if they agree on the scheme.

Shigola carries the OGC register of tile matrix sets as data, resolves grids through a registry, and lets each map declare which schemes it may be requested in.

The schemes this build serves

Three, and they are the three whose tile ↔ coordinate conversions are closed-form arithmetic over WGS 84 — no PROJ backend, no cgo:

tileMatrixSetIdCRSAxis orderMatrix at zoom zZooms
WebMercatorQuadEPSG:3857easting, northing2^z × 2^z0–24
WorldCRS84QuadOGC:CRS84longitude, latitude2·2^z × 2^z0–23
WGS1984QuadEPSG:4326latitude, longitude2·2^z × 2^z0–23

WebMercatorQuad is the familiar one: square matrix, square tiles, the scheme every web map slippy URL assumes. It is the default.

WorldCRS84Quad and WGS1984Quad are geographic. Their matrix is twice as wide as it is tall — at zoom 0 there are two tiles, not one — because 360° of longitude is covered at the same tile size as 180° of latitude. The two differ only in the CRS they declare and therefore in axis order: WorldCRS84Quad uses OGC:CRS84, which is explicitly longitude/latitude; WGS1984Quad uses EPSG:4326, whose authoritative axis order is latitude/longitude. Both index the same ground with the same matrix shape.

A z/x/y in one scheme is different ground in another. This is not a subtlety you can ignore — it is why the cache key changed and why the tile row and column are validated separately.

Schemes that ship but are not served

The build bundles all thirteen tile matrix sets from the OGC register, and /tileMatrixSets lists only the ones it can actually serve. The other ten are registered and report precisely why they are unavailable rather than silently going missing:

SchemeWhy it is not served
WorldMercatorWGS84Quad, CanadianNAD83_LCC, EuropeanETRS89_LAEAQuad, NZTM2000Quad, UTM31WGS84Quad, UPSArcticWGS84Quad, UPSAntarcticWGS84Quad, LINZAntarticaMapTilegridNeeds a coordinate transformation backend this build does not wire up.
GNOSISGlobalGrid, CDB1GlobalGridVariable-width tile matrices — these grids coalesce columns near the poles, and the tile pipeline assumes one column index maps to one matrix column.

Naming an unavailable scheme in a config is a startup error that lists what is available, not a silent fallback.

Configuring a map's schemes

tile_matrix_sets is set per map, not per layer or per provider. It is optional; a map that omits it is served in every scheme this build supports.

[[maps]]
name = "parks"
# The tiling schemes this map may be requested in.
# Omit the key entirely to offer every scheme this build serves.
tile_matrix_sets = ["WebMercatorQuad", "WorldCRS84Quad"]
  • Omitted → every scheme the build serves.
  • Every request names its scheme, so no entry is a serving default. What the list decides is which schemes a collection offers, and the order its tilesets are listed in.
  • A map's layer-collections offer exactly the schemes their map does.
warning

A map served in more than one scheme needs its layer SQL written for that. The provider hands the tile-space mapping to ST_AsMVTGeom, which spaces a tile across whichever envelope it is given — so the envelope has to be the scheme's, through !TILE_BBOX!, with the geometry transformed to !TILE_SRID! to match. A layer that clips against !BBOX! instead is only correct in a scheme whose CRS happens to be the layer's own; in any other it is skewed, worst at the shallow zooms. See Layer SRID and tiling scheme CRS.

The order matters to cache seed and cache purge

Serving reads no default off this list, but the CLI does. Without --tile-matrix-set, a run scoped with --map takes the first entry, in the order you wrote it — nothing sorts or prioritises it:

A map's tile_matrix_setscache seed --map=parks seeds
["WorldCRS84Quad", "WebMercatorQuad"]WorldCRS84Quad
["WebMercatorQuad", "WorldCRS84Quad"]WebMercatorQuad
key omittedWebMercatorQuad

Swapping the two entries changes what the same command seeds. The third row is why: a map that names no schemes is given every scheme the build serves, in the order WebMercatorQuad, WGS1984Quad, WorldCRS84Quad — WebMercatorQuad deliberately first rather than sorted, since sorting alone would put WGS1984Quad there (G sorts before e) and quietly change which pyramid an unconfigured map seeds.

Without --map at all, a run always uses WebMercatorQuad, whatever any map lists. That is a separate rule, not the first entry of anything.

A run that names no scheme says which one it picked. Both cases log a warning naming the scheme and where it came from, because the wrong one is not visibly wrong — the run reports success either way:

WARN cache seed/purge: no --tile-matrix-set given, using WorldCRS84Quad
(the first scheme map "parks" lists). one run covers one scheme --
pass --tile-matrix-set to choose it

Full detail in Cache seeding and purging.

Why a scheme id and not an SRID

A tiling scheme is named by its tileMatrixSetId, not by the SRID of its CRS, because an SRID cannot identify one: WorldCRS84Quad and WGS1984Quad are both EPSG:4326, so "4326" names two schemes. The id is what OGC uses, and it is what appears in tile URLs, cache keys and /tileMatrixSets.

Where an SRID still has to be interpreted — an internal caller that only knows a projection — 3857 resolves to WebMercatorQuad and 4326 to WorldCRS84Quad.

Changing a map's schemes changes its cache keys. Purge and re-seed the affected maps; see Cache Seeding and Purging.

Where schemes show up

  • /tileMatrixSets lists every servable scheme; /tileMatrixSets/{id} returns its full OGC definition, verbatim from the bundled register. See OGC API - Tiles.
  • Tile URLs carry the scheme on OGC routes: /collections/{collectionId}/tiles/{tileMatrixSetId}/{tileMatrix}/{tileRow}/{tileCol}. Every tile request names a scheme; there is no route that serves a map's default implicitly.
  • Cache keys begin with it: {tileMatrixSetId}/{map}/{layer}/{z}/{x}/{y}.
  • cache seed / cache purge take --tile-matrix-set; one run covers one scheme.

Credit

The tms package is a faithful Go port of developmentseed/morecantile 7.0.3 (MIT © Development Seed) — its document model, tile algorithms, the thirteen bundled grid definitions, and its test suite, which serves as the port's correctness oracle. See About Shigola.