code wiki / _hdl_build / nx_geo_h3.nx

nx_geo_h3.nx source

↩ module page · 63 lines · 2608 B

1// nx_geo_h3.nx -- LIB: GEO-018 H3-CLASS HEXAGONAL grid index in CUBE coordinates. A hex cell is 2// (q,r,s) with q+r+s=0; the 6 neighbours are the 6 axial directions, each at grid-distance 1. 3// 4// THE EXCEED ANGLE (measured, integer-exact -- not asserted): hexagons tile the plane with UNIFORM 5// adjacency. The exact squared Euclidean distance between two hex-lattice centres differing by axial 6// (da,db) is the lattice NORM FORM N(da,db) = da^2 + da*db + db^2 -- the irrational sqrt(3) of the hex 7// basis CANCELS, leaving a pure integer. All 6 immediate neighbours have N == 1: every adjacent hex 8// is equidistant. A square grid's natural 8-neighbourhood instead splits into squared distance 1 9// (4 edge) and 2 (4 diagonal) -- NON-uniform by a factor of 2. Uniform adjacency = no 10// direction-dependent bias in coverage / radius / flow, the H3 win over square cells. 11// 12// Pure integer, deterministic. (q,r) are axial cell coords; a real lon/lat first quantizes to the hex 13// lattice. license_tier: ORIGINAL 14import "nx_syscalls.nx" 15 16func geo_h3_abs(x: i64) -> i64 { if x < 0 { return 0 - x } return x } 17 18// axial (q,r) -> cube (q,r,s) with s = -q-r, written to out3. 19func geo_hex_axial_to_cube(q: i64, r: i64, out3: *i64) -> i64 { 20 out3[0] = q 21 out3[1] = r 22 out3[2] = (0 - q) - r 23 return 0 24} 25 26// hex grid distance (number of steps) between two axial cells = cube Chebyshev/2. 27func geo_hex_distance(q1: i64, r1: i64, q2: i64, r2: i64) -> i64 { 28 let dq: i64 = q1 - q2 29 let dr: i64 = r1 - r2 30 let ds: i64 = (0 - dq) - dr 31 return (geo_h3_abs(dq) + geo_h3_abs(dr) + geo_h3_abs(ds)) / 2 32} 33 34// EXACT squared Euclidean distance between hex centres differing by axial (da,db): the lattice norm. 35func geo_hex_norm2(da: i64, db: i64) -> i64 { 36 return da * da + da * db + db * db 37} 38 39// the dir-th (0..5) neighbour of axial (q,r), written to out2 = [q',r']. 40func geo_hex_neighbor(q: i64, r: i64, dir: i64, out2: *i64) -> i64 { 41 var dq: i64 = 0 42 var dr: i64 = 0 43 if dir == 0 { dq = 1; dr = 0 } 44 if dir == 1 { dq = 1; dr = 0 - 1 } 45 if dir == 2 { dq = 0; dr = 0 - 1 } 46 if dir == 3 { dq = 0 - 1; dr = 0 } 47 if dir == 4 { dq = 0 - 1; dr = 1 } 48 if dir == 5 { dq = 0; dr = 1 } 49 out2[0] = q + dq 50 out2[1] = r + dr 51 return 0 52} 53 54// cells at EXACTLY grid-distance k from a centre (H3 ring): 1 for k=0, else 6k. 55func geo_hex_ring_size(k: i64) -> i64 { 56 if k == 0 { return 1 } 57 return 6 * k 58} 59 60// cells WITHIN grid-distance k (H3 disk / k-ring): the centered hexagonal number 1 + 3k(k+1). 61func geo_hex_disk_size(k: i64) -> i64 { 62 return 1 + 3 * k * (k + 1) 63}