Rust implementation of a hex-based spatial indexing for British National Grid.
Inspired by the work done by GDS NUAR n3gb.
Creating a HexCell
- point_to_hex — Takes your input coordinates and finds which grid cell they fall into. Returns (row, col).
- hex_to_point — Takes the (row, col) and calculates the exact center of that cell. This is where the offset for odd rows gets applied. Returns (center_x, center_y).
- generate_identifier — Takes the center coordinates of the HexCell and zoom level, packs it all into binary, and then encodes as Base64. The ID contains: version + center_x + center_y + zoom.
Reconstructing from ID
- decode_hex_identifier — Decodes the Base64 string back into version, center_x, center_y, and zoom.
- create_hexagon — Draws 6 vertices around the center at the radius for that zoom level.
How polygons maintain the offset structure?
- They don't care nor need to know about it.
- The offset is applied when hex_to_point calculates the centre.
- The centre coordinates themselves contain the offset.
1. Single Cells - use HexCell
let point = Point::new(383640.0, 398260.0);
let cell = HexCell::from_bng(&point, 12)?;
println!("{}", cell.id);
let polygon = cell.to_polygon();Example output:
Hex ID: AQAAAAAW3cpQAAAAABe831IMHg
Center: (383634, 398253.9062859271)
Row: 25548, Col: 21313
Polygon: POLYGON((383643.0 398259.1024383498,383634.0 398264.2985907725,383625.0 398259.1024383498,383625.0 398248.7101335044,383634.0 398243.5139810817,383643.0 398248.7101335044,383643.0 398259.1024383498))2. Cell Collections - use HexGrid
let grid = HexGrid::builder()
.zoom_level(12)
.bng_extent(&(300000.0, 300000.0), &(350000.0, 350000.0))
.build();
if let Some(cell) = grid.get_cell_at(&point) {
println!("{}", cell.id);
}