H3 hexagons
H3 hexagon cells: the cell of a point at a resolution, its neighbours within k rings, its outline for a map, and distances between cells.
Version 1.0.0 · 6 functions · 1 crate
Functions
What use h3.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use h3_cell, h3_info from h3 (Quillo 0.6).
h3_cell(lat: float, lon: float, resolution: int) → stror an errorThe id of the cell holding a point, as 15 hex digits (8a1969053247fff), at resolution 0 to 15: 7 is about 5 km², 9 about 0.1 km², 12 about 300 m².
h3_info(id: str) → anyor an errorAbout a cell: { id, resolution, lat, lon, area_km2, pentagon, parent }, the centre's coordinates, and its parent one resolution up (null at 0).
h3_disk(id: str, k: int) → listor an errorThe cell and every cell within k steps of it (k 0 to 50): 1 gives the 7 of a ring, 2 gives 19. For "within about this far" searches with where cell in (...).
h3_boundary(id: str) → listor an errorThe cell's outline, as [[lat, lon], ...] (6 corners, 5 for a pentagon, a few more where edges cross faces), for drawing on a map.
h3_distance(a: str, b: str) → intor an errorHow many cell steps apart two cells of the same resolution are, or an error when they are too far apart to count (on another face of the grid).
h3_parent(id: str, resolution: int) → stror an errorThe cell holding id at a coarser resolution (for rolling up counts from street to district level).
Get it
$ quillo install h3 # h3.qwer into this folder$ quillo install h3 --example # and its example, h3.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/h3.qwer$ curl -O https://quillolang.org/plugins/files/h3.qweThen, in your program, all of it or only what you call:
use h3.qweruse h3_cell, h3_info from h3 // Quillo 0.6: only theseIt uses this crate, which cargo fetches the first time the plugin is built:
h3o = "0.6"Example
// Couriers near an order, by H3 cell: each courier's cell is kept (in the database in a real app),// and an order looks in its cell's neighbourhood; plus a heat map of orders by district.//// quillo run h3.qwe then open http://localhost:8080/near?lat=52.3702&lon=4.8952use "h3.qwer"let couriers = [ { name: "Ayla", lat: 52.3731, lon: 4.8922 }, { name: "Bram", lat: 52.3600, lon: 4.8850 }, { name: "Cas", lat: 52.3080, lon: 4.7600 },] | map((c) => merge(c, { cell: h3_cell(c.lat, c.lon, 9)? }))route GET /near ? { lat: float, lon: float } { let here = h3_cell(lat, lon, 9)? let nearby = h3_disk(here, 3)? { cell: here, area_km2: round(h3_info(here)?.area_km2, 3), couriers: couriers | filter((c) => contains(nearby, c.cell)) | map((c) => { name: c.name, steps: h3_distance(here, c.cell)? }) }}route GET /heat { let orders = [[52.3702, 4.8952], [52.3712, 4.8960], [52.3600, 4.8850], [52.3080, 4.7600], [52.3705, 4.8949]] orders | map((o) => h3_parent(h3_cell(o[0], o[1], 9)?, 6)?) | group_by((c) => c) | values | map((cs) => len(cs)) | sort | reverse}route GET /shape = { corners: len(h3_boundary(h3_cell(52.3702, 4.8952, 9)?)?), bad: h3_cell(52.37, 4.89, 16).error }$ quillo run h3.qwe$ curl 'localhost:8080/near?lat=52.3702&lon=4.8952'$ curl 'localhost:8080/heat'$ curl 'localhost:8080/shape'Source
//! H3 hexagons (Uber's global grid): the cell of a point at a resolution, its neighbours within k rings, its outline for a map, and the distance between cells. For heat maps, delivery zones, and "near me" by cell id in SQL.//! version: 1.0.0//!//! [dependencies]//! h3o = "0.6"use h3o::{CellIndex, LatLng, Resolution};use serde_json::{json, Value};use std::str::FromStr;fn res(r: i64) -> Result<Resolution, String> { u8::try_from(r).ok().and_then(|r| Resolution::try_from(r).ok()).ok_or(format!("{} is not a resolution: 0 (continents) to 15 (about 1 m²)", r))}fn cell(id: &str) -> Result<CellIndex, String> { CellIndex::from_str(id.trim()).map_err(|_| format!("`{}` is not an H3 cell id", id))}fn point(lat: f64, lon: f64) -> Result<LatLng, String> { LatLng::new(lat, lon).map_err(|_| format!("{}, {} is not a place", lat, lon))}/// The id of the cell holding a point, as 15 hex digits (`8a1969053247fff`), at `resolution` 0 to 15: 7 is about 5 km², 9 about 0.1 km², 12 about 300 m².pub fn h3_cell(lat: f64, lon: f64, resolution: i64) -> Result<String, String> { Ok(point(lat, lon)?.to_cell(res(resolution)?).to_string())}/// About a cell: `{ id, resolution, lat, lon, area_km2, pentagon, parent }`, the centre's coordinates, and its parent one resolution up (null at 0).pub fn h3_info(id: &str) -> Result<Value, String> { let c = cell(id)?; let ll = LatLng::from(c); let parent = c.resolution().pred().and_then(|r| c.parent(r)).map(|p| p.to_string()); Ok(json!({ "id": c.to_string(), "resolution": u8::from(c.resolution()), "lat": ll.lat(), "lon": ll.lng(), "area_km2": c.area_km2(), "pentagon": c.is_pentagon(), "parent": parent, }))}/// The cell and every cell within `k` steps of it (k 0 to 50): 1 gives the 7 of a ring, 2 gives 19. For "within about this far" searches with `where cell in (...)`.pub fn h3_disk(id: &str, k: i64) -> Result<Vec<String>, String> { let c = cell(id)?; let k = u32::try_from(k.clamp(0, 50)).unwrap_or(0); let cells: Vec<CellIndex> = c.grid_disk(k); Ok(cells.into_iter().map(|c| c.to_string()).collect())}/// The cell's outline, as `[[lat, lon], ...]` (6 corners, 5 for a pentagon, a few more where edges cross faces), for drawing on a map.pub fn h3_boundary(id: &str) -> Result<Vec<Vec<f64>>, String> { Ok(cell(id)?.boundary().iter().map(|p| vec![p.lat(), p.lng()]).collect())}/// How many cell steps apart two cells of the same resolution are, or an error when they are too far apart to count (on another face of the grid).pub fn h3_distance(a: &str, b: &str) -> Result<i64, String> { let (a, b) = (cell(a)?, cell(b)?); if a.resolution() != b.resolution() { return Err("the cells are of different resolutions".into()); } a.grid_distance(b).map(i64::from).map_err(|e| e.to_string())}/// The cell holding `id` at a coarser `resolution` (for rolling up counts from street to district level).pub fn h3_parent(id: &str, resolution: i64) -> Result<String, String> { let c = cell(id)?; c.parent(res(resolution)?).map(|p| p.to_string()).ok_or(format!("resolution {} is not coarser than the cell's", resolution))}Related
plus_codes.qwer · 1.0.0Plus codes (Open Location Codes), the addresses Google Maps gives places without a street: from a latitude and longitude, back to their area, shortened near a town and recovered from the short form.7 views · 8 downloadsPolygons polygons.qwer · 1.0.0Points and areas from GeoJSON: whether a point is in a polygon, which zone holds it, and an area's size, perimeter, centre and bounding box.7 views · 8 downloadsSpatial index spatial_index.qwer · 1.0.0An R-tree of places in memory: the nearest ones to a point, all within a distance, those in a map's view, and markers clustered for it.6 views · 8 downloadsCoordinates coordinates.qwer · 1.0.0Coordinates as people write them, such as 52°22'N 4°53'E or N 52° 22.2', read as one, written as degrees-minutes-seconds, and converted to and from UTM.7 views · 8 downloadsKML and KMZ kml.qwer · 1.0.0KML and KMZ files from Google Earth and My Maps read to GeoJSON, placemarks with their names, descriptions, folders and extended data, and GeoJSON written back as KML or KMZ.7 views · 8 downloadsMaidenhead locators maidenhead.qwer · 1.0.0Maidenhead grid locators as radio amateurs use them (FN31pr, JN58td): from a latitude and longitude at 2 to 10 characters, back to the square's centre and corners, and the distance and bearing between two.7 views · 8 downloadsThread 0 posts
On H3 hexagons: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.