Skip to main content

Concepts

Hierarchical geospatial indexing (S2/H3)

Intuition

Imagine dividing the world map into big numbered squares, then covering each square with smaller numbered squares (that fit exactly or nearly so), and so on until you reach pieces smaller than one square meter. Instead of recording the exact position of each occurrence, you record only the number of the piece where it fell, and all you need to do is choose the size of the piece to count how many occurrences there are in areas the size of a neighborhood, a city or a country. Because the pieces have comparable size and shape and don't move, the counts from different regions can be compared with each other.

How it works

Instead of storing latitude and longitude, the system divides the Earth into a hierarchy of cells and represents each point by the cell it falls in, identified by a 64-bit integer. In S2, the six faces of a cube are projected onto the sphere and each cell is recursively subdivided into four children, from level 0 to 30; the identifier of a level-k cell has 3 face bits, k pairs of bits that pick the child, a 1 bit, and zeros up to 64 bits, and it is numbered along a curve that links six Hilbert curves, so that nearby identifiers correspond to nearby cells. Because in S2 each square subdivides exactly into four child squares (aperture 4), truncating an indexed point to its parent cell always keeps it inside that cell. H3 builds the grid on the faces of an icosahedron, with hexagons at resolutions 0 to 15, and each resolution uses aperture 7, meaning each hexagon has one seventh of the area of the hexagon at the previous resolution (measured on the icosahedron, before projection onto the sphere); since you can't tile the icosahedron with hexagons alone, each resolution contains exactly 12 pentagons, and resolution 0 has 122 base cells. Hexagons have a single class of neighbors, the ones that share an edge, which simplifies smoothing and convolutions because you only need to count distance in cells; but they don't subdivide exactly into seven hexagons, so in H3 logical containment in the index is exact and geometric containment is approximate. A region becomes a set of cells at different levels: in H3, compactCells does this and, in the example from Uber's post, California goes from 10,633 cells at resolution 6 to 901 cells of resolutions up to 6, and uncompactCells recovers the original set. In S2, allowing more cells approximates the region better, at the cost of a larger set. When the application needs exact borders, the H3 documentation suggests treating the hierarchy as logical and using the grid as an optimization before a precise point-in-polygon test.

In practice

Uber's engineering post uses H3 to group marketplace events into hexagons and measure supply and demand per cell, for example to compute surge pricing. The choice between the two depends on what matters most: S2 offers exact containment across levels, while H3 offers uniform neighborhoods, which simplifies smoothing and convolutions over adjacent cells. In both, the resolution or level defines the granularity of the analysis, and covering a region with a few cells is cheap but approximate.

Use it in a design

Practice the cases that rely on this concept in the System Design school.