# Yoro

**Geographic addressing via Hilbert curves — GPS ↔ compact alphanumeric codes.**

*"Yoro" means "place" in Manding (West Africa).*

---

## The Problem

In many parts of the world — especially rural Africa — **street addresses don't exist**. GPS coordinates like `5.34519, -4.02868` are precise but impossible to remember, communicate by phone, or write on a receipt.

## The Solution

Yoro turns any GPS coordinate into a short, human-readable code:

```
(5.345, -4.028)  →  CI-PV9XD
```

And back:

```
CI-PV9XD  →  (5.345..., -4.028...)  + cell bounds + neighbors
```

It uses [Hilbert space-filling curves](concepts/how-it-works.md) to preserve spatial locality: **nearby places get similar codes**.

## Try It

```bash
pip install yoro
```

```python
import yoro

# Encode a location in Abidjan
code = yoro.encode(5.345, -4.028, domain="CI")
print(code)  # "CI-PV9XD"

# Decode it back
result = yoro.decode(code)
print(result["lat"], result["lon"])    # center of the cell
print(result["bounds"])                 # exact cell rectangle

# Find the 8 adjacent cells
for neighbor in yoro.neighbors(code):
    print(neighbor)

# What precision levels are available?
for level in yoro.precision_levels(domain="CI"):
    print(f"{level['code_length']} chars → ~{level['resolution_m']:.0f}m")
```

## What Can You Build With Yoro?

### :material-truck-delivery: Delivery & Logistics
Use 5-character codes (~170m) as delivery addresses. Drivers enter the code → the app shows the exact cell on a map. No street name needed.

### :material-tractor: Agricultural Traceability
Assign codes to parcels, cooperatives, and producers for supply chain tracking. Built for [EUDR compliance](https://environment.ec.europa.eu/topics/forests/deforestation/regulation-deforestation-free-products_en).

### :material-map-marker: Field Data Collection
Field agents encode GPS locations offline — Yoro is pure math, no internet required. Sync codes later.

### :material-grid: Spatial Indexing
Use Hilbert codes for efficient range queries: nearby objects share code prefixes. Faster than lat/lon range scans.

## How It Works (30 seconds)

1. Each country is a **domain** with a bounding box (`CI` = Cote d'Ivoire)
2. The bounding box is divided into a **2^p × 2^p grid** (p = precision)
3. Each cell gets a unique index via the **Hilbert curve** (preserves spatial locality)
4. That index is encoded in **base-29** (alphabet without ambiguous chars like 0/O, 1/I/L)
5. Result: `{domain}-{code}` e.g. `CI-PV9XD`

[Learn more →](concepts/how-it-works.md)

## Precision Levels

| Code Length | Resolution (CI) | Use Case |
|:-----------:|:---------------:|----------|
| 3 chars | ~5.5 km | City/district |
| 4 chars | ~1.4 km | Neighborhood |
| **5 chars** | **~170 m** | **Block/building (default)** |
| 6 chars | ~43 m | Building entrance |
| 7 chars | ~5.4 m | Room/spot |
| 8 chars | ~1.35 m | Meter precision |

[All precision levels →](concepts/precision.md)

## Integrations

=== "Pure Python"

    Zero dependencies. Works anywhere Python runs.

    ```python
    import yoro
    code = yoro.encode(6.8, -5.3, domain="CI")
    ```

=== "Django"

    GeoDjango model, views, admin, migrations.

    Model field with interactive map widget — works in Django admin.

    ```python
    # settings.py
    INSTALLED_APPS = [..., "yoro.django"]

    # In your model — one line
    from yoro.django.fields import YoroField

    class Shop(models.Model):
        name = models.CharField(max_length=100)
        address = YoroField(domain="CI")  # ← map picker in forms

    # Auto-encode from GPS
    shop.address = (5.345, -4.028)  # → "CI-PV9XD"
    ```

    [Django guide →](integrations/django.md) · [Django + Leaflet →](guides/django-leaflet.md)

=== "FastAPI"

    HTTP API with OpenAPI docs.

    ```bash
    pip install yoro[fastapi]
    yoro serve --port 8000
    # → http://localhost:8000/docs
    ```

=== "CLI"

    Command-line encoding/decoding.

    ```bash
    $ yoro encode 5.345 -4.028 --domain CI
    CI-PV9XD

    $ yoro precisions --domain CI
       p  k (chars)    resolution
      12          5      172.90 m  ← default
      19          8        1.35 m
    ```

=== "Leaflet Map"

    Interactive map with Hilbert grid overlay.

    [Django + Leaflet guide →](guides/django-leaflet.md) · [Grid overlay →](guides/grid-overlay.md) · [Tile providers →](guides/tile-providers.md)

=== "Mobile"

    React Native, Kivy, offline-first.

    [Mobile guide →](guides/mobile.md)

## Guides

| Guide | Description |
|-------|-------------|
| [Django + Leaflet Map](guides/django-leaflet.md) | Full Django app with interactive map, click-to-encode, code search |
| [Hilbert Grid Overlay](guides/grid-overlay.md) | Render the cell grid on Leaflet with zoom-adaptive precision |
| [Tile Providers](guides/tile-providers.md) | OSM, satellite, terrain, offline MBTiles, NICFI for EUDR |
| [Python GUI](guides/python-gui.md) | Desktop app with tkintermapview, Streamlit, PyQt examples |
| [Batch Geocoding](guides/batch-geocoding.md) | CSV, Pandas, GeoJSON, Django bulk operations |
| [React Native / Mobile](guides/mobile.md) | Offline-first encoding, sync patterns |

## Why Not...?

| System | Yoro Advantage |
|--------|----------------|
| **what3words** | Yoro is open source, free, offline. w3w is proprietary and requires API calls. |
| **Google Plus Codes** | Yoro uses country-scoped domains for better resolution. Plus Codes are global (lower precision per character). |
| **Geohash** | Yoro uses Hilbert curves (better locality preservation). Geohash has edge discontinuities. |
| **H3 (Uber)** | Yoro is simpler (pure Python, no C extension). H3 is better for hexagonal tiling at scale. |

## Created By

**Paul Guindo** — [Altius Academy SNC](https://altius-group.ch)

Built for agricultural traceability in West Africa. Used in production for EUDR compliance (cocoa, cashew, shea, coffee, cotton supply chains).
