IGEO7 Grid System

IGEO7 Grid System

Code
using GlobalGrids, GeoMakie, CairoMakie

grid = IGEO7Grid()
pents = pentagons(grid, 0)

fig = Figure()
ax = GeoAxis(fig[1,1], dest = "+proj=ortho +lon_0=-50 +lat_0=30")
poly!(ax, pents, color=(:black, .4))

ep = surface!(ax,
    -180..180, -90..90,
    zeros(axes(rotr90(GeoMakie.earth())));
    shading = NoShading, color = rotr90(GeoMakie.earth())
)
translate!(ep, 0, 0, -1)

fig

IGEO7 is a pure-Julia aperture-7 hexagonal discrete global grid. It uses the same icosahedral vertex placement as the ISEA orientation and a Lambert azimuthal equal-area projection centered on each of the 12 icosahedron vertices.

Key properties:

  • Aperture: 7 — each hexagonal cell subdivides into 7 children.
  • Resolutions: 0–20 (resolution 0 has 12 pentagonal cells at icosahedron vertices).
  • Cell count: \(10 \cdot 7^r + 2\) at resolution \(r\).
  • 12 pentagons at every resolution (located at the icosahedron vertices).
  • Pure Julia — no binary dependencies beyond the standard library.

Creating an IGEO7Cell

From Coordinates and Resolution

coord = LonLat(-75.0, 54.0)
cell = IGEO7Cell(coord, 5)
 IGEO7Cell 5 11-16612

From Base Vertex and Digits

Each cell is identified by a base vertex (0–11) and a sequence of digits (0–6):

# Base vertex 0, digits [1, 2, 3]
cell = IGEO7Cell(0, [1, 2, 3])
 IGEO7Cell 3 0-123

From Hex String

cell = IGEO7Cell(coord, 5)
str = encode(cell)
@info str
IGEO7Cell(str)
[ Info: b3b15fffffffffff
 IGEO7Cell 5 11-16612

Inspecting Cells

Code
cell = IGEO7Cell(LonLat(-75.0, 54.0), 5)

@show resolution(cell)
@show is_pentagon(cell)
@show GlobalGrids.digits(cell)
@show base_cell(cell)
@show decode(cell)
@show encode(cell)
nothing
resolution(cell) = 5
is_pentagon(cell) = false
GlobalGrids.digits(cell) = [1, 6, 6, 1, 2]
base_cell(cell) = 11
decode(cell) = "11-16612"
encode(cell) = "b3b15fffffffffff"

GeoInterface

Code
import GeoInterface as GI

@show GI.centroid(cell)
@show GI.coordinates(cell)
@show GI.area(cell)  # meters²
nothing
GI.centroid(cell) = LonLat{Float64} (-74.64844243661682, 53.873372152060995)
GI.coordinates(cell) = GlobalGrids.LonLat{Float64}[LonLat{Float64} (-74.25799929906842, 53.66190569679182), LonLat{Float64} (-74.14477025256443, 53.94599208281042), LonLat{Float64} (-74.5367432930249, 54.15792502960155), LonLat{Float64} (-75.04228216717915, 54.08356962806361), LonLat{Float64} (-75.14984526262614, 53.79826918505636), LonLat{Float64} (-74.75758368313738, 53.58852797442134), LonLat{Float64} (-74.25799929906842, 53.66190569679182)]
GI.area(cell) = 3.0348042608173203e9

Grid Hierarchy

  • parent, siblings, and children
Code
cell = IGEO7Cell(LonLat(0.0, 0.0), 3)

fig = Figure()
ax = Axis(fig[1,1], title="Cell:Black, Parent:Blue, Siblings:Orange, Children:Green")
lines!(ax, GlobalGrids.parent(cell), color = :blue)
poly!(ax, cell, color = :black)
lines!(ax, siblings(cell), color = :orange)
lines!(ax, children(cell), color = :green)
fig

Pentagons at any resolution:

Code
pents = pentagons(IGEO7Grid(), 3)

f, a, p = lines(pents, axis=(;type=GeoAxis, dest = "+proj=ortho +lon_0=-50 +lat_0=30"))
ep = surface!(a,
    -180..180, -90..90,
    zeros(axes(rotr90(GeoMakie.earth())));
    shading = NoShading, color = rotr90(GeoMakie.earth())
)
translate!(ep, 0, 0, -1)
f

Quantizing Geometries

Point

Code
ll = LonLat(-54.0, -12.0)

fig = Figure()
ax = Axis(fig[1,1], title="Cells Containing Point at Resolutions 0-3")
for res in 0:3
    lines!(ax, igeo7cells(ll, res))
end
scatter!(ax, ll)

fig

MultiPoint

Code
coords = [LonLat(360rand() - 180, 180rand() - 90) for _ in 1:100]

x = IGEO7Cell.(coords, 0)

f, a, p = lines(x, axis=(;type=GeoAxis, dest = "+proj=ortho +lon_0=-50 +lat_0=30"))
scatter!(a, coords, color=:black)
f

Line

  • Containment options for lines: :center and :shortest_path.
Code
line = GI.Line([LonLat(0, 0), LonLat(1,1)])

fig = Figure(size=(700, 300))

for (i, containment) in enumerate((:center, :shortest_path))
    ax = Axis(fig[1, i], aspect=DataAspect(), title="containment = :$containment")
    x = igeo7cells(line, 4; containment)
    lines!(ax, x)
    lines!(ax, GI.coordinates(line), linewidth=3, color = :black)
end

fig

Polygon

  • Containment modes for polygons:
    • :center: Include cell if its center is inside the polygon.
    • :overlap: Include cell if any part intersects the polygon.
Code
boundary = [(-20.0, -20.0), (-20.0, 20.0), (20.0, 20.0), (20.0, -20.0), (-20.0, -20.0)]
poly = GI.Polygon([boundary])

fig = Figure(size=(700, 300))

for (i, containment) in enumerate((:center, :overlap))
    ax = Axis(fig[1, i], aspect=DataAspect(), title="containment = :$containment")
    x = igeo7cells(poly, 2; containment)
    lines!(ax, x)
    lines!(ax, GI.LineString(boundary), linewidth=2, color=:black)
end

fig