How It Works¶
The Problem¶
GPS coordinates like (5.34519, -4.02868) are precise but unwieldy. They're hard for humans to remember, communicate, or write on paper. In regions without postal addresses, there's no alternative — until now.
The Solution: Hilbert Curve Bijection¶
Yoro uses a 2D Hilbert space-filling curve to create a reversible mapping between GPS coordinates and short alphanumeric codes.
Step 1: Domain Bounding Box¶
Each domain (e.g. CI for Cote d'Ivoire) defines a geographic bounding box:
This constrains the coordinate space, giving better resolution per character than a global system.
Step 2: Grid Discretization¶
The bounding box is divided into a 2^p × 2^p grid, where p is the Hilbert order (precision). For p=12, that's a 4096×4096 grid = 16.7 million cells over Cote d'Ivoire.
The GPS coordinate (lat, lon) is mapped to a grid cell (x, y):
x = floor((lon - lon_min) / (lon_max - lon_min) × 2^p)
y = floor((lat - lat_min) / (lat_max - lat_min) × 2^p)
Step 3: Hilbert Curve Index¶
The 2D grid position (x, y) is converted to a 1D Hilbert distance d using the standard Hilbert curve algorithm. This is the key insight: the Hilbert curve preserves spatial locality — nearby points in 2D map to nearby values in 1D.
Step 4: Base-29 Encoding¶
The Hilbert distance d is encoded in base-29 using an alphabet designed to avoid ambiguity:
Excluded characters: 0 (confused with O), 1 (confused with I/L), I, L, O, U (confused with V).
Step 5: Domain Prefix¶
The final code is {domain}-{base29}, e.g. CI-PV9XD.
Decoding¶
Decoding reverses the process exactly:
- Split
CI-PV9XD→ domainCI, codePV9XD - Base-29 → Hilbert distance
d - Hilbert distance → grid position
(x, y) - Grid position → GPS center of cell
(lat, lon)+ bounding box
Why Hilbert Curves?¶
Why not just use a simple row-major grid? The Hilbert curve has a unique property: it preserves spatial locality better than any other space-filling curve. Two codes that are numerically close are also geographically close. This means:
- Prefix sharing — codes in the same area tend to share leading characters
- Neighbor queries — the 8 adjacent cells can be computed with simple arithmetic
- Range queries — a bounding box maps to a small set of Hilbert index ranges
The Base-29 Quantization Effect¶
The code length k is determined by:
Since k must be an integer, several values of p produce the same k. Only the canonical precision — the highest p for each k — fully exploits the address space. Use yoro.precision_levels() to see them, and yoro.snap_precision(p) to check which canonical p your requested value maps to.