globalhex works with a discrete global grid: a set of cells that covers the whole Earth with no gaps or overlaps. This vignette introduces grids, cells, and the functions that move between them.
A grid is defined by hex_grid(). The default, IGEO7, is
an equal-area grid of hexagons in which each cell has seven children at
the next finer resolution.
grid <- hex_grid()
grid
#> <globalhex_grid>
#> system: IGEO7
#> index: Z7
#> orientation: 11.25, 58.28252559, 0Every function that creates cells takes a grid argument
that defaults to hex_grid(), so you rarely need to pass it
explicitly. The alternative ISEA3H grid, in which each cell has three
children, is available as hex_grid("isea3h").
Resolution 0 is the coarsest level. Each step finer divides every cell into seven, so cells shrink quickly:
resolution <- 0:12
n_cells <- 10 * 7^resolution + 2
data.frame(
resolution,
n_cells = format(n_cells, big.mark = ",", scientific = FALSE),
area_km2 = signif(510.1e6 / n_cells, 3)
)
#> resolution n_cells area_km2
#> 1 0 12 4.25e+07
#> 2 1 72 7.08e+06
#> 3 2 492 1.04e+06
#> 4 3 3,432 1.49e+05
#> 5 4 24,012 2.12e+04
#> 6 5 168,072 3.04e+03
#> 7 6 1,176,492 4.34e+02
#> 8 7 8,235,432 6.19e+01
#> 9 8 57,648,012 8.85e+00
#> 10 9 403,536,072 1.26e+00
#> 11 10 2,824,752,492 1.81e-01
#> 12 11 19,773,267,432 2.58e-02
#> 13 12 138,412,872,012 3.69e-03Because the grid is equal-area, these areas hold everywhere on Earth, from the equator to the poles.
The grid is built on an icosahedron, so 12 cells at every resolution
are pentagons rather than hexagons. That is why cell operations use the
cell_ prefix rather than hex_: not every cell
is a hexagon. Pentagons have five neighbors instead of six, and
globalhex handles them like any other cell.
point_to_cell() finds the cell containing a point.
Coordinates are always longitude first, then latitude:
gainesville <- point_to_cell(c(-82.32, 29.65), resolution = 7)
gainesville
#> <globalhex_cell[1]>
#> [1] 020050152
cell_resolution(gainesville)
#> [1] 7It also accepts a matrix or data frame. Columns named
lon/lat (or long,
lng, longitude, x,
latitude, y) are matched by name; otherwise
the first two columns are used. With sf installed, sf POINT
objects work too.
cities <- data.frame(
name = c("Gainesville", "Nairobi", "Reykjavik"),
lat = c(29.65, -1.29, 64.15),
lon = c(-82.32, 36.82, -21.94)
)
cities$cell <- point_to_cell(cities, resolution = 5)
cities
#> name lat lon cell
#> 1 Gainesville 29.65 -82.32 0200501
#> 2 Nairobi -1.29 36.82 0401421
#> 3 Reykjavik 64.15 -21.94 0041112Cells are a vector type, so they sit happily in data frame columns, and they remember which grid they belong to. Cells from different grids cannot be combined by accident.
cell_center() returns the center of each cell, and
cell_boundary() its vertices:
cell_center(cities$cell)
#> # A tibble: 3 × 3
#> cell lon lat
#> <gh_cell> <dbl> <dbl>
#> 1 0200501 -82.2 29.7
#> 2 0401421 36.9 -1.56
#> 3 0041112 -21.9 64.4polygons <- sf::st_as_sf(cities$cell)
polygons
#> Simple feature collection with 3 features and 1 field
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -82.52929 ymin: -1.886798 xmax: 37.14544 ymax: 64.71727
#> Geodetic CRS: WGS 84
#> # A tibble: 3 × 2
#> cell geometry
#> <gh_cell> <POLYGON [°]>
#> 1 0200501 ((-81.90485 29.68215, -82.11736 29.96618, -82.43091 29.93892, -82.5…
#> 2 0401421 ((37.06223 -1.299545, 36.79428 -1.23296, 36.61043 -1.492471, 36.694…
#> 3 0041112 ((-21.58766 64.12927, -21.26621 64.41509, -21.59749 64.71051, -22.2…cell_neighbors() returns the cells sharing an edge.
cell_disk() returns all cells within k steps,
and cell_ring() only those exactly k steps
away:
cell_neighbors(gainesville)
#> # A tibble: 6 × 2
#> origin cell
#> <gh_cell> <gh_cell>
#> 1 020050152 020050156
#> 2 020050152 020050105
#> 3 020050152 020050101
#> 4 020050152 020050114
#> 5 020050152 020050153
#> 6 020050152 020050150
cell_disk(gainesville, k = 2)
#> # A tibble: 19 × 3
#> origin cell distance
#> <gh_cell> <gh_cell> <int>
#> 1 020050152 020050152 0
#> 2 020050152 020050156 1
#> 3 020050152 020050105 1
#> 4 020050152 020050101 1
#> 5 020050152 020050114 1
#> 6 020050152 020050153 1
#> 7 020050152 020050150 1
#> 8 020050152 020050141 2
#> 9 020050152 020050143 2
#> 10 020050152 020050154 2
#> 11 020050152 020050104 2
#> 12 020050152 020050100 2
#> 13 020050152 020050103 2
#> 14 020050152 020050116 2
#> 15 020050152 020050110 2
#> 16 020050152 020050115 2
#> 17 020050152 020051466 2
#> 18 020050152 020050151 2
#> 19 020050152 020050155 2Functions that can return several cells per input always return a tibble with one row per result and a column recording which input it came from. That holds for one input or many, so you never have to handle a list.
cell_distance() counts the steps between two cells:
Each cell has one parent at the next coarser resolution, and seven children at the next finer one:
parent <- cell_parent(gainesville)
parent
#> <globalhex_cell[1]>
#> [1] 02005015
cell_children(parent)
#> # A tibble: 7 × 2
#> parent cell
#> <gh_cell> <gh_cell>
#> 1 02005015 020050150
#> 2 02005015 020050151
#> 3 02005015 020050152
#> 4 02005015 020050153
#> 5 02005015 020050154
#> 6 02005015 020050155
#> 7 02005015 020050156
cell_parent(gainesville, resolution = 3)
#> <globalhex_cell[1]>
#> [1] 02005A cell’s ID begins with its parent’s ID, so a cell vector can mix resolutions:
To summarize values from fine cells into coarse ones, use
cell_aggregate(), described in
vignette("plotting").
A cell ID is a short string of digits. Store it as text, never as a
number, or leading zeros will be lost. After reading it back, attach the
grid again with as_globalhex_cell():
path <- tempfile(fileext = ".csv")
write.csv(data.frame(cell = as.character(cities$cell)), path, row.names = FALSE)
restored <- read.csv(path, colClasses = "character")
restored$cell <- as_globalhex_cell(restored$cell, grid)
restored
#> cell
#> 1 0200501
#> 2 0401421
#> 3 0041112cell_is_valid() checks that IDs read from elsewhere are
well formed:
globalhex calls a bundled copy of DGGRID.
globalhex_info() reports which copy is in use and the
versions of related packages. To use your own DGGRID build instead, set
the globalhex.dggrid option or the DGGRID_BIN
environment variable.
For grids created with the older dggridR package,
legacy_grid() provides a limited compatibility path. It is
only used when you ask for it.