MapMath

CHAPTER 05

Web Mercator and tile math

How every web map (Google, OSM, Mapbox) tiles the world, with the formulas to convert lat/lon to tile coordinates.

3 min readfree

Almost every web map (Google, OSM, Mapbox, Leaflet) uses Web Mercator (EPSG:3857). It's Mercator with one important simplification: it treats the Earth as a sphere of radius 6,378,137 m even though the underlying data is on the WGS84 ellipsoid. This introduces small errors but makes the math fast.

The reason the entire web mapping ecosystem converged on this standard is practical: tiles precomputed by one provider can be layered with data from another. Google, Apple, Microsoft Bing, and OpenStreetMap all publish tiles at the same zoom levels covering the same geographic cells — your map client can mix them freely because the math is identical.

Tile grid explorer

z=2 · 4×4 = 16 tiles

0/01/02/03/00/11/12/1← your point3/10/21/22/23/20/31/32/33/3
tile: 2/2/1
total: 16 tiles at z2

The slippy map tile system

The world is divided into a quadtree of square tiles, each 256 × 256 pixels:

optional — skip if familiarrefresher
  • At zoom 0, the entire world is one tile.
  • At zoom 1, it's a 2×2 grid (4 tiles).
  • At zoom z, it's 2z×2z2^z \times 2^z tiles (4z4^z total).

A tile is identified by three numbers (z, x, y):

  • z — zoom level
  • x — column, increases east (0 at lon = −180°)
  • y — row, increases south (0 at the top, near lat = 85.05°)

The y-axis pointing south (top = 0) follows screen convention: pixel coordinates on a display start at the top-left corner. Latitude 85.05° is the Web Mercator cutoff — at that latitude, the Mercator y-value equals x, producing a square world map.

Tile URL example: https://tile.openstreetmap.org/{z}/{x}/{y}.png

Lat/lon → tile coordinates

n=2zn = 2^z xtile=nλ+180360x_{\text{tile}} = \left\lfloor n \cdot \frac{\lambda + 180}{360} \right\rfloor ytile=n1ln(tanφ+secφ)/π2y_{\text{tile}} = \left\lfloor n \cdot \frac{1 - \ln(\tan\varphi + \sec\varphi) / \pi}{2} \right\rfloor

(φ in radians here)

The x formula is just linear interpolation of longitude into [0, n). The y formula applies the Mercator projection and then normalises it from [0, 1] top-to-bottom.

In JavaScript:

function lonLatToTile(lon, lat, zoom) {
  const n = 2 ** zoom;
  const x = Math.floor(n * (lon + 180) / 360);
  const latRad = lat * Math.PI / 180;
  const y = Math.floor(
    n * (1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2
  );
  return { x, y, z: zoom };
}

Tile coordinates → lat/lon (top-left corner)

λ=x2z360180\lambda = \frac{x}{2^z} \cdot 360 - 180 φ=arctan ⁣(sinh ⁣(π(12y2z)))180π\varphi = \arctan\!\left(\sinh\!\left(\pi \cdot \left(1 - \frac{2y}{2^z}\right)\right)\right) \cdot \frac{180}{\pi}
function tileToLonLat(x, y, z) {
  const n = 2 ** z;
  const lon = x / n * 360 - 180;
  const lat = Math.atan(Math.sinh(Math.PI * (1 - 2 * y / n))) * 180 / Math.PI;
  return { lon, lat };
}

Note that this returns the top-left corner of the tile. To get the bounding box of a tile, call it for (x, y) and (x+1, y+1).

Worked example

Q: Which tile contains Lahore (31.5204, 74.3587) at zoom 12?

n=212=4096n = 2^{12} = 4096 x=4096×(74.3587+180)/360=2893.8=2893x = \lfloor 4096 \times (74.3587 + 180) / 360 \rfloor = \lfloor 2893.8 \rfloor = 2893 y=4096×0.4077=1670.0=1670y = \lfloor 4096 \times 0.4077 \rfloor = \lfloor 1670.0 \rfloor = 1670

So tile (12, 2893, 1670). You can check by visiting https://tile.openstreetmap.org/12/2893/1670.png.

Resolution at a given zoom

How many meters does one pixel represent? At the equator:

resolution=2πR2562z156,543.032z m/px\text{resolution} = \frac{2\pi R}{256 \cdot 2^z} \approx \frac{156{,}543.03}{2^z} \text{ m/px}

At any latitude φ, multiply by cosφ\cos\varphi.

Zoommeters/pixel (equator)
0156,543
54,892
10152.9
154.78
180.60
200.15

Resolution drops by half with each zoom increment — each zoom level doubles the number of tiles in each dimension, covering the same area with four times the pixels.

References

3 sources
  1. [1]

    Open Geospatial Consortium (2007).

    OpenGIS Web Map Tile Service Implementation Standard.”

    OGC 07-057r7

    The WMTS standard formalising the slippy-map tile grid used by Google, OSM, and Mapbox.

  2. [2]

    Simonds, L. (2006).

    Slippy Map Tilenames.”

    OpenStreetMap Wiki

    The original derivation of the z/x/y tile coordinate formulas from Web Mercator.

  3. [3]

    Esri (2012).

    Well-Known Scale Sets.”

    ArcGIS REST API documentation

    Documents the standard zoom-level resolution table (metres per pixel at each zoom level).