Skip to content

Commit 59ae664

Browse files
committed
some more figures and Z7 stuff
1 parent a343bf1 commit 59ae664

22 files changed

Lines changed: 778 additions & 13 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,4 @@ yarn-error.log*
222222
website/build/
223223
website/.docusaurus/
224224
.docusaurus/
225+
.DS_Store

website/docs/api/traversal.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,63 @@ title: Traversal Functions
55

66
# Traversal Functions
77

8+
This page is directly based off [Renoud and Shaw's work on the Z7 C++ prototype][renoud2025]
9+
10+
This is a work-in-progress to explore the possibility of neighbor traversal in the Z7 domain. Z7 is based on
11+
the Generalized Balanced Ternary (GBT) numeral system described in [Lucas, Gibson (1982)][lucas1982],
12+
[van Roessel (1988)][vanRoessel1988], and [Wikipedia (2025)][wikipedia2025].
13+
14+
## Rotation Pattern
15+
16+
Lucas and Gibson (1982) gave examples of GBT with exclusively counter-clockwise (CCW) rotation. The disadvantage of this
17+
approach is that the orientation of the hexagons at the different hierarchy levels quickly diverge from each other.
18+
[White et al. (1992)][white1992] proposed an alternating rotation direction (CW, CCW, CW, ...) to maintain an alignment
19+
of hexagon
20+
orientations across hierarchy levels. Kmoch et al. (2025) adopted this alternating rotation pattern for Z7 assigning CW
21+
to odd resolutions and CCW to even resolutions.
22+
23+
For reference purposes a rendering of three hierarchies of alternating GBT rotation is included (CW, CCW, CW).
24+
25+
<img src="https://raw.githubusercontent.com/wrenoud/Z7/refs/heads/main/images/grid.svg" width="200" alt="3 hierarchies in Z7's alternating GBT pattern"></img>
26+
27+
### GBT Addition
28+
29+
| Counter-clockwise (CCW) | Clockwise (CW) |
30+
|----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
31+
| <img src="/images/neighbors-neighbors-ccw.png" width="300" alt="Single digit GBT addition with CCW rotation"></img> | <img src="/images/neighbors-neighbors-cw.png" width="300" alt="Single digit GBT addition with CW rotation"></img> |
32+
33+
## References
34+
35+
1. Renoud and Shaw (2025).
36+
[Z7][renoud2025]. _GitHub[renoud2025]
37+
Series, 6_(32). https://doi.org/10.5194/agile-giss-6-32-2025
38+
2. Lucas, D., & Gibson, L. (1982). [_Automated Analysis of imagery_][lucas1982]. Air Force Office of Scientific
39+
Research. https://apps.dtic.mil/sti/tr/pdf/ADA125710.pdf. (No. AFOSRTR830055).
40+
3. Sahr, K. (2011). [Hexagonal discrete global grid systems for geospatial computing][sahr2011]. _Archives of
41+
Photogrammetry Cartography and Remote Sensing, 22_, 363–376.
42+
4. van Roessel, J. W. (1988).
43+
[Conversion of Cartesian coordinates from and to Generalized Balanced Ternary addresses][vanRoessel1988].
44+
_Photogrammetric Engineering & Remote Sensing, 54_(11), 1565–1570.
45+
5. White, D., Kimerling, J. A., & Overton, S. W. (1992).
46+
[Cartographic and Geometric Components of a Global Sampling Design for Environmental Monitoring][white1992].
47+
_Cartography and Geographic Information Systems_, 19(1), 5-22. https://doi.org/10.1559/152304092783786636
48+
6. Wikipedia Contributors. (2025, December 16). [_Generalized balanced ternary_][wikipedia2025]. Wikipedia; Wikimedia
49+
Foundation.
50+
51+
---
52+
53+
[wikipedia2025]: https://en.wikipedia.org/wiki/Generalized_balanced_ternary
54+
55+
[renoud2025]: https://github.com/wrenoud/Z7/
56+
57+
[vanRoessel1988]: https://web.archive.org/web/20250523045258/https://www.asprs.org/wp-content/uploads/pers/1988journal/nov/1988_nov_1565-1570.pdf
58+
59+
[white1992]: https://www.tandfonline.com/doi/pdf/10.1559/152304092783786636?casa_token=lyaVPE0vjcQAAAAA:GL0QWw01pvr2AQWJgmNcjHH_rCp3VLv5jayMi7O9Kb7jC_l2KFt2b98GvnRcOhi4qSXV-FXXxUYAVg
60+
61+
[sahr2011]: https://www.researchgate.net/publication/266415994_Hexagonal_discrete_global_grid_systems_for_geospatial_computing
62+
63+
[lucas1982]: https://apps.dtic.mil/sti/tr/pdf/ADA125710.pdf
64+
865
:::note Coming soon
966
This page is under construction.
1067
:::
Lines changed: 128 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,135 @@
11
---
22
id: z7-indexing
3+
sidebar_position: 5
34
title: Z7 Indexing
45
---
56

67
# Z7 Indexing
78

8-
:::note Coming soon
9-
This page is under construction.
10-
:::
9+
The **Z7 index** is the core data structure of IGEO7. A single 64-bit integer encodes everything needed to identify a cell: which base cell it belongs to, its resolution, and its exact position within the hierarchy.
10+
11+
## Why a Hierarchical Index?
12+
13+
Traditional geographic coordinate systems (lat/lng, UTM) identify a *point* on the Earth's surface. For spatial analysis at scale, you often need:
14+
15+
- **Aggregation:** group fine-resolution observations into coarser cells
16+
- **Neighbourhood queries:** find all cells adjacent to a given cell
17+
- **Spatial joins:** map observations to a uniform grid
18+
19+
A hierarchical index like Z7 enables all of these in O(1) or O(r) time (where r is the resolution), without any geometry computation.
20+
21+
## Structure
22+
23+
A Z7 index is a 64-bit unsigned integer with this layout:
24+
25+
```
26+
Bits 63–60 │ Bits 59–57 │ Bits 56–54 │ ... │ Bits 2–0
27+
────────────┼──────────────┼──────────────┼───────┼──────────
28+
Base cell │ Digit 1 │ Digit 2 │ ... │ Digit 20
29+
(4 bits) │ (3 bits) │ (3 bits) │ │ (3 bits)
30+
```
31+
32+
- **Base cell (4 bits):** which of the 12 icosahedral pentagonal base cells (0–11) the cell belongs to
33+
- **Resolution digits (20 × 3 bits):** one digit per resolution level, value 0–6 for valid digits, 7 as an "end-of-resolution" sentinel
34+
35+
## The 12 Base Cells
36+
37+
IGEO7 starts from the **12 vertices of the icosahedron**, which become the 12 pentagonal cells at resolution 0. All other cells at all resolutions are hexagons that subdivide the faces around these vertices.
38+
39+
This is fundamentally different from H3, which has 122 resolution-0 cells formed by a mixed aperture 4→3 pre-subdivision. IGEO7's simpler base gives it 5 additional resolution levels.
40+
41+
![The 12 pentagonal base cells on the icosahedron](/images/plot3_pentagon_noquad.png)
42+
43+
## Aperture 7 Subdivision
44+
45+
At each resolution step, every hexagonal cell is subdivided into **7 children**:
46+
47+
![ISEA7H aperture-7 refinement showing parent cell subdivided into 7 children](/images/isea7h_refinement.png)
48+
49+
- **Digit 0:** centre child — directly below the parent centroid
50+
- **Digits 1–6:** six surrounding children, numbered in space-filling curve order
51+
52+
Pentagons are an exception: they have 6 children (1 centre + 5 surrounding), since pentagons have only 5 edges.
53+
54+
## Reading a Z7 Index
55+
56+
The Z7 string format `"0800433"` decodes as:
57+
58+
| Part | Value | Meaning |
59+
|---|---|---|
60+
| `08` | base cell 8 | one of the 12 icosahedron vertices |
61+
| `0` | digit 1 = 0 | centre child at resolution 1 |
62+
| `0` | digit 2 = 0 | centre child at resolution 2 |
63+
| `4` | digit 3 = 4 | child 4 at resolution 3 |
64+
| `3` | digit 4 = 3 | child 3 at resolution 4 |
65+
| `3` | digit 5 = 3 | child 3 at resolution 5 |
66+
67+
This cell is at **resolution 5** (5 valid digits after the base cell).
68+
69+
## Parent–Child Relationships
70+
71+
**Parent:** remove the last digit.
72+
73+
```python
74+
z7_str = "0800433"
75+
parent = z7_str[:-1] # "080043" (resolution 4)
76+
```
77+
78+
**Children:** append digits 0–6.
79+
80+
```python
81+
children = [z7_str + str(d) for d in range(7)]
82+
# ["08004330", "08004331", ..., "08004336"]
83+
```
84+
85+
This works identically on the integer representation via bit operations:
86+
87+
```python
88+
# Get parent (set last valid digit group to 0b111)
89+
def get_parent(z7_int: int, resolution: int) -> int:
90+
shift = 57 - 3 * (resolution - 1)
91+
mask = ~(0x7 << shift)
92+
return (z7_int & mask) | (0x7 << shift)
93+
```
94+
95+
## The Space-Filling Curve
96+
97+
The Z7 index order is not arbitrary — it defines a **space-filling curve** over the sphere. Cells that are adjacent in Z7 integer order tend to be spatially close. This property:
98+
99+
![Z7 space-filling curve index order](/images/plot_index_order.png)
100+
101+
- Improves cache locality when processing large datasets in index order
102+
- Makes range scans on indexed database columns spatially coherent
103+
- Is analogous to the Hilbert curve used in many raster spatial indexing schemes
104+
105+
## Digit 0: The Centre Cell
106+
107+
The digit `0` always means "the child that contains the parent's centroid". This is a consistent orientation anchor: no matter which base cell or resolution you're at, digit `0` is always the spatial centre.
108+
109+
This means the **path of all-zero digits** (e.g., `"080000...0"`) traces a straight line from the icosahedron vertex down to the finest resolution, always staying at the centre of each parent cell.
110+
111+
## Comparison with H3 Indexing
112+
113+
| Property | Z7 (IGEO7) | H3 |
114+
|---|---|---|
115+
| Index size | 64-bit integer | 64-bit integer |
116+
| Base cell bits | 4 (values 0–11) | 7 (values 0–121) |
117+
| Digit size | 3 bits (values 0–6, 7=sentinel) | 3 bits (values 0–6, 7=sentinel) |
118+
| Max resolution | 20 | 15 |
119+
| Digit encoding | 0=centre, 1–6=surrounding | 0=centre, 1–6=surrounding |
120+
| String format | `BB` + up to 20 octal digits | 15-hex-char string |
121+
122+
The indexing philosophy is nearly identical — both use 64-bit integers with 3-bit resolution digits and a sentinel value. The key differences are at the base cell level: Z7 has 12 pure-aperture-7 base cells; H3 has 122 mixed-aperture base cells.
123+
124+
## Neighbourhood Traversal
125+
126+
Finding neighbours requires Z7 arithmetic — specifically, Central Place Indexing (CPI) addition with carry propagation across base cell boundaries. This is implemented in [IGEO7.jl](https://github.com/allixender/IGEO7.jl) and the [C++ work](https://github.com/wrenoud/Z7/) by W.Renoud J.Shaw.
127+
128+
129+
130+
## See Also
131+
132+
- [Z7 Bit Layout](../reference/z7-bit-layout) — detailed binary encoding
133+
- [Z7 String Format](../reference/z7-string-format) — the two external string representations
134+
- [Aperture 7 Hierarchy](./aperture7) — the subdivision geometry
135+
- [Pentagons](./pentagons) — the 12 special cells

website/docs/installation.md

Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,116 @@
11
---
22
id: installation
3+
sidebar_position: 2
34
title: Installation
45
---
56

67
# Installation
78

8-
:::note Coming soon
9-
This page is under construction.
9+
IGEO7 is implemented in **DGGRID** (the core C++ engine) and accessed via the **dggrid4py** Python wrapper. You need both.
10+
11+
## 1. Install DGGRID
12+
13+
DGGRID is a C++ command-line tool. You need a compiled binary on your system.
14+
15+
### Pre-built binaries
16+
17+
Download a pre-built binary from the [DGGRID releases page](https://github.com/sahrk/DGGRID/releases).
18+
19+
### Build from source
20+
21+
```bash
22+
git clone https://github.com/sahrk/DGGRID.git
23+
cd DGGRID
24+
mkdir build && cd build
25+
cmake -DCMAKE_BUILD_TYPE=Release ..
26+
make -j$(nproc)
27+
sudo make install # installs to /usr/local/bin/dggrid
28+
```
29+
30+
**Requirements:** CMake ≥ 3.12, a C++17 compiler (GCC ≥ 7 or Clang ≥ 5).
31+
32+
Verify the installation:
33+
34+
```bash
35+
dggrid --version
36+
```
37+
38+
### Setting the path
39+
40+
dggrid4py locates the DGGRID binary via the `DGGRID_PATH` environment variable or an explicit path in the API call:
41+
42+
```bash
43+
export DGGRID_PATH=/usr/local/bin/dggrid
44+
```
45+
46+
## 2. Install dggrid4py
47+
48+
dggrid4py is the Python wrapper that drives DGGRID programmatically.
49+
50+
### With pip
51+
52+
```bash
53+
pip install dggrid4py
54+
```
55+
56+
### With conda / mamba
57+
58+
```bash
59+
conda install -c conda-forge dggrid4py
60+
```
61+
62+
### Dependencies
63+
64+
| Package | Purpose |
65+
|---|---|
66+
| `geopandas` | Geospatial DataFrames with geometry support |
67+
| `shapely` | Geometry objects (polygons, points) |
68+
| `pandas` | Tabular data |
69+
| `numpy` | Array operations |
70+
71+
All are installed automatically.
72+
73+
## 3. (Optional) DGGAL / pydggal
74+
75+
For a pure-Python alternative with no subprocess calls, [DGGAL](https://github.com/ecere/dggal) implements IGEO7 natively as `ISEA7H_Z7`. Install the Python binding:
76+
77+
```bash
78+
pip install dggal
79+
```
80+
81+
## 4. Verify the setup
82+
83+
```python
84+
import os
85+
from dggrid4py import DGGRIDv7
86+
87+
dggrid = DGGRIDv7(
88+
executable=os.environ.get("DGGRID_PATH", "/usr/local/bin/dggrid"),
89+
working_dir="/tmp",
90+
capture_logs=True,
91+
silent=True,
92+
)
93+
94+
# Quick sanity check: generate grid stats for resolution 5
95+
df = dggrid.grid_stats_table("IGEO7", 5)
96+
print(df)
97+
```
98+
99+
Expected output (truncated):
100+
101+
```
102+
Resolution # Cells Area (km^2)
103+
0 0 12 51006562.172409
104+
1 1 72 7286651.738916
105+
...
106+
5 5 168072 3034.840374
107+
```
108+
109+
:::tip Working directory
110+
dggrid4py creates temporary metafiles in `working_dir`. `/tmp` works well on Linux/macOS. The directory is cleaned up automatically after each call.
10111
:::
112+
113+
## Next Steps
114+
115+
- [Quickstart](./quickstart) — generate your first IGEO7 cells
116+
- [dggrid4py ecosystem page](./ecosystem/dggrid4py) — full API reference for the Python wrapper

0 commit comments

Comments
 (0)