1 unstable release
| 0.1.0 | Feb 9, 2026 |
|---|
#5 in #2048
79KB
170 lines
bgrid-rust
A Rust implementation of the BGrid hierarchical global grid, based on the BGrid specification described below. It converts coordinates (lat/lon) to multi-level BGrid indices, decodes indices back to cell centers/bounds, and optionally maps indices to BIP39 words.
What Is BGrid?
BGrid partitions the globe into 2048 cells per level. Each level alternates its split factors:
- Odd levels:
lon = 64,lat = 32 - Even levels:
lon = 32,lat = 64
A BGrid index at each level is a 1-based integer in [1..2048], computed from row/column. Levels can be chained (1 to N levels) to increase resolution.
Coordinate Encoding (DD → BGrid)
Given latitude/longitude in decimal degrees:
- Normalize to unit square:
x = (lon + 180) / 360y = (90 - lat) / 180(north is small y, same as JS)
- For each level:
col = floor(x * lonSplits)row = floor(y * latSplits)index = row * lonSplits + col + 1
- Refine
x,yto the subcell residual and repeat.
This yields an array like [531, 1563, 1600] (or CSV if formatted).
Decoding (BGrid → Cell)
Given a grid index array, the cell bounds are refined level-by-level:
- Start with
[-180..180]and[-90..90]. - For each level, compute the sub-rectangle based on row/col.
- Lat bounds are derived from the top (north) downward, matching
bgrid-js.
The output includes:
- center (
lat,lon) - bounds
[[minLat, minLon], [maxLat, maxLon]]
BIP39 Word Mapping
BGrid indices can be displayed as words using BIP39 wordlists:
number_to_word(1..2048)word_to_number(word)(case-insensitive)grid_to_display(grid, Words, words)
Wordlists are loaded from JSON arrays of 2048 strings.
Install
cargo add bgrid
Quick Start
use std::path::Path;
use bgrid::{
coords_to_bgrid, bgrid_to_cell, load_language,
DisplayMode, grid_to_display,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let grid = coords_to_bgrid(40.7128, -74.0060, 4)?;
let cell = bgrid_to_cell(&grid)?;
println!("grid={:?}", grid);
println!("center=({}, {})", cell.lat, cell.lon);
let display = grid_to_display(&grid, DisplayMode::Numbers, None)?;
println!("numbers={display}");
let words = load_language("es", Path::new("bip39-wordlist"))?;
let display_words = grid_to_display(&grid, DisplayMode::Words, Some(&words))?;
println!("words={display_words}");
Ok(())
}
Bundled Wordlists
This repo includes JSON wordlists under:
bip39-wordlist/
bip39-cs.json
bip39-en.json
bip39-es.json
bip39-fr.json
bip39-it.json
bip39-ja.json
bip39-ko.json
bip39-pt.json
bip39-zh.json
API Overview
coords_to_bgrid(lat, lon, levels) -> Vec<u16>bgrid_to_cell(grid) -> Cellget_grid_cells(level, parent_grid, max_level) -> Vec<GridCell>load_language(lang, base_path) -> Vec<String>number_to_word(number, words) -> Option<&str>word_to_number(word, words) -> Option<u16>grid_to_display(grid, mode, words?) -> String
Error Model
All functions return Result<_, BGridError> with meaningful error variants such as:
InvalidLatLonInvalidLevelsInvalidGridInvalidLanguageInvalidWords
Tests
cargo test
Compatibility Notes
- Lat orientation follows the BGrid spec:
y = (90 - lat) / 180. - Indices are 1-based (1..2048) per level.
- Word lookup is case-insensitive to match
bgrid-js.
License
MIT
Dependencies
~0.3–0.8MB
~17K SLoC