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}