Grid Point Code
Source on GitHub

How it is built

Ten characters, each one naming a cell inside the cell the character before it named. What decides which cell gets which character is three ideas: a serpentine over the world, a reflection at every level below it, and one reset in the middle. Between them they are the reason a plain string sort puts places in spatial order.

Every figure below is worked out by the library at build time, and the claims are checked rather than stated. The page fails to build if the construction stops behaving as it is described here.

The world in twenty-four blocks

The first character divides the world four ways by six. Six columns of 60° and four rows of 45°, which absorbs Earth's two-to-one aspect ratio in a single step and leaves every level below it dividing its parent evenly, five by five.

The blocks are lettered in a serpentine: west to east along the bottom row, then east to west along the next, snaking northward. Not left to right and back to the start, because that would put the end of one row and the start of the next at opposite edges of the world.

012345DC9876FGHJKLWTRPNM
The path runs from 0 at 90°S, 180°W to W at 45°N, 180°W. Twenty-four blocks and twenty-five symbols, so one is never used at this position: X begins no code, which is what leaves a reserved namespace nothing can collide with.

Inside a block: the reflection

Every level after the first divides its cell into a 5 × 5 grid, and the twenty-five symbols are laid into it in an order that depends on where the cell sits. Each axis is mirrored according to the parity of the digits accumulated in the other. That is the whole rule, and this is what it looks like, on two neighbouring blocks of the world, at the level below them:

J, 0° to 45°N, 0° to 60°E
K, 0° to 45°N, 60°E to 120°E

The right-hand block is the left one turned over, and that is what keeps the order joined up. The traversal runs west to east along this row of the world: it leaves the left block by X in the bottom-right corner, and takes up the right block at 0 in the bottom-left, the two cells touching across the boundary, marked above. Without the mirror it would have to fly back to the far corner of the world at the end of every cell.

One unbroken curve

Two levels of that, drawn: the 625 cells of one block, connected in the order their codes sort. Every step is to a cell sharing an edge with the one before it.

624 steps, of which 0 land anywhere but next door. That count is taken at build time from the drawing itself, not from the specification, and anything above zero stops the build.

The reset at level 6

Entering the sixth character, the accumulated parities are set back to zero. Without that, what characters six to ten mean would depend on the five before them, and they would name nothing on their own. With it, the last five characters depend only on the position inside the level-5 cell, so they mean the same thing everywhere on Earth:

#G3RJM-98NM943.6500, -79.3800781 up, 390 across, inside its own cell
#KDC8X-98NM922.9860, 72.4920781 up, 390 across, inside its own cell

The same five characters after the dash, one in Ontario and one in Gujarat, and the same position within the cell to the metre. That is what makes the short form recoverable rather than merely suggestive: five characters and a rough idea of where you are is enough to rebuild the whole code.

What it costs

The curve stays continuous inside every level-5 cell, but the traversal of one cell ends at its far corner while the next begins at its near one. So every crossing between level-5 cells is a jump, and it is a large one:

One step along the orderFromToApart
Anywhere inside a level-5 cell#86000-19M00#86000-19M013.25 m
Out of one level-5 cell into the next#86000-XXXXX#86001-000008.0 km

There are 9,374,999 of those jumps in the 91,552,734,374,999 steps of the full traversal, which leaves 99.99999 % of consecutive codes in touching cells. The trade was deliberate: a recoverable short form is worth more than the last decimal place of continuity, and a range query never notices because a window small enough to query lies inside one level-5 cell almost always.

Why any of it matters

Because the alphabet ascends in ASCII and the earlier characters are the more significant, comparing two codes as plain strings gives the same answer as comparing their positions along that curve. Sorting codes sorts places. Here are the specification's own sample points, sorted as text and nothing else:

CodePlaceLatitudeBand
#6LK4X-NRP0RSydney Opera House-33.86-45° to 0°, east to west
#C8HKC-13C80Machu Picchu-13.16-45° to 0°, east to west
#G3RJM-0M6DXCN Tower43.640° to 45°, west to east
#G3RJM-98NM9Toronto43.650° to 45°, west to east
#KDC8X-JM49XAhmedabad23.020° to 45°, west to east
#RDX9R-TN19TReykjavík64.1545° to 90°, east to west

South to north by band, and inside each band along the serpentine, which is why Toronto precedes Ahmedabad though it is further north, and why Sydney precedes Machu Picchu though it is further east. The two Toronto points share nine characters and land side by side.

No decoding, no custom collation, no separate index column. A database can answer ORDER BY code spatially with the ordinary string index it already has. This is why the digits come first in the alphabet: the other convention would have sorted C before 0, and every index built on a raw code would have been silently unordered.

The rules themselves are in the specification: the serpentine and the reflection in section 5, the ordering in section 11. The playground will resolve any point through all ten levels, and the seams page shows where this construction costs something.