| Title: | Equal-Area Hex Grids on the Snyder ISEA Icosahedron |
| Version: | 0.9.0 |
| Description: | Provides functions to build and use hexagonal discrete global grids using the Icosahedral Snyder Equal Area ('ISEA') projection (Snyder 1992 <doi:10.3138/27H7-8K88-4882-1752>) and the 'H3' hierarchical hexagonal system (Uber Technologies). Implements the 'ISEA' discrete global grid system (Sahr, White and Kimerling 2003 <doi:10.1559/152304003100011090>) and the 'Hex9' octahedral grid (Griffin 2026 <doi:10.48550/arXiv.2608.00022>). Includes a fast C++ core for 'ISEA' projection and aperture quantization, an included 'H3' v4.4.1 C library for native 'H3' grid operations, and 'sf'/'terra'-compatible R wrappers for grid generation and coordinate assignment. Output is compatible with 'dggridR' for interoperability. |
| License: | MIT + file LICENSE |
| SystemRequirements: | C99 |
| Language: | en-US |
| Encoding: | UTF-8 |
| Suggests: | testthat (≥ 3.0.0), chromote, hexglobe, knitr, rmarkdown, terra, raster, ggplot2, RColorBrewer, rnaturalearth, tibble, gridExtra, htmlwidgets, jsonlite, leaflet |
| VignetteBuilder: | knitr |
| LinkingTo: | Rcpp |
| Imports: | sf, Rcpp, methods, rlang, bit64 |
| Additional_repositories: | https://gcol33.r-universe.dev |
| URL: | https://gillescolling.com/hexify/ |
| BugReports: | https://github.com/gcol33/hexify/issues |
| Config/testthat/edition: | 3 |
| Depends: | R (≥ 4.0) |
| LazyData: | true |
| Config/roxygen2/version: | 8.1.0 |
| Collate: | 'RcppExports.R' 'aperture_mixed_hierarchy.R' 'aperture_sequence.R' 'cell_id.R' 'cell_metrics.R' 'constants.R' 'classes.R' 'construction.R' 'constructors.R' 'crosswalk.R' 'data.R' 'dggrid.R' 'dggrid_compat.R' 'dggrs_definition.R' 'distortion.R' 'gosper.R' 'grid_helpers.R' 'h3_compat.R' 'hex9_warp.R' 'hex_aggregate.R' 'hex_browse.R' 'hex_compact.R' 'hex_distance.R' 'hex_extract.R' 'hex_globe.R' 'hex_glyphs.R' 'hex_sample.R' 'hex_smooth.R' 'hex_summarize.R' 'hex_topology.R' 'hex_zonal.R' 'hexify-package.R' 'hexify.R' 'hexify_assign.R' 'hexify_cell_to_sf.R' 'hexify_conversions.R' 'hexify_grid.R' 'hexify_index.R' 'hexify_map.R' 'hexify_neighbors.R' 'hexify_projection.R' 'hexify_stats.R' 'net_cells.R' 'net_layout.R' 'ogc_zirs.R' 'orientation.R' 'plot_methods.R' 'plot_surface.R' 'sphere_geometry.R' |
| NeedsCompilation: | yes |
| Packaged: | 2026-10-23 09:59:50 UTC; Gilles Colling |
| Author: | Gilles Colling |
| Maintainer: | Gilles Colling <gilles.colling051@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-10-23 19:30:02 UTC |
hexify: Equal-Area Hex Grids on the Snyder ISEA Icosahedron
Description
Provides functions to build and use hexagonal discrete global grids using the Icosahedral Snyder Equal Area ('ISEA') projection (Snyder 1992 doi:10.3138/27H7-8K88-4882-1752) and the 'H3' hierarchical hexagonal system (Uber Technologies). Implements the 'ISEA' discrete global grid system (Sahr, White and Kimerling 2003 doi:10.1559/152304003100011090) and the 'Hex9' octahedral grid (Griffin 2026 doi:10.48550/arXiv.2608.00022). Includes a fast C++ core for 'ISEA' projection and aperture quantization, an included 'H3' v4.4.1 C library for native 'H3' grid operations, and 'sf'/'terra'-compatible R wrappers for grid generation and coordinate assignment. Output is compatible with 'dggridR' for interoperability.
Author(s)
Maintainer: Gilles Colling gilles.colling051@gmail.com (ORCID) [copyright holder]
Authors:
Gilles Colling gilles.colling051@gmail.com (ORCID) [copyright holder]
Other contributors:
Uber Technologies, Inc. (H3 C library, src/h3 (Apache-2.0)) [contributor, copyright holder]
Ben Griffin (Hex9 address tables in src/hex9.cpp, from libhex9 (Apache-2.0)) [contributor, copyright holder]
See Also
Useful links:
HexData Class
Description
An S4 class representing hexified data. Contains the original user data plus cell assignments from the hexification process.
Usage
## S4 method for signature 'HexData'
grid_info(x)
## S4 method for signature 'HexData'
cells(x)
## S4 method for signature 'HexData'
n_cells(x)
## S4 method for signature 'HexData'
nrow(x)
## S4 method for signature 'HexData'
ncol(x)
## S4 method for signature 'HexData'
dim(x)
## S4 method for signature 'HexData'
names(x)
## S4 method for signature 'HexData'
x$name
## S4 replacement method for signature 'HexData'
x$name <- value
## S4 method for signature 'HexData'
x[i, j, ..., drop = FALSE]
## S4 method for signature 'HexData'
x[[i]]
## S4 replacement method for signature 'HexData,ANY,missing'
x[[i, j]] <- value
## S4 method for signature 'HexData'
show(object)
## S4 method for signature 'HexData'
summary(object, ...)
## S3 method for class 'hexify_data_summary'
print(x, ...)
## S4 method for signature 'HexData'
as.data.frame(x, row.names = NULL, optional = FALSE, ...)
## S4 method for signature 'HexData'
as.list(x, ...)
## S3 method for class 'HexData'
as_tibble(x, ...)
## S3 method for class 'HexData'
st_as_sf(
x,
...,
geometry = c("point", "polygon"),
shape = c("hexagon", "gosper", "descendants"),
depth = 3L
)
## S3 method for class 'HexData'
st_crs(x, ...)
## S4 method for signature 'HexData,missing'
plot(
x,
y,
basemap = TRUE,
clip_basemap = TRUE,
basemap_fill = "gray90",
basemap_border = "gray50",
basemap_lwd = 0.5,
grid_fill = "#E69F00",
grid_border = "#5D4E37",
grid_lwd = 0.8,
grid_alpha = 0.7,
fill = NULL,
show_points = FALSE,
point_size = "auto",
point_color = "red",
point_alpha = 1,
jitter = TRUE,
crop = TRUE,
crop_expand = 0.1,
main = NULL,
shape = c("hexagon", "gosper", "descendants"),
depth = 3L,
...
)
Arguments
x |
A HexData object; for |
name |
Column name |
value |
Replacement value |
i, j |
Row/column indices |
... |
For |
drop |
Logical, whether to drop dimensions |
object |
A HexData object |
row.names |
Optional row names |
optional |
Logical (ignored) |
geometry |
For |
shape, depth |
Cell shape for polygon geometry and for |
y |
Ignored (for S4 method compatibility) |
basemap |
Basemap specification:
|
clip_basemap |
Clip basemap to data extent (default TRUE). Clipping temporarily disables S2 spherical geometry to avoid edge-crossing errors. |
basemap_fill |
Fill color for basemap (default "gray90") |
basemap_border |
Border color for basemap (default "gray50") |
basemap_lwd |
Line width for basemap borders (default 0.5) |
grid_fill |
Fill color for grid cells (default "#E69F00" - amber/orange) |
grid_border |
Border color for grid cells (default "#5D4E37" - dark brown) |
grid_lwd |
Line width for cell borders (default 0.8) |
grid_alpha |
Transparency for cell fill (0-1, default 0.7) |
fill |
Column name for fill mapping (optional) |
show_points |
Show original points on top of cells (default FALSE). Points are jittered within their assigned hexagon. |
point_size |
Size of points. Can be:
|
point_color |
Color of points (default "red") |
point_alpha |
Transparency for points (0-1, default 1) |
jitter |
If TRUE (default), points are randomly scattered within their assigned hexagon. If FALSE, all points in a cell are plotted at the cell centroid instead. |
crop |
Crop to data extent (default TRUE) |
crop_expand |
Expansion factor for crop (default 0.1) |
main |
Plot title |
Details
HexData objects are created by hexify. The original data
is preserved in the data slot, while cell assignments are stored
separately in cell_id and cell_center.
Use as.data.frame() to get a combined data frame with cell columns.
Unlike [.data.frame, drop defaults to FALSE: selecting
a single column returns a HexData object (preserving grid/
cell_id/cell_center) rather than dropping to a bare vector.
Pass drop = TRUE explicitly to get data.frame-style dropping.
Value
-
show(): the object, invisibly, after printing two lines: rows, columns and cells, and the grid -
summary(): a list of classhexify_data_summarycarryingrows,columns,column_names,n_cells,type, thegridsummary and apreviewof the first rows; printing it lists all of these and returns it invisibly -
grid_info(): HexGridInfo object containing grid specification -
cells(): vector of unique cell IDs -
n_cells(): integer count of unique cells -
nrow(),ncol(),dim(): integer dimensions -
names(): character vector of column names (including virtual cell columns) -
$,[[: the requested column or cell data as a vector -
$<-,[[<-: the modified HexData object -
[: subsetted HexData object or extracted data -
as.data.frame(): data frame with original data plus cell columns -
as.list(): named list containing data, grid, cell_id, and cell_center -
as_tibble(): the original data (without geometry) as a tibble -
plot(): the object, invisibly -
st_as_sf(): an sf object, one feature per row -
st_crs(): the grid's coordinate reference system, as for a HexGridInfo
Slots
dataData frame or sf object. The original user data (untouched).
gridHexGridInfo object. The grid specification used.
cell_idCell IDs for each row of data:
bit64::integer64for ISEA grids, character for H3 grids.cell_centerMatrix. Two-column matrix (lon, lat) of cell centers.
Plotting data
plot() draws the cells the data falls in, with an optional basemap.
It builds polygons for the cells present in the data when it draws them,
rather than storing them, to keep memory use low.
See Also
hexify for creating HexData objects,
HexGridInfo-class for grid specifications
hexify_heatmap for ggplot2 plotting
Examples
df <- data.frame(lon = c(0, 10, 20), lat = c(45, 50, 55), n = 1:3)
result <- hexify(df, lon = "lon", lat = "lat", area_km2 = 1000)
result
summary(result)
summary(result)$column_names
cells(result)
n_cells(result)
head(as.data.frame(result))
result$cell_id
result[1:2, ]
st_crs(result)
# sf points at the cell centres, or the cells as polygons
sf_pts <- st_as_sf(result)
sf_poly <- st_as_sf(result, geometry = "polygon")
if (requireNamespace("tibble", quietly = TRUE)) {
tibble::as_tibble(result)
}
df <- data.frame(lon = runif(50, -5, 5), lat = runif(50, 45, 50))
result <- hexify(df, lon = "lon", lat = "lat", area_km2 = 2000)
# Basic plot
plot(result, basemap = FALSE)
# With basemap and custom styling
plot(result, grid_fill = "lightblue", grid_border = "darkblue")
HexGridInfo Class
Description
An S4 class representing a hexagonal grid specification. Stores all parameters needed for grid operations.
Usage
## S4 method for signature 'HexGridInfo'
x$name
## S4 method for signature 'HexGridInfo'
n_cells(x)
## S4 method for signature 'HexGridInfo'
names(x)
## S4 method for signature 'HexGridInfo'
show(object)
## S4 method for signature 'HexGridInfo'
summary(object, ...)
## S3 method for class 'hexify_grid_summary'
print(x, ...)
## S4 method for signature 'HexGridInfo'
as.list(x, ...)
## S3 method for class 'HexGridInfo'
st_as_sf(x, ...)
## S3 method for class 'HexGridInfo'
st_crs(x, ...)
## S4 method for signature 'HexGridInfo,missing'
plot(
x,
y,
surface = c("sphere", "solid", "net"),
center = c(lon = 15, lat = 32),
projection = c("orthographic", "perspective"),
distance = NULL,
tilt = 0,
rotation = 0,
fov = NULL,
cells = NULL,
land = TRUE,
ocean_fill = "#F4F6F8",
land_fill = "#C9D0D6",
land_border = "#8C969F",
land_lwd = 0.4,
grid_border = "#0072B2",
grid_lwd = 0.8,
face_edges = NULL,
edge_col = "black",
edge_lwd = 1.1,
layout = "plane",
seams = FALSE,
seam_col = "#D55E00",
seam_lwd = 1.6,
graticule = FALSE,
graticule_col = "#9AA3AB",
graticule_lwd = 0.5,
distortion = c("none", "angular", "areal"),
tissot = FALSE,
tissot_col = "#2E3439",
tissot_lwd = 0.8,
parents = NULL,
parent_col = "#1B2A38",
parent_lwd = 1.8,
area_legend = FALSE,
tabs = FALSE,
step = 0.01,
main = NULL,
...
)
Arguments
x |
A HexGridInfo object; for |
name |
Slot name |
object |
A HexGridInfo object |
... |
For |
y |
Ignored |
surface |
|
center |
Point the view looks down on: a preset name from
|
projection |
|
distance |
Distance of the untilted perspective camera from the
sphere's centre, in sphere radii; greater than 1. |
tilt |
Degrees the perspective camera swings about the point at
|
rotation |
Degrees the view turns about the line of sight; positive values turn north clockwise. |
fov |
Field of view of the perspective camera in degrees, across the
square the plot shows, centred on |
cells |
Cell IDs to draw. |
land |
|
ocean_fill |
Fill colour of the surface. |
land_fill |
Fill colour of land; |
land_border |
Colour of country outlines; |
land_lwd |
Line width of country outlines. |
grid_border |
Colour of cell boundaries. |
grid_lwd |
Line width of cell boundaries. |
face_edges |
Draw the edges of the solid's faces. |
edge_col |
Colour of face edges. |
edge_lwd |
Line width of face edges. |
layout |
For |
seams |
For |
seam_col |
Colour of seams. |
seam_lwd |
Line width of seams. |
graticule |
|
graticule_col |
Colour of the graticule. |
graticule_lwd |
Line width of the graticule. |
distortion |
|
tissot |
|
tissot_col |
Colour of Tissot ellipses. |
tissot_lwd |
Line width of Tissot ellipses. |
parents |
Resolutions up whose cell outlines are drawn over the
cells, such as |
parent_col |
Colour of parent outlines, recycled over |
parent_lwd |
Line width of parent outlines, recycled over
|
area_legend |
For |
tabs |
For |
step |
Spacing of the points along a cell boundary, as a fraction of a face edge. |
main |
Plot title. |
Details
Create HexGridInfo objects using the hex_grid constructor function.
Do not use new("HexGridInfo", ...) directly.
The aperture can be "3", "4", "7" for grids that refine by one aperture at every level; a family name such as "4/3" or "4/7", which refines by the first aperture for the first floor(resolution / 2) levels and by the second for the rest; or one aperture per level, "4,4,7,3". The separator tells the two apart: "4,7" and the family "4/7" are the same grid at resolution 2, but their grids one level coarser are "4" and "7".
For H3 grids, the aperture is fixed at "7" and resolution ranges from 0 to 15.
Value
-
show(): the object, invisibly, after printing one line naming the grid -
summary(): a list of classhexify_grid_summarycarryinggrid_type,aperture,resolution,area_km2,diagonal_km,crs,radius_km,earth,orientation(c(vert0_lon, vert0_lat, azimuth), empty for H3),projection(NAfor H3),polyhedron(NAfor H3),ellipsoid(c(a_km, f), empty for a grid on the sphere) andn_cells; printing it lists every property and returns it invisibly -
$: the value of the requested slot -
names(): character vector of slot names -
n_cells(): the number of cells the grid contains -
as.list(): a named list of slot values -
plot(): the grid, invisibly -
st_as_sf(): an sf object of the grid's global cell set -
st_crs(): an object of classcrs, assf::st_crs()returns: an Earth grid gives 'WGS84', a grid on another body a longlat CRS on the sphere of its radius
Slots
apertureCharacter. Grid aperture: "3", "4", "7", a mixed family such as "4/3" or "4/7", or one aperture per resolution level ("4,4,7,3").
resolutionInteger. Grid resolution level: for ISEA 0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7 on the icosahedron (cell IDs fit in 64 bits); 0-15 for H3.
area_km2Numeric. Cell area in square kilometers.
diagonal_kmNumeric. Centre spacing in kilometers: the short (flat-to-flat) diagonal of a regular hexagon of area
area_km2,\sqrt{2A/\sqrt{3}}.crsInteger or character. Coordinate reference system: an EPSG code, or a 'PROJ' or 'WKT' string. Defaults to 'WGS84' on Earth, and to a longlat CRS on the sphere of
radius_kmon any other body.grid_typeCharacter. Grid system: "isea" (default) or "h3".
radius_kmNumeric. Radius of the body the grid covers, in kilometers.
NAreads as Earth's mean radius.orientationNumeric. Where an ISEA grid's solid sits:
c(vert0_lon, vert0_lat, azimuth)in degrees, vertex 0 and the azimuth of vertex 1 seen from it. Empty for H3 grids, whose orientation H3 fixes.projectionCharacter. How an ISEA-family grid projects each face of its solid onto its plane triangle: "isea" (Snyder's equal-area projection), "ivea" (van Leeuwen and Strebe's vertex-oriented equal-area projection) or "fuller" (Fuller's projection). Empty for H3 grids.
polyhedronCharacter. The solid an ISEA-family grid is built on: "icosahedron" or "octahedron". Empty for H3 grids.
ellipsoidNumeric. The ellipsoid of revolution an ISEA-family grid reads geodetic latitude on,
c(a_km, f): semi-major axis in km and flattening. Empty for a grid that reads latitude on the sphere, and for H3 grids.
Plotting a grid
plot() draws the cells of a grid in 3D, seen from above a chosen point: on the
sphere, or on the flat faces of the solid the grid is built on. All
surfaces take their cell boundaries from the same points, so a cell on the
solid is the cell on the sphere folded flat.
surface = "net" lays the faces out flat, by default in the PLANE
layout of DGGRID (hexify_cell_to_plane gives cell centres in
the same coordinates); layout picks another, such as Van de Sande's
Gosper World on the octahedron (see net_layout). A cell on a
cut of the net is drawn in parts, one on each side. The net is drawn
without a camera, so center, projection, distance,
tilt, rotation and fov apply to the other two
surfaces.
distortion colours the surface by the distortion of the face
projection that maps the sphere onto the faces (see
projection_distortion), and tissot draws Tissot's
indicatrix on the faces: the ellipse each small circle of the sphere maps
to. With graticule on the net, Snyder's projection shows small bends
in the meridians and parallels where they cross the arcs from each face's
centre to its corners.
parents draws the outlines of the cells some resolutions up over
the grid's own cells, to show the hierarchy. On a net of an equal-area
grid, area_legend draws one cell at the scale of the map, with its
area, and the same for each resolution parents draws. tabs
adds glue tabs along the seams of a net, one on each pair of edges glued
together, so a printed net (for example through pdf) folds into
the solid (Carr et al. 1997).
The view is an orthographic projection by default: parallel lines of sight,
so the whole near half of the sphere shows. projection =
"perspective" places a camera distance sphere radii from the
sphere's centre, above center; it sees a smaller cap, and nearer
cells appear larger. tilt swings that camera about the point at
center, which it keeps looking at, so the surface is seen at a slant
with the horizon towards the top; by default the plot frames the whole
visible sphere. fov sets how wide
the camera sees, and rotation turns the view about the line of sight
in either projection.
References
Carr, D. B., Kahn, R., Sahr, K., Olsen, A. R. (1997). ISEA discrete global grids. Statistical Computing & Graphics Newsletter 8(2/3): 31-39.
See Also
hex_grid for the constructor function,
HexData-class for hexified data objects
grid_global for the cells as sf polygons,
projection_distortion, net_cells
Examples
grid <- hex_grid(area_km2 = 100000)
grid
summary(grid)
summary(grid)$n_cells
n_cells(grid)
grid$resolution
st_crs(grid)
# Every cell of a coarse grid as sf polygons
cells_sf <- st_as_sf(hex_grid(resolution = 2))
grid <- hex_grid(resolution = 3, aperture = 3)
plot(grid)
plot(grid, surface = "solid")
plot(grid, surface = "solid", land = FALSE, center = "pacific")
plot(grid, projection = "perspective", distance = 2, center = "europe")
plot(grid, surface = "solid", projection = "perspective",
distance = 2.5, tilt = 25, rotation = 30)
plot(grid, surface = "net")
octa <- hex_grid(resolution = 3, aperture = 4, polyhedron = "octahedron",
orientation = "gosper")
plot(octa, surface = "net", layout = "gosper", seams = TRUE, graticule = TRUE)
# Distortion of the face projections, with Tissot's indicatrix
plot(grid, surface = "net", land = FALSE, distortion = "angular",
tissot = TRUE, graticule = 15, cells = numeric(0))
fuller <- hex_grid(resolution = 3, aperture = 3, projection = "fuller")
plot(fuller, distortion = "areal", land = FALSE, cells = numeric(0))
# Two resolutions with an area legend, and a net to print and fold
fine <- hex_grid(resolution = 4, aperture = 3)
plot(fine, surface = "net", land = FALSE, parents = 1, area_legend = TRUE)
plot(grid, surface = "net", layout = "land", land = FALSE, seams = TRUE,
tabs = TRUE)
Convert HexGridInfo to Legacy hexify_grid
Description
For backwards compatibility with existing functions.
Usage
HexGridInfo_to_hexify_grid(x)
Arguments
x |
A HexGridInfo object (S4) |
Value
A hexify_grid object (S3)
Convert hexify Grid to 'dggridR'-compatible Grid Object
Description
Creates a 'dggridR'-compatible grid specification from a hexify_grid object. The resulting object can be used with 'dggridR' functions that accept a dggs object.
Usage
as_dggrid(grid)
## S3 method for class 'dggs'
format(x, ...)
## S3 method for class 'dggs'
print(x, ...)
Arguments
grid |
A grid from |
x |
A dggs object |
... |
Ignored |
Details
A dggs carries no body radius, so a grid built on another body cannot be expressed as one: 'dggridR' reads every dggs on Earth's radius, and its areas, spacings and CLS come back on Earth. Converting such a grid warns.
Value
A list with 'dggridR'-compatible fields:
pole_lon_deg |
Longitude of icosahedron vertex 0 (standard 11.25) |
pole_lat_deg |
Latitude of icosahedron vertex 0 (standard 58.282525588538995) |
azimuth_deg |
Azimuth of vertex 1 seen from vertex 0 (standard 0) |
aperture |
Grid aperture (3, 4, or 7) |
res |
Resolution level |
topology |
Grid topology ("HEXAGON") |
projection |
Face projection ('ISEA' or 'FULLER') |
precision |
Output decimal precision (default 7) |
It prints as one line naming the grid in DGGRID's terms.
See Also
Other 'dggridR' compatibility:
dggrid_43h_sequence(),
dggrid_is_compatible(),
from_dggrid()
Examples
dggs <- as_dggrid(hex_grid(resolution = 5, aperture = 3))
dggs
dggrid_is_compatible(dggs)
from_dggrid(dggs)
Calculate Resolution for Target Area
Description
Uses the cell count formula N = d * aperture^res + 2, d the solid's diamond quads; on the icosahedron (d = 10) this is the 'ISEA3H'/'ISEA4H'/'ISEA7H' count, which matches 'dggridR' resolution numbering exactly.
Usage
calculate_resolution_for_area(
target_area_km2,
aperture = 3,
radius_km = EARTH_RADIUS_KM,
polyhedron = "icosahedron"
)
Arguments
target_area_km2 |
Target area in square kilometers |
aperture |
Aperture (3, 4, or 7) |
radius_km |
Radius of the body, in kilometers |
polyhedron |
The solid the grid is built on |
Value
Resolution level, not rounded. A target larger than the cells of resolution 0 gives -Inf.
Compute Per-Cell Area in km²
Description
Returns the area of each cell in square kilometers. On the ISEA and IVEA projections every hexagon of a resolution has the same area, the 12 pentagons of the icosahedron 5/6 of it, the 6 squares of the octahedron 4/6 of it and the 4 triangles of the tetrahedron half of it. On the Fuller projection and for H3 grids, the area varies from cell to cell.
Usage
cell_area(cell_id = NULL, grid)
Arguments
cell_id |
Cell IDs to compute area for. For ISEA grids, these are
numeric; for H3 grids, character strings. When |
grid |
A HexGridInfo or HexData object. |
Details
On the ISEA and IVEA projections, both equal-area, every hexagon of a
resolution has the same area. A vertex cell, centred on a vertex of the
solid where k faces meet, covers k of a hexagon's six sixths,
so a grid of N cells on a body of area S has hexagons of area
S / (N - 2), pentagons of (5/6) S / (N - 2) on the
icosahedron, squares of (4/6) S / (N - 2) on the octahedron and
triangles of (3/6) S / (N - 2) on the tetrahedron. The
grid's area_km2 is the mean, S / N.
On the Fuller projection (hex_grid(projection = "fuller")) cells are
not equal-area. Each cell's area is its solid angle, summed over its true
boundary, times the body's area over 4\pi, so the cells of a grid add
up to the body's area.
For H3 grids the area varies from cell to cell, by about a factor of 2
across the hexagons of a resolution. The vendored 'H3' library computes
each cell's spherical polygon area as a solid angle, which this function
reads on the grid's body, so a grid built with radius_km reports that
body's areas.
Value
Named numeric vector of areas in km², one per cell_id.
See Also
hex_grid for grid specifications,
h3_crosswalk for ISEA/H3 interoperability
Examples
# ISEA: one area for every hexagon
grid <- hex_grid(area_km2 = 1000)
cells <- lonlat_to_cell(c(0, 10, 20), c(45, 50, 55), grid)
cell_area(cells, grid)
# H3: area varies by location
h3 <- hex_grid(resolution = 5, type = "h3")
h3_cells <- lonlat_to_cell(c(0, 0), c(0, 80), h3)
cell_area(h3_cells, h3) # equator vs polar — different areas
Shape Metrics of Cells: Area, Perimeter and Compactness
Description
Measures each cell on the sphere: its area, the length of its boundary and how close its shape is to a circle.
Usage
cell_metrics(cell_id = NULL, grid)
Arguments
cell_id |
Cell IDs. When |
grid |
A HexGridInfo or HexData object. |
Details
The perimeter follows each wall as the grid draws it. An ISEA wall is straight on its face of the solid and curved on the sphere, so it is followed on the sphere until its length is exact to about 1e-8. An H3 wall is a great-circle arc between corners, with an extra corner where it crosses an edge of the icosahedron.
Compactness (White et al. 1998) is the perimeter of a spherical cap with the
cell's area over the cell's perimeter, \sqrt{4\pi a - a^2/r^2} / p for
area a, perimeter p and radius r. A circle scores 1; a
small regular hexagon 0.952, pentagon 0.930, square 0.886 and triangle
0.778.
The normalized area is the cell's area over the mean area of the grid's
cells, the body's surface over the cell count; an equal-area grid of
N cells gives N / (N - 2) for its hexagons, 5/6 of that for
the pentagons of the icosahedron, 4/6 for the squares of the octahedron and
3/6 for the triangles of the tetrahedron. The isoperimetric quotient
ipq is 4\pi a / p^2, for a circle 1, a small regular hexagon
0.907, square 0.785 and triangle 0.605. Kmoch et al. (2022) compare
grids by these two measures, reading area and perimeter in an equal-area
plane centred on each cell; here both are read on the sphere, which adds
(a/(rp))^2 to compactness^2, a few parts in a million for
cells of a few thousand square kilometres.
Value
Data frame with one row per cell_id: cell_id,
area_km2 (as cell_area gives it),
normalized_area, perimeter_km, compactness and
ipq.
References
White, D., Kimerling, A. J., Sahr, K. and Song, L. (1998). Comparing area and shape distortion on polyhedral-based recursive partitions of the sphere. International Journal of Geographical Information Science 12(8), 805-827. doi:10.1080/136588198241518
Kmoch, A., Vasilyev, I., Virro, H. and Uuemaa, E. (2022). Area and shape distortions in open-source discrete global grid systems. Big Earth Data 6(3), 256-275. doi:10.1080/20964471.2022.2094926
See Also
wall_metrics for the spacing of neighbouring cells,
cell_area
Examples
g <- hex_grid(resolution = 3, aperture = 3)
m <- cell_metrics(grid = g)
summary(m$compactness)
# Fuller's projection is not equal-area: compare the spread of areas
gf <- hex_grid(resolution = 3, aperture = 3, projection = "fuller")
mf <- cell_metrics(grid = gf)
sd(mf$area_km2) / mean(mf$area_km2)
Convert Cell ID to Hierarchical Index String
Description
Advanced function for working with hierarchical index strings. Most users don't need this - use cell IDs directly.
Usage
cell_to_index(
cell_id,
grid,
form = c("string", "int", "hex", "monotonic", "textZIRS", "uint64ZIRS")
)
Arguments
cell_id |
Cell IDs: integer64 for ISEA grids (whole numbers below 2^53 and digit strings are accepted), character for H3 grids |
grid |
A HexGridInfo or HexData object |
form |
The form of the identifier. |
Details
A cell ID numbers the cells of one resolution from 1, so it names a cell
only together with its grid. The index string carries its resolution in
its length and names one cell among all resolutions of the grid's family,
and so serves as the zonal identifier of OGC Topic 21; an H3 index carries
its resolution in its bits. A Hex9 index is the cell's label in 'libhex9',
Griffin's reference implementation: its digits, one per resolution (0-9 and
a, b for the twelve cells of resolution 0), a dot, and the key tail
(0-5), as in "435878503.3".
Value
Character vector of hierarchical index strings, or the form
form names
IGEO7 integer forms
The Z7 string of an aperture-7 cell is two decimal digits naming its base cell (00-11) and one digit 0-6 per resolution. The packed index holds the same fields in 64 bits (Kmoch et al. 2025): the base cell in bits 63-60, then three bits per digit, resolution 1 in bits 59-57 down to resolution 20 in bits 2-0, and the digit 7 (binary 111) at every resolution below the cell's own. "033000" packs to 0x3600ffffffffffff. The packed index exists up to resolution 20, IGEO7's finest.
integer64 is a signed type, so "int" keeps the 64 bits and reads them as
a signed number: the indices of base cells 08-11, whose top bit is set,
print as negative numbers and sort before those of base cells 00-07. The
one packed index whose bits are 2^63, the pentagon of base cell 08 at
resolution 20, is the bit pattern bit64 reserves for NA, so as integer64
it cannot be told from a missing value. "hex" carries every index
exactly.
The monotonic ID reads the Z7 string as a number: the base cell times 7^r plus the r digits as a base-7 number, so "033000" is 3 * 7^4 + 3 * 7^3 = 8232. Within one resolution it sorts as the strings do, and the deleted subsequence under each pentagon leaves its numbers unused. It reaches resolution 21, where it still fits in a signed 64-bit integer.
OGC zone identifiers
"textZIRS" and "uint64ZIRS" are the identifiers DGGAL writes for OGC's
ISEA3H, ISEA7H, IVEA3H and IVEA7H. textZIRS names a zone by its level (a
letter; for aperture 3 the level of the even resolution at or below), a
root rhombus 0-9 (two icosahedron faces; A and B for the two polar zones),
a sub-rhombus counted row by row within it in hexadecimal, and a letter
for the zone among those at that sub-rhombus. uint64ZIRS packs the same
fields into one integer. They depend on which cell is which, not on where
the solid sits, so they are written for any orientation and face
projection; they name OGC's zones on hex_grid(aperture = 3, ellipsoid = "WGS84", orientation = "ogc"), its aperture-7 twin, and the same with
projection = "ivea". Aperture-7 zones exist up to level 19.
References
Kmoch, A., Sahr, K., Chan, W. T., Uuemaa, E. (2025). IGEO7: A new hierarchically indexed hexagonal equal-area discrete global grid system. AGILE: GIScience Series 6, 32. doi:10.5194/agile-giss-6-32-2025
Open Geospatial Consortium. OGC API - Discrete Global Grid Systems, DGGRS definition examples ISEA3H, ISEA7H, IVEA3H and IVEA7H. https://github.com/opengeospatial/ogcapi-discrete-global-grid-systems
See Also
index_to_cell() for the inverse
Examples
g <- hex_grid(resolution = 4, aperture = 7)
cell <- index_to_cell("033000", g)
cell_to_index(cell, g, form = "hex")
cell_to_index(cell, g, form = "monotonic")
ogc <- hex_grid(resolution = 8, aperture = 3, ellipsoid = "WGS84",
orientation = "ogc")
crimea <- lonlat_to_cell(34.78, 45.43, ogc)
cell_to_index(crimea, ogc, form = "textZIRS")
cell_to_index(crimea, ogc, form = "uint64ZIRS")
Convert Cell ID to Longitude/Latitude
Description
Converts DGGS cell IDs back to geographic coordinates (cell centers).
Usage
cell_to_lonlat(cell_id, grid)
Arguments
cell_id |
Cell IDs: integer64 for ISEA grids (whole numbers below 2^53 and digit strings are accepted), character for H3 grids |
grid |
A HexGridInfo or HexData object |
Value
Data frame with lon_deg and lat_deg columns
See Also
lonlat_to_cell for the forward operation
Examples
grid <- hex_grid(area_km2 = 1000)
cells <- lonlat_to_cell(c(0, 10), c(45, 50), grid)
coords <- cell_to_lonlat(cells, grid)
Convert Cell IDs to sf Polygons
Description
Creates sf polygon geometries for hexagonal grid cells.
Usage
cell_to_sf(
cell_id = NULL,
grid,
wrap_dateline = TRUE,
densify = NULL,
max_km = NULL,
shape = c("hexagon", "gosper", "descendants"),
depth = 3L
)
Arguments
cell_id |
Cell IDs (integer64 for ISEA, character for H3). If NULL and x is HexData, uses cells from x. |
grid |
A HexGridInfo or HexData object. If HexData and cell_id is NULL, polygons are generated for all cells in the data. |
wrap_dateline |
Logical. If TRUE (default), calls
|
densify |
Points added along each cell edge: every edge is halved
until the straight line in longitude and latitude between consecutive
points stays within |
max_km |
Longest edge piece, in km on the grid's sphere: edges are
halved further until no straight piece between consecutive points spans
more than |
shape |
|
depth |
For |
Details
When called with a HexData object and no cell_id argument, this function generates polygons for all unique cells in the data, which is useful for plotting.
An ISEA cell edge is straight on its icosahedron face and curved in longitude and latitude, so ISEA polygons are densified by default. An H3 cell edge is a great-circle arc between corners, which sf reads exactly from the corners alone when it uses s2; densify H3 cells for planar work, or to draw them on a flat map.
A Gosper island replaces every cell edge by three segments
1/\sqrt{7} as long, turned by \arctan(\sqrt{3}/5), and repeats
this depth times; its outline approaches the flowsnake. The
replacement is drawn on the face plane of the projection and moves as much
area out of a cell as into it, so on an equal-area grid an island has
exactly its cell's area, and neighbouring islands share their boundary, so
the islands of a grid tile the sphere. The twelve pentagonal cells give
five-sided islands.
The descendant outline of an aperture-7 cell is the boundary of its
descendants depth resolutions down. It covers exactly the cell's
area, the outlines of one resolution tile the sphere, and an outline is the
union of its children's outlines, so they nest across resolutions. The
child lattice of an aperture-7 ISEA grid turns one way at one resolution and
back at the next, so the outline stays close to the hexagon rather than
approaching a Gosper island.
Either shape is drawn around the cell's hexagon: a point near the boundary
can lie in one cell's shape and be assigned to the neighbouring cell by
lonlat_to_cell.
Value
sf object with cell_id and geometry columns
See Also
hex_grid for grid specifications,
st_as_sf for converting HexData to sf
Examples
# From grid specification
grid <- hex_grid(area_km2 = 1000)
cells <- lonlat_to_cell(c(0, 10, 20), c(45, 50, 55), grid)
polys <- cell_to_sf(cells, grid)
# From HexData (all cells)
df <- data.frame(lon = c(0, 10, 20), lat = c(45, 50, 55))
result <- hexify(df, lon = "lon", lat = "lat", area_km2 = 1000)
polys <- cell_to_sf(grid = result)
# Cells drawn as Gosper islands, and as the outline of their descendants
g7 <- hex_grid(resolution = 3, aperture = 7)
cells <- lonlat_to_cell(c(0, 10), c(45, 50), g7)
islands <- cell_to_sf(cells, g7, shape = "gosper", depth = 3)
outlines <- cell_to_sf(cells, g7, shape = "descendants", depth = 2)
Get Cell IDs
Description
Extract the unique cell IDs present in a HexData object.
Usage
cells(x)
Arguments
x |
A HexData object |
Value
A vector of cell IDs
Examples
df <- data.frame(lon = c(0, 0.01, 20), lat = c(45, 45, 55))
cells(hexify(df, lon = "lon", lat = "lat", area_km2 = 1000))
Find Closest Resolution for Target Cell Area
Description
Finds the grid resolution that produces cells closest to the target area.
This is primarily used internally by hexify_grid and
hex_grid. Most users should use those functions directly.
Usage
dg_closest_res_to_area(
dggs,
area,
round = "nearest",
metric = TRUE,
show_info = FALSE
)
Arguments
dggs |
Grid specification (aperture and topology must be set) |
area |
Target cell area in km^2 (if metric=TRUE) |
round |
Rounding method ("nearest", "up", "down") |
metric |
Whether area is in metric units |
show_info |
Print information about chosen resolution |
Value
Resolution level (integer)
See Also
Other grid statistics:
dgearthstat(),
hexify_area_to_eff_res(),
hexify_compare_resolutions(),
hexify_eff_res_to_area(),
hexify_eff_res_to_resolution(),
hexify_resolution_to_eff_res()
Examples
grid <- hex_grid(resolution = 5, aperture = 3)
dg_closest_res_to_area(grid, area = 1000, show_info = TRUE)
Get Grid Statistics for Whole-Body Coverage
Description
Calculates statistics about the hexagonal grid at the current resolution,
including total number of cells, cell area, and cell spacing. Figures follow
the radius the grid carries, so a grid built with radius_km reports
that body's areas and distances.
Usage
dgearthstat(dggs)
Arguments
dggs |
Grid specification from hexify_grid() |
Value
List with components:
area_km |
Total surface area of the body in km^2 |
n_cells |
Total number of cells at this resolution |
cell_area_km2 |
Average cell area in km^2 |
cell_spacing_km |
Average distance between cell centers in km |
resolution |
Resolution level |
aperture |
Grid aperture |
See Also
Other grid statistics:
dg_closest_res_to_area(),
hexify_area_to_eff_res(),
hexify_compare_resolutions(),
hexify_eff_res_to_area(),
hexify_eff_res_to_resolution(),
hexify_resolution_to_eff_res()
Examples
grid <- hexify_grid(area = 1000, aperture = 3)
stats <- dgearthstat(grid)
print(sprintf("Resolution %d has %.0f cells",
stats$resolution, stats$n_cells))
print(sprintf("Average cell area: %.2f km^2",
stats$cell_area_km2))
print(sprintf("Average cell spacing: %.2f km",
stats$cell_spacing_km))
Create DGGRID 43H Aperture Sequence
Description
Create an aperture sequence following DGGRID's 43H pattern: first num_ap4 resolutions use aperture 4, then aperture 3.
Usage
dggrid_43h_sequence(num_ap4, num_ap3)
Arguments
num_ap4 |
Number of aperture-4 resolutions |
num_ap3 |
Number of aperture-3 resolutions |
Value
Integer vector of aperture sequence
See Also
Other 'dggridR' compatibility:
as_dggrid(),
dggrid_is_compatible(),
from_dggrid()
Examples
# DGGRID 43H with 2 ap4 resolutions, then 3 ap3 resolutions
seq <- dggrid_43h_sequence(2, 3) # c(4, 4, 3, 3, 3)
Validate 'dggridR' Grid Compatibility with hexify
Description
Checks whether a 'dggridR' grid object is compatible with hexify functions. Returns TRUE if compatible, or throws an error describing incompatibilities.
Usage
dggrid_is_compatible(dggs, strict = TRUE)
Arguments
dggs |
A 'dggridR' grid object |
strict |
If TRUE (default), throw errors for incompatibilities. If FALSE, return FALSE instead of throwing errors. |
Value
TRUE if compatible, FALSE if not compatible (when strict=FALSE)
See Also
Other 'dggridR' compatibility:
as_dggrid(),
dggrid_43h_sequence(),
from_dggrid()
Examples
dggrid_is_compatible(as_dggrid(hex_grid(resolution = 4, aperture = 7)))
dggrid_is_compatible(list(projection = "ISEA", topology = "DIAMOND",
aperture = 4, res = 4), strict = FALSE)
Definition of a Grid as a Discrete Global Grid Reference System
Description
Describes a grid in the DGGRS definition schema of OGC API - Discrete Global Grid Systems: the hierarchy of grids (solid, refinement ratio, refinement strategy, zone shapes, orientation), the zone identifiers and the order of sub-zones.
Usage
dggrs_definition(grid)
Arguments
grid |
A HexGridInfo or HexData object. |
Details
The definition describes the grid as hexify builds it. The zone
identifiers are the strings cell_to_index writes, which carry
their resolution and are unique across all resolutions, and the cell IDs,
which number the cells of one resolution from 1 and are unique only
together with it.
The ISEA3H, ISEA7H, IVEA3H and IVEA7H definitions registered with OGC
(https://www.opengis.net/def/dggrs/OGC/1.0/ISEA7H) convert WGS84
geodetic latitude to authalic latitude before projecting, and place the
icosahedron's first vertex at 11.20 degrees E and authalic latitude
\arctan(\phi): hex_grid(aperture = 3, ellipsoid = "WGS84",
orientation = "ogc"), its aperture-7 twin and the same with
projection = "ivea". For such a grid the definition carries OGC's
zone identifiers (cell_to_index(form = "textZIRS")) and links to the
OGC definition, which it matches in its hierarchy and zone identifiers; it
carries no OGC URI, since hexify lists sub-zones in ascending order of
cell ID rather than in OGC's scanlines. On a grid with an ellipsoid the
orientation's latitude is geodetic, as OGC states it.
Value
A named list with the schema's fields title,
description, dggh, zirs and subZoneOrder.
jsonlite::toJSON(x, auto_unbox = TRUE, pretty = TRUE) writes it as
JSON.
References
Open Geospatial Consortium. OGC API - Discrete Global Grid Systems - Part 1: Core. OGC 21-038r1. https://docs.ogc.org/is/21-038r1/21-038r1.html
See Also
Examples
def <- dggrs_definition(hex_grid(resolution = 5, aperture = 7))
def$dggh$definition$refinementRatio
def$zirs$textZIRS$description
Verify Grid Object
Description
Validates that a grid object has all required fields and valid values. This function is called internally by most hexify functions to ensure grid integrity.
Usage
dgverify(dggs)
Arguments
dggs |
Grid object to verify (from hexify_grid() or hex_grid()) |
Value
TRUE (invisibly) if valid, otherwise throws an error
Examples
grid <- hexify_grid(area = 1000, aperture = 3)
dgverify(grid) # Should pass silently
# Modern HexGridInfo objects are accepted too
dgverify(hex_grid(area_km2 = 1000))
# Invalid grid will throw error
bad_grid <- list(aperture = 5)
try(dgverify(bad_grid)) # Will error
Extract Grid from Various Objects
Description
Internal function to extract a HexGridInfo from different input types. Accepts HexGridInfo, HexData, or legacy hexify_grid objects.
Usage
extract_grid(x, allow_null = FALSE)
Arguments
x |
Object containing grid info |
allow_null |
If TRUE, return NULL when x is NULL |
Value
HexGridInfo object
Convert 'dggridR' Grid Object to hexify_grid
Description
Creates a hexify_grid object from a 'dggridR' dggs object. This allows using hexify functions with grids created by 'dggridR' dgconstruct().
Usage
from_dggrid(dggs, radius_km = EARTH_RADIUS_KM)
Arguments
dggs |
A 'dggridR' grid object from dgconstruct() |
radius_km |
Radius the grid is sized on, in km or as a body name. A dggs carries no radius, so the default is Earth's; pass this when the dggs describes a grid on another body. |
Details
The 'ISEA' and 'FULLER' projections with HEXAGON topology are supported. Other configurations will generate warnings.
A dggs has no field for the body it is sized on, so the resolution is all
that carries over and the result is an Earth grid unless radius_km
says otherwise. Cell area follows from the radius, so it is read from the
radius given rather than from the dggs.
The orientation carries over: pole_lon_deg, pole_lat_deg and
azimuth_deg place the icosahedron as DGGRID's dggs_vert0_lon,
dggs_vert0_lat and dggs_vert0_azimuth do, and a field left out
takes its standard ISEA value.
The function validates that the 'dggridR' grid uses compatible settings:
Projection must be 'ISEA' or 'FULLER'
Topology must be "HEXAGON" (DIAMOND, TRIANGLE not supported)
Aperture must be 3, 4, or 7
Value
A hexify_grid object
See Also
Other 'dggridR' compatibility:
as_dggrid(),
dggrid_43h_sequence(),
dggrid_is_compatible()
Examples
dggs <- as_dggrid(hex_grid(resolution = 4, aperture = 4))
from_dggrid(dggs)
Get Children Cells
Description
Returns the child cells at a finer resolution.
Usage
get_children(cell_id, grid, levels = 1L, as_sf = FALSE)
Arguments
cell_id |
Cell IDs: integer64 for ISEA grids (whole numbers below 2^53 and digit strings are accepted), character for H3 grids |
grid |
A HexGridInfo or HexData object |
levels |
Number of levels down (default 1) |
as_sf |
If |
Value
List of vectors of child cell IDs, one per input
cell; with as_sf = TRUE, an sf object with columns
parent_id, cell_id and geometry.
Examples
grid <- hex_grid(resolution = 3, aperture = 4)
parent <- lonlat_to_cell(10, 50, grid)
get_children(parent, grid)
kids <- get_children(parent, grid, levels = 2, as_sf = TRUE)
plot(sf::st_geometry(kids))
plot(sf::st_geometry(cell_to_sf(parent, grid)), border = "red", add = TRUE)
Get Neighboring Cells
Description
Returns the k-ring (disk) of cells neighboring the input cells.
For k = 1, returns the immediate 6 neighbors (5 for pentagons).
For k > 1, returns all cells within k grid hops.
Usage
get_neighbors(
cell_id,
grid,
k = 1L,
include_self = FALSE,
distances = FALSE,
as_sf = FALSE,
ring = FALSE
)
Arguments
cell_id |
Cell IDs to find neighbors for: integer64 (or whole numbers) for ISEA grids, character for H3 grids. |
grid |
A HexGridInfo or HexData object specifying the grid. |
k |
Integer. Ring distance (default 1). |
include_self |
Logical. If |
distances |
Logical. If |
as_sf |
Logical. If |
ring |
Logical. If |
Details
For ISEA grids, neighbors are computed using axial coordinate offsets in the quad IJ space. On aperture-7 grids of the icosahedron, a cell at a quad boundary takes its neighbors from digit arithmetic on its IGEO7 Z7 index, which is exact and needs no projection; on other ISEA grids such a cell's neighbors are found by reprojection through lon/lat coordinates.
For H3 grids, neighbors use the vendored H3 gridDisk /
gridDiskDistances functions.
Pentagon cells (the 12 icosahedron vertices) have only 5 neighbors instead of the usual 6.
Value
If distances = FALSE (default): a list of cell ID vectors, one
per input cell. If distances = TRUE: a list of data.frames with columns
cell_id and ring_distance. If as_sf = TRUE: an sf object of
lines (MULTILINESTRINGs when one is split at the antimeridian), one
row per cell and neighbour, with columns cell_id,
neighbor_id and ring_distance.
See Also
hexify() for creating HexData objects,
hex_distance() for grid distances between cells
Examples
# ISEA grid neighbors
g <- hex_grid(area_km2 = 1000)
cell <- lonlat_to_cell(10, 50, g)
nbrs <- get_neighbors(cell, g)
nbrs[[1]]
# H3 grid neighbors
g_h3 <- hex_grid(resolution = 5, type = "h3")
cell_h3 <- lonlat_to_cell(10, 50, g_h3)
get_neighbors(cell_h3, g_h3, k = 2)
# With distances
get_neighbors(cell, g, k = 2, distances = TRUE)
# Only the cells two hops away
get_neighbors(cell, g, k = 2, ring = TRUE)
# Links to the neighbours, drawn over the cells
links <- get_neighbors(cell, g, k = 2, as_sf = TRUE)
plot(sf::st_geometry(cell_to_sf(c(cell, links$neighbor_id), g)))
plot(sf::st_geometry(links), col = "red", add = TRUE)
Get Parent Cell
Description
Returns the parent cell at a coarser resolution.
Usage
get_parent(cell_id, grid, levels = 1L, overlapping = FALSE)
Arguments
cell_id |
Cell IDs: integer64 for ISEA grids (whole numbers below 2^53 and digit strings are accepted), character for H3 grids |
grid |
A HexGridInfo or HexData object |
levels |
Number of levels up (default 1) |
overlapping |
If |
Details
A cell's parent is the coarser cell holding its centre. The hexagons of
successive resolutions do not nest, so a cell can also reach into one or two
neighbours of that parent: an aperture-3 cell centred on a parent corner
lies a third in each of three parents, an aperture-4 cell centred on a
parent edge half in each of two, and an aperture-7 cell off the parent's
centre 11/12 in its parent and 1/12 in one neighbour. A Hex9 cell's parent
is the coarser cell holding the cell's mode-0 half (Griffin 2026); six of
every nine cells lie inside their parent, and the other three straddle its
boundary, half in each of two cells. Several levels up, a Hex9 cell's parent
is again the coarser cell holding its mode-0 half, Griffin's canonical
ancestor ('libhex9”s hex9_cell_ancestor), and
get_children returns the cells it is the ancestor of; on
every other grid it is the parent's parent.
overlapping = TRUE returns all of them, as the parent() query
of OGC Topic 21 does when inheritID is false; the default is its
inheritID = true answer. hex_aggregate divides cell
values among them by these shares.
Every part of a cell that lies in a coarser cell holds a corner of the cell, so the overlapping cells are the coarser cells holding the cell's corners, each taken a small step towards the centre.
Value
Parent cell IDs, of the type the grid's cell IDs have. With
overlapping = TRUE, a list with one vector per input cell, the
parent holding the cell's centre first.
Examples
grid <- hex_grid(resolution = 10)
child_cells <- lonlat_to_cell(c(0, 10), c(45, 50), grid)
parent_cells <- get_parent(child_cells, grid)
# Every coarser cell a cell reaches into
g3 <- hex_grid(resolution = 5, aperture = 3)
cells <- lonlat_to_cell(c(0, 10), c(45, 50), g3)
get_parent(cells, g3, overlapping = TRUE)
Sibling Cells
Description
Returns the other children of each cell's parent.
Usage
get_siblings(cell_id, grid, include_self = FALSE)
Arguments
cell_id |
Cell IDs: integer64 for ISEA grids (whole numbers below 2^53 and digit strings are accepted), character for H3 grids |
grid |
A HexGridInfo or HexData object |
include_self |
If |
Details
The parent is the one get_parent returns, the coarser cell
holding the cell's centre, and the siblings are its children as
get_children returns them: the siblingOf relation of
OGC Topic 21 with inheritID true.
Value
List with one vector of cell IDs per input cell.
See Also
Examples
g <- hex_grid(resolution = 4, aperture = 7)
cell <- lonlat_to_cell(16.37, 48.21, g)
get_siblings(cell, g)
Globe Center Presets
Description
Named list of lon/lat coordinates for common globe views, accepted by the
center argument of the grid plot
method.
Usage
globe_centers
Format
Named list with elements:
- europe
c(10, 50) - Western/Central Europe
- north_america
c(-100, 45) - USA and Canada
- south_america
c(-60, -15) - Full continent
- africa
c(20, 5) - Central Africa
- asia
c(100, 35) - China, SE Asia, Japan
- oceania
c(135, -25) - Australia, NZ, Indonesia
- middle_east
c(45, 25) - Arabian Peninsula, Iran, Turkey
- south_asia
c(80, 20) - India, Pakistan, Bangladesh
- pacific
c(-160, -10) - Polynesia, Pacific islands
- caribbean
c(-70, 18) - Caribbean islands
- arctic
c(0, 90) - North pole view
- antarctic
c(0, -90) - South pole view
Examples
globe_centers$europe
globe_centers$oceania
Clip Hexagon Grid to Polygon Boundary
Description
Creates hexagon polygons clipped to a given polygon boundary. This is useful for generating grids that conform to country borders, study areas, or other irregular boundaries.
Usage
grid_clip(boundary, grid, crop = TRUE)
Arguments
boundary |
An sf/sfc polygon to clip to. Can be a country boundary, study area, or any polygon geometry. |
grid |
A HexGridInfo object specifying the grid parameters |
crop |
If TRUE (default), cells are cropped to the boundary. If FALSE, only cells whose centroids fall within the boundary are kept (no cropping). |
Details
The function first generates cells covering the boundary polygon, then clips or filters them. For H3 grids, all cells that overlap the boundary are included (not just cells whose center falls inside), ensuring full spatial coverage with no gaps along the boundary edge.
When crop = TRUE, hexagons are geometrically intersected with the
boundary, which may produce partial hexagons at the edges. When
crop = FALSE, only complete hexagons whose centroids fall within
the boundary are returned.
Value
sf object with hexagon polygons clipped to the boundary
See Also
grid_rect for rectangular grids,
grid_global for global grids
Examples
# Metropolitan France: the world map also carries the overseas departements,
# and grid_clip() covers the bounding box of whatever it is given.
france <- sf::st_crop(
sf::st_geometry(hexify_world[hexify_world$name == "France", ]),
c(xmin = -5, ymin = 41, xmax = 10, ymax = 52)
)
# Create grid clipped to France
grid <- hex_grid(area_km2 = 2000)
france_grid <- grid_clip(france, grid)
# Plot result
library(ggplot2)
ggplot() +
geom_sf(data = france, fill = "gray95") +
geom_sf(data = france_grid, fill = alpha("steelblue", 0.3),
color = "steelblue") +
theme_minimal()
# Keep only complete hexagons (no cropping)
france_grid_complete <- grid_clip(france, grid, crop = FALSE)
Generate a Global Hexagon Grid
Description
Creates hexagon polygons covering the entire Earth.
Usage
grid_global(grid, wrap_dateline = TRUE)
Arguments
grid |
A HexGridInfo object specifying the grid parameters |
wrap_dateline |
Logical. If TRUE (default), calls
|
Details
Every cell of the grid, one row each, in cell ID order for ISEA grids.
For large grids (many small cells), consider using grid_rect() to
generate regional subsets.
Value
sf object with hexagon polygons
See Also
grid_rect for regional grids
Examples
# Coarse global grid
grid <- hex_grid(area_km2 = 100000)
global <- grid_global(grid)
plot(global)
Get Grid Specification
Description
Extract the grid specification from a HexData object.
Usage
grid_info(x)
Arguments
x |
A HexData object |
Value
A HexGridInfo object
Examples
df <- data.frame(lon = c(0, 10, 20), lat = c(45, 50, 55))
result <- hexify(df, lon = "lon", lat = "lat", area_km2 = 1000)
grid_spec <- grid_info(result)
Generate a Rectangular Grid of Hexagons
Description
Creates hexagon polygons covering a rectangular geographic region. All cells that overlap the bounding box are included (not just cells whose center falls inside), ensuring full spatial coverage on both backends.
Usage
grid_rect(bbox, grid)
Arguments
bbox |
Bounding box as c(xmin, ymin, xmax, ymax), or an sf/sfc object |
grid |
A HexGridInfo object specifying the grid parameters |
Value
sf object with hexagon polygons
See Also
grid_global for global grids
Examples
grid <- hex_grid(area_km2 = 5000)
europe <- grid_rect(c(-10, 35, 30, 60), grid)
plot(europe)
Crosswalk Between ISEA and H3 Cell IDs
Description
Maps cell IDs between ISEA (equal-area) and H3 grid systems by looking up each cell's center coordinate in the target grid. This enables workflows where analysis is done in ISEA (exact equal-area) and reporting in H3 (industry-standard).
Usage
h3_crosswalk(
cell_id = NULL,
grid,
h3_resolution = NULL,
isea_grid = NULL,
direction = c("isea_to_h3", "h3_to_isea")
)
Arguments
cell_id |
Cell IDs to translate. integer64 for ISEA, character for H3.
When |
grid |
A HexGridInfo or HexData object. For |
h3_resolution |
Target H3 resolution for |
isea_grid |
A HexGridInfo for the target ISEA grid. Required when
|
direction |
One of |
Details
The crosswalk works by computing the center coordinate of each source cell, then finding which cell in the target grid contains that center. This is a many-to-one mapping: multiple ISEA cells may map to the same H3 cell (or vice versa) depending on the relative resolutions.
When h3_resolution is NULL and direction = "isea_to_h3",
the H3 resolution whose average cell area is closest to the ISEA cell area
is chosen automatically. This gives the best 1:1 correspondence.
Value
A data frame with columns:
- isea_cell_id
ISEA cell ID (integer64)
- h3_cell_id
H3 cell ID (character)
- isea_area_km2
Area of the ISEA cell in km2, as
cell_areareturns it- h3_area_km2
Geodesic area of the H3 cell in km2
- area_ratio
Ratio of ISEA area to H3 area
See Also
cell_area for per-cell area computation,
hex_grid for creating grids
Examples
# ISEA -> H3
grid <- hex_grid(area_km2 = 1000)
cells <- lonlat_to_cell(c(0, 10, 20), c(45, 50, 55), grid)
xwalk <- h3_crosswalk(cells, grid)
head(xwalk)
# H3 -> ISEA
h3 <- hex_grid(resolution = 5, type = "h3")
h3_cells <- lonlat_to_cell(c(0, 10), c(45, 50), h3)
xwalk2 <- h3_crosswalk(h3_cells, h3, isea_grid = grid, direction = "h3_to_isea")
Download Hex9's Warp Field
Description
Hex9's own projection (hex_grid(aperture = 9, projection = "akw"))
is Kaseorg's octahedral projection with an area-correcting warp that Griffin
trained by optimal transport and publishes with 'libhex9', his reference
implementation (Griffin 2026, Sec. 11b). The field is 19 MB of stored
displacements and gradients, which hexify reads but does not ship; this
function downloads it once from the 'libhex9' repository, checks it, and
saves it where hexify looks for it.
Usage
hex9_warp_download(path = hex9_warp_path(), quiet = FALSE)
Arguments
path |
Where to save the field. The default is hexify's user data
directory ( |
quiet |
Passed to |
Details
The file is 'libhex9”s core/Sphere_l6_fund.f64g.h9warp at the
commit of version 2.3.1, which the Hex9 agreement checks in hexify were run
against. 'libhex9' is Apache-2.0 licensed. Its field is defined on the unit
sphere: 'libhex9”s WGS84 functions first turn geodetic latitude into
authalic latitude, while hexify reads latitude as spherical latitude, as
'libhex9”s _sphere functions do.
Value
The path of the saved file, invisibly.
References
Griffin, B. (2026). Hex9: A Quasi-Authalic, Quasi-Continuous Hexagonal DGGS on the Reference Ellipsoid. arXiv:2608.00022.
Examples
if (interactive()) {
hex9_warp_download()
g <- hex_grid(resolution = 5, aperture = 9, projection = "akw")
lonlat_to_cell(16.37, 48.21, g)
}
Aggregate Cell Values to a Coarser Resolution
Description
Adds up, or averages, values given on cells into the cells levels
resolutions coarser. The hexagons of successive resolutions do not nest, so
a cell can lie partly in two or three coarser cells; rule says how
its value is divided among them.
Usage
hex_aggregate(
cell_id,
value,
grid,
levels = 1L,
rule = c("area", "centre"),
measure = c("total", "mean"),
na.rm = FALSE
)
Arguments
cell_id |
Cell IDs, each listed once. |
value |
Numeric vector with one value per cell, or a numeric matrix or data frame with one row per cell, each column aggregated on its own. |
grid |
A HexGridInfo or HexData object at the resolution of
|
levels |
Number of resolutions up. |
rule |
|
measure |
|
na.rm |
If |
Details
The two rules. Write |c \cap p| / |c| for the share of
cell c's area that lies in the coarser cell p. The area rule
gives p that share of c's value, which assumes the amount is
spread evenly over c; the centre rule gives p all of it when
p holds c's centre and nothing otherwise. A cell's shares add
up to one under both, so both keep the total of the values. Only the area
rule keeps where the amount lies: a uniform density gives every
hexagonal coarser cell the same total under it, and each vertex cell
(the twelve pentagons of the icosahedron) its sides over six of that.
A mean is the total of value times area over the total area, both
aggregated by the same rule.
Shares on the lattice. Within a face, the cells of one resolution
are the Voronoi cells of a hexagonal lattice and those of the next coarser
resolution the Voronoi cells of a sublattice, of index 3, 4 or 7, the
aperture of the step. After an aperture-3 step the cells are centred on
the parent centres and corners: the three parent edges meeting at a
corner run through every second edge midpoint of the cell centred there
and cut it into thirds. After an aperture-4 step the cells are centred on
the parent centres and edge midpoints: a parent edge runs through the
centre and two opposite corners of the cell on its midpoint and cuts it in
half. After an aperture-7 step every centre lies inside a parent. Take the
finer lattice as the Eisenstein integers Z[\omega],
\omega = e^{2\pi i/3}, with unit spacing, so a cell has circumradius
s = 1/\sqrt{3}. The parent lattice is \mu Z[\omega] with
\mu = 3 + \omega, |\mu|^2 = 7, turned by
\arg \mu = \arctan(\sqrt{3}/5) (the mirror image
3 + \bar\omega at the other twist). The centre child, of
circumradius s, lies inside its parent, of inradius
\sqrt{7}/2. The parent edge facing the neighbour at \mu runs
from the parent corner \mu(1 - \omega)/3 = 1 + (1 - \omega)/3, which
is a corner A of the ring child centred at 1, through the parent's
edge midpoint \mu/2 = (1 + (2 + \omega))/2, which is the midpoint of
the edge the children at 1 and 2 + \omega share. That edge is the
second from A, so the part of the child at 1 beyond its parent is
the triangle of A, the next corner B and \mu/2: sides
s and s/2 at 120 degrees, area \sqrt{3}s^2/8 against
3\sqrt{3}s^2/2 for the cell, one twelfth. The half-turn about
\mu/2 swaps the two parents and the two children, so the edge cuts
one twelfth off the child at 2 + \omega the other way. Each of the
six ring children lies 11/12 in its parent and 1/12 in one neighbour, and
the parent's area checks: 1 + 6 \cdot 11/12 + 6 \cdot 1/12 = 7.
A Hex9 step (aperture 9 on the octahedron, Griffin 2026) divides each
triangle of the solid's lattice into nine. A cell is the six lattice
triangles around its centre, so a parent's edges are lines of the coarser
lattice and therefore of the finer one. Six of a parent's nine children
lie inside it; the other three are centred on its edges, and the edge
through such a child's centre cuts it into its two half-hexagons, three
triangles each: half in each of two parents. The parent's area checks:
6 + 6 \cdot 1/2 = 9 children's worth.
The vertices of the solid are cell centres at every resolution, and the
turn by the angle deficit about a vertex maps both lattices onto
themselves, so the cells around a vertex are cut as in the plane; the cell
at a vertex lies wholly inside the vertex cell above it. On Hex9 the
vertices are lattice points no cell is centred on, and the cells there are
cut along lattice lines as everywhere. Snyder's projection
and the vertex-oriented one ("ivea") are equal-area, so these plane
shares are the shares on the sphere, for every cell, across quad and face
edges and at the vertices. get_parent with
overlapping = TRUE finds the coarser cells a cell overlaps, its own
parent first, and the share follows from their number and the aperture of
the step: one parent, 1; three after an aperture-3 step, 1/3 each; two
after aperture 4, 1/2 each; two after aperture 7, 11/12 to the parent and
1/12 to the neighbour; two after a Hex9 step, 1/2 each, the parent holding
the child's mode-0 half first.
Several levels. levels > 1 applies the one-level rule level
by level, each step with the shares of its own aperture: a grid built with
aperture = c(3, 7, 4) aggregates from resolution 3 with halves, then
twelfths, then thirds. A value at an intermediate resolution is again taken
as spread evenly over its cell, so several levels up the area rule is the
one-level rule repeated rather than the share of a fine cell's area in a
coarse cell.
Fuller's projection and H3. Neither is equal-area, so the plane shares do not carry over to the sphere, and each share is measured. Both cells are clipped against each other where they are straight, which makes the pieces exact: an ISEA-family cell on each face plane it covers, an H3 cell on the gnomonic plane at the finer cell's centre, where its great-circle edges are straight. An H3 piece is a spherical polygon whose area is a sum of spherical triangles, exact to rounding. A face-plane piece has curved edges on the sphere; its area is that of the polygon through equally spaced points of its edges, extrapolated to infinitely many points (Romberg), which leaves an error near rounding. The share is a piece's area over that of all the cell's pieces. Measured this way on Snyder's projection, the shares come out as the lattice's.
Value
A data frame with one row per coarser cell that receives a share
of any listed cell, sorted by cell_id, and the aggregated values:
a column value for a vector, the columns of value
otherwise. With measure = "mean", a coarser cell whose
contributing cells are all NA gets NA.
References
Carr, D. B., Kahn, R., Sahr, K., Olsen, A. R. (1997). ISEA discrete global grids. Statistical Computing & Graphics Newsletter 8(2/3): 31-39.
See Also
get_parent for the coarser cells a cell overlaps,
hex_summarize to aggregate points into cells
Examples
g <- hex_grid(resolution = 4, aperture = 3)
ids <- grid_global(g)$cell_id
set.seed(1)
counts <- rpois(length(ids), 5)
area <- hex_aggregate(ids, counts, g)
centre <- hex_aggregate(ids, counts, g, rule = "centre")
c(sum(counts), sum(area$value), sum(centre$value))
# A uniform density: every parent gets its own area, the hexagons one
# value and the twelve pentagons 5/6 of it
density <- cell_area(ids, g)
range(hex_aggregate(ids, density, g, levels = 2)$value)
# Values per unit area average instead
hex_aggregate(ids, data.frame(a = counts, b = 2 * counts), g,
measure = "mean")[1:3, ]
Interactive Hex Map
Description
Opens an interactive leaflet map with hexagonal cell polygons. Cells can be colored by a data column, with popups showing cell information on click.
Usage
hex_browse(
hex_data,
grid = NULL,
value = NULL,
palette = "viridis",
opacity = 0.7
)
Arguments
hex_data |
A HexData object, or a data.frame with a |
grid |
A HexGridInfo object. Required if |
value |
Optional column name (character) to color cells by.
If |
palette |
Color palette name for continuous values. Default |
opacity |
Fill opacity (0-1). Default 0.7. |
Details
Requires the leaflet package (in Suggests). The map is built using
st_as_sf() to generate polygon geometries, then rendered as a leaflet
choropleth.
Value
A leaflet map object (can be printed or embedded in Shiny).
See Also
hexify_heatmap() for static ggplot2 maps,
st_as_sf() for sf conversion
Examples
if (requireNamespace("leaflet", quietly = TRUE)) {
df <- data.frame(
lon = runif(50, -5, 5),
lat = runif(50, 45, 55),
value = rnorm(50)
)
hd <- hexify(df, lon = "lon", lat = "lat", area_km2 = 500)
hex_browse(hd, value = "value")
}
Compact Hex Cells
Description
Merges child cells into their parent when all children are present, so that the same set of cells is named by fewer of them.
Usage
hex_compact(cell_ids, grid)
Arguments
cell_ids |
Cell IDs to compact. For H3 grids, a character vector.
For ISEA grids, a character vector of hierarchical index strings, as
|
grid |
A HexGridInfo object specifying the grid. |
Details
H3 backend: Uses the vendored H3 compactCells function.
ISEA backend: Cells are grouped by get_parent(), and a group holding as
many distinct cells as its parent has children replaces them, from the finest
resolution up until no further compaction is possible. That count is the
aperture away from the twelve icosahedron vertices and fewer at one, and it
is read rather than assumed: a vertex cell sits at the corner of several
quads and carries an index spelling in each, so appending a digit to any one
spelling names neither all of its children nor only its children.
What is preserved is the set of cells: uncompacting the result at the original resolution returns the input. The covered area is not identical, because a hexagonal hierarchy is not congruent at any aperture – a parent does not tile exactly into its children – so an area computed on the compacted set differs from one computed on the original.
Value
A character vector of compacted cell IDs. Cells that could be merged into parents appear as parent IDs at coarser resolution.
See Also
hex_uncompact() for the inverse operation,
get_parent(), get_children() for hierarchical operations
Examples
# H3 compaction
g <- hex_grid(resolution = 3, type = "h3")
parent <- "832830fffffffff"
children <- get_children(parent, g)[[1]]
compact <- hex_compact(children, g)
compact # Should return the parent
# ISEA, on the default aperture
g <- hex_grid(resolution = 2, aperture = 3)
children <- cell_to_index(get_children(40L, g)[[1]],
hex_grid(resolution = 3, aperture = 3))
hex_compact(children, g)
Build an sf POLYGON from Six (lon, lat) Corner Pairs
Description
Low-level helper to create a single hexagon polygon from corner coordinates.
Most users should use cell_to_sf instead.
Usage
hex_corners_to_sf(lon, lat, crs = 4326)
Arguments
lon |
numeric vector of length 6 (longitude) |
lat |
numeric vector of length 6 (latitude) |
crs |
integer CRS (default 4326) |
Value
sf object with one POLYGON geometry
See Also
Other sf conversion:
hexify_cell_to_sf(),
hexify_grid_global(),
hexify_grid_rect()
Grid Distance Between Cells
Description
Computes the grid distance (minimum number of hops) between pairs of hexagonal cells. This is a discrete distance measured in cell steps, not a geodesic distance.
Usage
hex_distance(cell_a, cell_b, grid)
Arguments
cell_a, cell_b |
Cell IDs. Must be the same length (pairs) or one of them length 1 (broadcast). For H3 grids, character vectors. For ISEA grids, numeric vectors. |
grid |
A HexGridInfo or HexData object specifying the grid. |
Details
H3 backend: Uses the vendored H3 gridDistance function.
Returns the exact shortest path length in cell hops.
ISEA backend: Cells on the same quad are counted in the quad's own cell
lattice, where the six neighbours are one step away and the distance is the
axial hex distance max(|di|, |dj|, |di - dj|). The lattice is not always
the substrate the cell IDs are packed on – at aperture 3's odd resolutions
one substrate point in three is a cell – so the difference is divided by the
lattice generator first. Cross-quad distances use breadth-first search over
get_neighbors() and return NA beyond a hundred rings.
For geodesic (geographic) distances between cell centers, convert to
lon/lat with cell_to_lonlat() and use sf::st_distance().
Value
An integer vector of grid distances. NA where the distance
cannot be computed (e.g., pentagon path issues in H3).
See Also
get_neighbors() for finding cells within a given distance,
cell_to_lonlat() for geographic coordinates
Examples
# H3 grid distance
g <- hex_grid(resolution = 5, type = "h3")
a <- lonlat_to_cell(10, 50, g)
b <- lonlat_to_cell(10.1, 50.1, g)
hex_distance(a, b, g)
# ISEA: neighbouring cells are one hop apart
g <- hex_grid(resolution = 3, aperture = 3)
a <- lonlat_to_cell(10, 50, g)
hex_distance(a, get_neighbors(a, g)[[1]], g)
Extract Raster Values at Hex Cell Centers
Description
Samples raster values at hexagonal cell centers. Faster than
hex_zonal() because it only queries cell center points, not full
polygons.
Usage
hex_extract(raster, grid, cells = NULL, boundary = NULL)
Arguments
raster |
A |
grid |
A HexGridInfo or HexData object specifying the grid. |
cells |
Optional cell IDs to extract. If |
boundary |
Optional sf polygon to limit extraction extent. |
Details
Requires the terra package (in Suggests). The function:
Generates cell centers for the raster extent
Calls
terra::extract(raster, cell_center_matrix)Attaches cell IDs
For full zonal statistics (aggregating all pixels within each hex polygon),
use hex_zonal() instead.
Value
A data.frame with columns cell_id, plus one column per raster
layer.
See Also
hex_zonal() for polygon-based zonal statistics,
hexify() for creating HexData objects
Examples
if (requireNamespace("terra", quietly = TRUE)) {
# Create a small synthetic raster
r <- terra::rast(nrows = 10, ncols = 10,
xmin = -10, xmax = 10, ymin = 40, ymax = 55)
terra::values(r) <- runif(100)
names(r) <- "temperature"
# Extract at hex cell centers
g <- hex_grid(area_km2 = 500)
df <- data.frame(lon = c(0, 5), lat = c(45, 50))
hd <- hexify(df, lon = "lon", lat = "lat", grid = g)
hex_extract(r, hd)
}
Interactive Globe of a Grid
Description
Draws the cells of a grid on a globe that turns under the mouse, rendered on the graphics card through WebGPU. A slider folds the solid the grid is built on into the sphere, and the shader blends the two surfaces. Values given per cell fill the cells through a colour ramp.
Usage
hex_globe(
x,
values = NULL,
cells = NULL,
surface = c("sphere", "solid"),
lambert = NULL,
lambert_path = c("steps", "single"),
center = c(lon = 15, lat = 32),
projection = c("orthographic", "perspective"),
distance = NULL,
tilt = 0,
rotation = 0,
fov = NULL,
land = TRUE,
ocean_fill = "#F4F6F8",
land_fill = "#C9D0D6",
land_border = "#8C969F",
land_lwd = 0.4,
grid_border = "#0072B2",
grid_lwd = 0.8,
face_edges = NULL,
edge_col = "black",
edge_lwd = 1.1,
palette = "viridis",
limits = NULL,
na_fill = NA,
smooth = FALSE,
step = 0.01,
width = NULL,
height = NULL,
elementId = NULL
)
Arguments
x |
A HexGridInfo object; for |
values |
Numeric values, one per cell in |
cells |
Cell IDs to draw. |
surface |
Surface shown first, |
lambert |
|
lambert_path |
How the points move along the construction:
|
center |
Point the view looks down on: a preset name from
|
projection |
|
distance |
Distance of the untilted perspective camera from the
sphere's centre, in sphere radii; greater than 1. |
tilt |
Degrees the perspective camera swings about the point at
|
rotation |
Degrees the view turns about the line of sight; positive values turn north clockwise. |
fov |
Field of view of the perspective camera in degrees, across the
square the plot shows, centred on |
land |
|
ocean_fill |
Fill colour of the surface. |
land_fill |
Fill colour of land; |
land_border |
Colour of country outlines; |
land_lwd |
Line width of country outlines. |
grid_border |
Colour of cell boundaries. |
grid_lwd |
Line width of cell boundaries. |
face_edges |
Draw the edges of the solid's faces. |
edge_col |
Colour of face edges. |
edge_lwd |
Line width of face edges. |
palette |
Colours of the ramp from low to high values, or the name of
a palette of |
limits |
Values at the two ends of the ramp; |
na_fill |
Fill colour of cells whose value is |
smooth |
Whether the fill of an ISEA grid blends between the values of neighbouring cells, linearly across the triangles of cell centres, rather than filling each cell with its own value. |
step |
Spacing of the points along a cell boundary, as a fraction of a face edge. |
width, height |
Size of the widget, as CSS units or pixels. |
elementId |
Id of the widget's HTML element. |
Details
The cells of an ISEA grid are found per pixel on the graphics card, by the
same projection and cell numbering as lonlat_to_cell, so the
page holds the grid's description and the values rather than the cells'
outlines, and a grid of any resolution draws as fast as a coarse one.
Hex9 grids are found the same way; on Hex9's own projection
(projection = "akw") the page also carries the warp field
(hex9_warp_download), 9.6 MB as a texture.
The values sit on the graphics card as a texture laid out like the grid's
quads, one block per quad and resolution, which the shader reads at the
place it finds a cell. Where the cells shrink below a pixel the fill is
read from the grid one resolution coarser, and so on, whose cells take the
mean of the values in them, so a fine grid seen whole shows its pattern
rather than noise. Borders keep their width at every zoom and fade out
where the cells get too small to see. The pointer shows the ID and value
of the cell under it. H3 cells are drawn from their outlines.
With lambert, the slider instead follows Lambert's construction of
Snyder's projection (see projection_stages), on a grid with
that projection: from the sphere (0), every point swings about its face's
centre down onto the plane touching the sphere there, keeping its distance
from the centre (1, Lambert's azimuthal equal-area projection); within
that plane it moves to Snyder's azimuth and radius (2); and the plane
scales about the sphere's centre onto the face (3), the face of the solid
whose faces have the area of theirs on the sphere. The neighbouring faces'
planes come apart along the way and meet again on the solid. A menu
beside the slider switches between these three steps and one path per
point that changes the angle, azimuth and radius together.
Drag to turn the globe. Drag with Shift held to turn the view about the
line of sight and, in the perspective view, to tilt the camera. The mouse
wheel moves the perspective camera closer or zooms the orthographic view.
The view starts where the camera arguments, those of the grid's
plot method, place it.
The globe needs the 'htmlwidgets' package and a viewer or browser with WebGPU: Chrome and Edge (on Linux with some graphics cards only), Firefox on Windows and macOS, Safari 26, and RStudio's viewer. Without WebGPU the widget shows a notice instead. The article https://gillescolling.com/hexify/articles/globe.html lists the versions.
Value
An htmlwidget.
See Also
plot for the same
view as a static plot
Examples
if (requireNamespace("htmlwidgets", quietly = TRUE)) {
grid <- hex_grid(resolution = 3, aperture = 3)
hex_globe(grid)
hex_globe(grid, surface = "solid", center = "pacific")
cells <- seq_len(n_cells(grid))
centres <- cell_to_lonlat(cells, grid)
hex_globe(grid, values = centres$lat_deg, palette = "Blue-Red 3")
# Lambert's construction of Snyder's projection, opened at the Lambert
# points
hex_globe(grid, lambert = 1, land = FALSE)
}
Save a Globe as a PNG Image
Description
Draws a globe made by hex_globe with the same WebGPU
shader and pipelines the widget uses, and saves the view it opens with,
without its controls, as a PNG file. The image is drawn on the graphics
card and read back from it, so it is the same on a machine without a
display. Pixels off the globe are transparent.
Usage
hex_globe_png(
widget,
file,
width = 800,
height = 800,
scale = 1,
timeout = 30,
renderer = c("wgpu", "chrome")
)
Arguments
widget |
A globe from |
file |
Path of the PNG file to write. |
width, height |
Size of the view in CSS pixels. |
scale |
Image pixels per CSS pixel; 2 draws the view at twice the resolution. |
timeout |
Seconds to wait for the globe to be drawn in Chrome. |
renderer |
|
Details
renderer = "wgpu" draws through 'wgpu', the 'Rust' implementation
of WebGPU, in the 'hexglobe' package, with no browser.
renderer = "chrome" draws in headless Chrome, which needs the
'chromote' and 'htmlwidgets' packages and a Chromium browser, such as
Chrome or Edge, that chromote::find_chrome() finds; the browser is
started with its GPU, which WebGPU draws on.
Value
file, invisibly.
See Also
plot for a static
plot that needs no graphics card
Examples
# Drawing needs the hexglobe package and a GPU adapter
if (requireNamespace("hexglobe", quietly = TRUE) && interactive()) {
grid <- hex_grid(resolution = 3, aperture = 3)
globe <- hex_globe(grid, surface = "solid", center = "pacific")
hex_globe_png(globe, tempfile(fileext = ".png"), scale = 2)
}
Create a Hexagonal Grid Specification
Description
Creates a HexGridInfo object that stores all parameters needed for hexagonal grid operations. Use this to define the grid once and pass it to all downstream functions.
Usage
hex_grid(
area_km2 = NULL,
resolution = NULL,
aperture = 3,
type = c("isea", "h3"),
resround = "nearest",
crs = NULL,
radius_km = EARTH_RADIUS_KM,
orientation = "standard",
projection = c("isea", "fuller", "ivea", "ak", "akw"),
region = NULL,
polyhedron = c("icosahedron", "octahedron", "tetrahedron"),
ellipsoid = NULL
)
Arguments
area_km2 |
Target cell area in square kilometers. Mutually exclusive
with |
resolution |
Grid resolution level: for ISEA 0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7
on the icosahedron, where the cell count stays within the 2^63 - 1
cell IDs a 64-bit integer numbers; 0-18 for aperture 9 (Hex9); 0-15 for
H3.
Mutually exclusive with
|
aperture |
Grid aperture: 3 (default), 4, 7, 9 for Hex9 on the
octahedron (see the Hex9 section), a mixed family such as
"4/3", "4/7" or "7/4", or one aperture per resolution level as a vector,
e.g. |
type |
Grid type: "isea" (default) or "h3". |
resround |
Resolution rounding when using |
crs |
Coordinate reference system: an EPSG code, or a 'PROJ' or 'WKT'
string. Defaults to 'WGS84' on Earth, and to a longlat CRS on the sphere of
|
radius_km |
Radius of the body the grid covers, in kilometers, or the name of a body: "mercury", "venus", "earth" (default), "moon", "mars", "ceres", "jupiter", "io", "europa", "ganymede", "callisto", "saturn", "enceladus", "titan", "uranus", "neptune", "pluto". |
orientation |
Where the icosahedron of an ISEA grid sits on the
sphere: "standard" (default), "ogc", "dymaxion", "gosper", "random",
"region", "face", or
|
projection |
How an ISEA-family grid projects each icosahedron face
onto its plane triangle: "isea" (default), Snyder's equal-area
projection, "ivea", van Leeuwen and Strebe's vertex-oriented equal-area
projection, "fuller", Fuller's projection, or, on the octahedron, "ak",
Kaseorg's projection, or "akw", Kaseorg's with Hex9's trained warp
(see |
region |
For |
polyhedron |
The solid an ISEA-family grid is built on: "icosahedron" (default), "octahedron" or "tetrahedron". See the Polyhedron section. H3 grids are built on the icosahedron and take only the default. Aperture 9 is defined on the octahedron, which it takes when no solid is named. |
ellipsoid |
The ellipsoid of revolution an ISEA-family grid reads
geodetic latitude on: |
Details
Exactly one of area_km2 or resolution must be provided.
When area_km2 is provided, the resolution is calculated automatically
using the cell count formula: N = 10 * aperture^res + 2 (ISEA on the
icosahedron, 4 * aperture^res + 2 on the octahedron, 2 * aperture^res + 2
on the tetrahedron) or by matching the
closest H3 resolution.
H3 grids use the Uber H3 hierarchical hexagonal system. Unlike ISEA grids, H3 cells are NOT exactly equal-area: hexagon area varies by about a factor of 2 within a resolution, and by about 2.4 once the twelve pentagons are counted. The variation follows position on the icosahedron rather than latitude, with the smallest cells near face centres.
Value
A HexGridInfo object containing the grid specification.
Other Bodies
A grid is a partition of the sphere, and radius_km sets the sphere it
is measured on. Cell geometry – which cell a coordinate lands in, where cell
centres and corners sit, the hierarchy, the neighbours – is angular and
identical on every body; the radius sets the kilometer figures: cell area,
diagonal, spacing, and the resolution that area_km2 picks. Earth's
area comes from the 'WGS84' ellipsoid, every other radius gives the sphere
area 4pir^2.
mars <- hex_grid(area_km2 = 1000, radius_km = "mars") hex_grid(resolution = 8, radius_km = 3389.5) # the same grid
Both backends take a radius. 'H3' reports a cell's area as its solid angle times Earth's radius squared, so another radius scales those areas by the square of the radius ratio, exactly. One caveat carries: an 'H3' cell ID names a position in 'H3”s topology, which 'Uber”s 'H3' reads on Earth, so the IDs of a grid on another body are that topology on that body and are not interchangeable with Earth 'H3' data.
Earth Model
By default a grid reads geodetic latitude as latitude on its sphere, as
DGGRID and H3 do, and an Earth grid shares the 'WGS84' ellipsoid's area
among its cells. Measured geodesically on 'WGS84', the cells' areas then
run from 0.9955 times the reported area at the equator to 1.0090 times it
at the poles (paper/bench/bench_ellipsoid_area.R): within the 1
percent error budget OGC Topic 21 allows a spherical earth model for an
equal-area grid (Requirement 28), and systematic in latitude.
With ellipsoid, geodetic latitude is converted to authalic
latitude, the latitude on the sphere of the ellipsoid's area below which
that sphere holds the same area as the ellipsoid below the geodetic one,
before projecting, and back after. This carries the ellipsoid onto that
sphere keeping every area, so cells of Snyder's and of the vertex-oriented
projection are equal-area on the ellipsoid itself; on 'WGS84' the measured
areas agree with the reported ones to the measurement's own error, about
2e-6. Fuller's projection stays not equal-area, but its cell areas are
then the cells' areas on the ellipsoid. The conversion moves a point by up
to 0.13 degrees of latitude on 'WGS84', so a grid with an ellipsoid places
points in other cells than the same grid without one, and than DGGRID.
Cell IDs, the hierarchy and neighbours are the same; kilometre figures of
lengths are measured on the sphere of the ellipsoid's area.
The ISEA3H and ISEA7H DGGRS definitions OGC registers are
hex_grid(aperture = 3, ellipsoid = "WGS84", orientation = "ogc")
and its aperture-7 twin, and DGGAL's IVEA3H and IVEA7H the same with
projection = "ivea".
g <- hex_grid(resolution = 9, aperture = 3, ellipsoid = "WGS84") hex_grid(resolution = 6, aperture = 7, ellipsoid = "mars") hex_grid(resolution = 6, ellipsoid = c(6378.137, 1 / 298.257222101)) # GRS80
Orientation
An ISEA grid is built on a solid, an icosahedron unless polyhedron
names another, and its orientation places that solid on the sphere: vertex
0 at longitude vert0_lon and latitude vert0_lat, and vertex 1
at azimuth azimuth seen from vertex 0, all in degrees, as DGGRID's
dggs_vert0_lon, dggs_vert0_lat and dggs_vert0_azimuth
do.
"standard" is the ISEA orientation on the icosahedron: vertex 0 at 11.25E, 58.28N, azimuth 0, symmetric about the equator, with eleven of the twelve pentagons over the oceans and one in Sichuan (Sahr et al. 2003). On the octahedron it puts vertices at both poles and at longitudes 0, 90E, 180 and 90W on the equator.
"ogc" is the orientation of the ISEA3H and ISEA7H DGGRS definitions registered with OGC and of DGGAL's grids: vertex 0 at 11.20E and latitude arctan of the golden ratio (58.28N) on the sphere, azimuth 0. With
ellipsoid = "WGS84"that vertex lies at geodetic latitude 58.397145907431N."dymaxion" is Fuller's orientation of the icosahedron for his Dymaxion map: vertex 0 at 5.2454W, 2.3009N, azimuth 7.46658 (Sahr et al. 2003), with all twelve pentagons in the ocean. With
projection = "fuller"the grid lies on Fuller's Dymaxion map."gosper" places the octahedron as Van de Sande's Gosper World places its poles, at midpoints of octahedron edges: vertex 0 at 21.25W, 45N, vertex 1 across the north pole from it, all six vertices at least 619 km offshore.
net_layoutlays it out as four hexagons. The standard octahedron puts the poles at vertices instead, as Rus's four-hexagon map does."random" draws vertex 0 uniformly on the sphere and the azimuth uniformly in [0, 360), from R's random number generator, so
set.seed()repeats it. Grids in several random orientations show how much a result depends on where the cell boundaries fall."region" places the grid as DGGRID's
REGION_CENTERdoes: the centre ofregionlands on the midpoint of an edge of the solid, the middle of the two faces sharing it, far from the vertices where the vertex cells and the largest distortion sit."face" places the centre of
regionon the centre of a face. On the icosahedron that is about 20.9 degrees from the nearest face edge and 37.4 degrees from the nearest vertex, so a region up to about 40 degrees across lies on one face, away from the face edges where the projection bends.
Rotating the icosahedron rotates the grid with it, so cell IDs, the cell
hierarchy and neighbours are the same under every orientation; only where
each cell sits on the sphere changes. Every function taking the grid reads
its orientation. On a grid with an ellipsoid the orientation places
the solid on the sphere of the ellipsoid's area, so vert0_lat is an
authalic latitude; a region is given in geodetic latitude.
alps <- hex_grid(area_km2 = 100, orientation = "region", region = c(10, 46.5)) hex_grid(resolution = 8, orientation = c(0, 90, 0)) # vertex 0 at the pole
Projection
An ISEA-family grid lays its cells out on the plane triangles of the
icosahedron's faces, and the projection carries each spherical face onto its
triangle. With "isea", Snyder's icosahedral equal-area projection,
every cell of a resolution has the same area. With "ivea", van
Leeuwen and Strebe's (2006) vertex-oriented great-circle projection, cells
are equal-area as well: the projection maps the great circles through each
vertex of a face to straight lines, which leaves no cusps along the face
edges and gives lower, more even angular distortion than Snyder's (their
Table 1). These are DGGAL's IVEA3H and IVEA7H (Jacovella-St-Louis et al.
2025); DGGAL places the icosahedron at orientation = c(11.20,
58.282525588538995, 0), 0.05 degrees west of the standard one, and reads
latitudes as WGS84 geodetic, mapping them to the authalic sphere. With
"fuller", Fuller's
projection keeps lengths along the face edges and is not equal-area, so
area_km2 is the mean cell area and cell_area() reports each
cell's own; the Equal-Area Earth Reference System of OGC Topic 21 asks for
cells of equal area, so a Fuller grid falls outside it. These are DGGRID's
dggs_proj ISEA and FULLER,
giving FULLER3H, FULLER4H, FULLER7H and FULLER43H. Cell IDs, the hierarchy
and neighbours are the same under every projection; where each cell's
centre and corners sit on the sphere differs.
hex_grid(resolution = 5, aperture = 3, projection = "ivea") # IVEA3H hex_grid(resolution = 5, aperture = 4, projection = "fuller") # FULLER4H
Polyhedron
Snyder's equal-area projection and the vertex-oriented one are defined on every regular solid with triangular faces, and a hexagonal grid lies on the icosahedron, the octahedron and the tetrahedron alike: each pair of faces sharing an edge forms a diamond of cells, and the cell at each vertex has one side per face meeting there. The icosahedron has twelve pentagons, the octahedron six squares and the tetrahedron four triangles; every other cell is a hexagon, and every cell of a resolution has the same area except the vertex cells, which have five sixths, two thirds or one half of it, by their sides. The octahedron's cells are more distorted than the icosahedron's and the tetrahedron's more again, so they suit layouts that need their four- or three-fold symmetry rather than analysis. Fuller's projection is defined on the icosahedron only.
The tetrahedron unfolds into a strip of its two diamonds. Each long side of the strip folds onto itself at its midpoint, so the second diamond holds the far edge of its box in place of the near edge it shares with the first; its cells still number one box's worth.
hex_grid(resolution = 5, aperture = 4, polyhedron = "octahedron") hex_grid(resolution = 5, aperture = 4, polyhedron = "tetrahedron")
Hex9
aperture = 9 builds Hex9 (Griffin 2026), the hexagonal grid of the
octahedron that refines by 9 with no central child. Level L divides
each octahedron edge into 3^{L+1} steps of a triangular lattice and
centres a hexagon on every third lattice point, one class of a three-colouring
of the lattice that leaves the solid's vertices out; the octahedron's even
vertex valence keeps that class consistent across its faces, which the
icosahedron's odd valence does not. There are 12 \cdot 9^L cells, all
hexagons. Two meet at each of the six vertices, a corner each, and share both
edges there, so those twelve cells have five neighbours. On an equal-area
projection every cell has the same area.
A line through each cell's centre cuts it into two halves, each inside one
triangle of the next coarser level, and the cell is named through its half
in a triangle of Griffin's mode 0: one digit for each level of triangles
holding that half, digit 0 picking one of the twelve cells of resolution 0
(0-11) and every further digit one of nine (0-8). The cell ID is that digit
string read as a number, digit 0 counting 9^L, plus one, so the IDs of
a resolution run from 1 to 12 \cdot 9^L; the digit strings are those
of 'libhex9', Griffin's reference implementation, and
cell_to_index() writes a cell's 'libhex9' label, its digits and key
tail. A cell's parent is the cell of the coarser resolution holding its
mode-0 half, and every cell has nine children. Three of them straddle the
cell's boundary, so a cell's children cover it only in part.
Hex9's own projection is Kaseorg's octahedral projection, "ak"
(Griffin 2026, Sec. 11a): it maps each octant's weights on its three
vertices through tangents of the weights, coupled by a fitted constant, and
is not equal-area, its cells varying by about 20 percent in area across a
face. 'libhex9' corrects that with a warp of each face trained by optimal
transport (Sec. 11b): "akw" reads it (hex9_warp_download
fetches it), and a grid on it names every point by the cell 'libhex9”s
functions on the sphere name it. Any of the face projections serves the
same cells of the octahedron, with the same IDs; where each cell lies on
the sphere follows projection.
hex_grid(resolution = 4, aperture = 9) # Hex9 hex_grid(resolution = 4, aperture = 9, projection = "ivea") hex_grid(resolution = 4, aperture = 9, projection = "ak")
One Grid, Many Datasets
A HexGridInfo acts as a shared spatial reference system - like a CRS, but discrete and equal-area. Define the grid once, then attach multiple datasets without repeating parameters:
# Step 1: Define the grid once
grid <- hex_grid(area_km2 = 1000)
# Step 2: Attach multiple datasets to the same grid
birds <- hexify(bird_obs, lon = "longitude", lat = "latitude", grid = grid)
mammals <- hexify(mammal_obs, lon = "lon", lat = "lat", grid = grid)
climate <- hexify(weather_stations, lon = "x", lat = "y", grid = grid)
# No aperture, resolution, or area needed after step 1 - the grid
# travels with the data.
# Step 3: Work at the cell level
# Once hexified, lon/lat no longer matter - cell_id is the shared key
bird_counts <- aggregate(species ~ cell_id, data = as.data.frame(birds), length)
mammal_richness <- aggregate(species ~ cell_id, data = as.data.frame(mammals),
function(x) length(unique(x)))
# Join datasets by cell_id - guaranteed to align because same grid
combined <- merge(bird_counts, mammal_richness, by = "cell_id")
# Step 4: Visual confirmation
# All datasets produce identical grid overlays
plot(birds) # See the grid
plot(mammals) # Same grid, different data
See Also
hexify for assigning points to cells,
HexGridInfo-class for class documentation
Examples
# Create grid by target area
grid <- hex_grid(area_km2 = 1000)
print(grid)
# Create grid by resolution
grid <- hex_grid(resolution = 8, aperture = 3)
# Create grid with different aperture
grid4 <- hex_grid(area_km2 = 500, aperture = 4)
# Create mixed aperture grid
grid43 <- hex_grid(area_km2 = 1000, aperture = "4/3")
# Mix in aperture 7, either as a family or level by level
grid47 <- hex_grid(area_km2 = 1000, aperture = "4/7")
grid_seq <- hex_grid(resolution = 4, aperture = c(4, 4, 7, 3))
# Grid on another body, by name or by radius
mars <- hex_grid(area_km2 = 1000, radius_km = "mars")
titan <- hex_grid(resolution = 6, radius_km = 2574.76)
# Use grid in hexify
df <- data.frame(lon = c(0, 10, 20), lat = c(45, 50, 55))
result <- hexify(df, lon = "lon", lat = "lat", grid = grid)
Ray Glyphs for Cell Values
Description
Draws one ray per cell from its centre whose angle shows a value, as in Carr et al. (1997): the ray points down for the smallest value, level for the middle of the range and up for the largest. A confidence arc at the ray's tip spans the angles of a lower and an upper bound. A second variable gets a ray of its own pointing to the left from the same centre, so one glyph shows two values.
Usage
hex_rays(
cell_id,
value,
grid,
lower = NULL,
upper = NULL,
value2 = NULL,
lower2 = NULL,
upper2 = NULL,
limits = NULL,
limits2 = NULL,
length = 0.85
)
Arguments
cell_id |
Cell IDs, each listed once. |
value |
Values shown by the right-hand rays. |
grid |
A HexGridInfo or HexData object. |
lower, upper |
Optional bounds of |
value2, lower2, upper2 |
Optional second variable and its bounds, drawn to the left. |
limits |
Values drawn straight down and straight up: |
limits2 |
Limits of the second variable. |
length |
Length of a ray as a fraction of the distance from the cell centre to the middle of a wall. |
Details
Rays run in the plane tangent to the sphere at the cell centre, with up towards north, and are returned as lines in longitude and latitude, ready for any map of the cells.
Value
An sf object of LINESTRINGs with columns cell_id,
side ("right" or "left") and part
("ray" or "arc").
References
Carr, D. B., Kahn, R., Sahr, K., Olsen, A. R. (1997). ISEA discrete global grids. Statistical Computing & Graphics Newsletter 8(2/3): 31-39.
See Also
hex_triangles for the change towards each
neighbour
Examples
g <- hex_grid(resolution = 4, aperture = 3)
cells <- lonlat_to_cell(c(5, 10, 15), c(45, 47, 49), g)
trend <- c(-1, 0.2, 1.4)
rays <- hex_rays(cells, trend, g, lower = trend - 0.5, upper = trend + 0.5)
plot(sf::st_geometry(cell_to_sf(cells, g)))
plot(sf::st_geometry(rays), add = TRUE, col = "#D55E00")
Random Points Inside Cells
Description
Draws points uniformly over the area of each cell on the sphere, as
DGGRID's randpts output does; on a grid with an ellipsoid,
uniformly over its area on the ellipsoid. Each point is assigned back to its
cell by lonlat_to_cell, so the points of a cell are exactly
the points the grid places in it. Use set.seed() for a reproducible
draw.
Usage
hex_sample(cell_id, grid, n = 1L)
Arguments
cell_id |
Cell IDs. integer64 for ISEA grids, character for H3 grids. |
grid |
A HexGridInfo or HexData object. |
n |
Number of points per cell: one number, or one per cell. |
Details
Points are drawn uniformly in a spherical cap around the cell centre that holds the whole cell, and those outside the cell are drawn again.
Value
A data frame with columns cell_id, lon and
lat, the points of each cell together in the order of
cell_id.
See Also
cell_to_lonlat for cell centres
Examples
grid <- hex_grid(resolution = 3, aperture = 3)
cell <- lonlat_to_cell(10, 50, grid)
set.seed(1)
pts <- hex_sample(cell, grid, n = 200)
plot(sf::st_geometry(cell_to_sf(cell, grid)))
points(pts$lon, pts$lat, pch = 20, cex = 0.5)
Smooth Cell Values Over Neighbouring Cells
Description
Replaces each cell's value by the weighted mean of its own value and the
values of its edge neighbours, and repeats this steps times: the
neighbour-matrix smoother of Carr et al. (1997). Each neighbour has weight
1 and the cell itself self_weight. On an equal-area grid every cell
has the same area, so the mean is also the area-weighted mean.
Usage
hex_smooth(cell_id, value, grid, steps = 1L, self_weight = 1, group = NULL)
Arguments
cell_id |
Cell IDs, each listed once. |
value |
Numeric values, one per cell. |
grid |
A HexGridInfo or HexData object. |
steps |
Number of smoothing steps. Each step widens the reach by one ring of cells. |
self_weight |
Weight of a cell's own value relative to each
neighbour's. |
group |
Optional vector, one entry per cell; only neighbours in the same group contribute. |
Details
Only the cells in cell_id take part: a neighbour that is not listed,
or whose value is NA, does not contribute, so a cell at the edge of
the data averages over the neighbours it has. A pentagon averages over its
five neighbours. A cell whose value is NA stays NA.
group restricts the smoothing to cells of the same group, such as
land and ocean: a neighbour in another group does not contribute, so values
do not mix across a coastline. A cell whose group is NA keeps its
value and contributes to no other cell.
Value
Numeric vector of smoothed values, in the order of cell_id.
References
Carr, D. B., Kahn, R., Sahr, K., Olsen, A. R. (1997). ISEA discrete global grids. Statistical Computing & Graphics Newsletter 8(2/3): 31-39.
See Also
get_neighbors() for the neighbours a step averages over
Examples
g <- hex_grid(resolution = 4, aperture = 3)
cells <- grid_global(g)
set.seed(1)
noise <- rnorm(nrow(cells))
smooth <- hex_smooth(cells$cell_id, noise, g, steps = 3)
c(sd(noise), sd(smooth))
# Keep land and ocean apart
ctr <- sf::st_as_sf(cell_to_lonlat(cells$cell_id, g),
coords = c("lon_deg", "lat_deg"), crs = 4326)
land <- lengths(sf::st_intersects(ctr, hexify_world)) > 0
coastal <- hex_smooth(cells$cell_id, noise, g, steps = 3, group = land)
Summarize Data by Hex Cell
Description
Aggregates data within each hexagonal cell, similar to
dplyr::group_by(cell_id) |> summarize(...). Returns a data.frame
with one row per unique cell, including cell center coordinates and area.
Usage
hex_summarize(hex_data, ..., .fns = NULL, geometry = FALSE)
Arguments
hex_data |
A HexData object (from |
... |
Named summary expressions (tidyeval). Each expression is
evaluated per cell group with the group's columns available by name.
Examples: |
.fns |
Optional named list of functions for formula-style aggregation.
Example: |
geometry |
Logical. If |
Details
The function works entirely in R (no C++ needed). It groups by cell_id
and evaluates the summary expressions within each group.
If no summary expressions are provided, returns cell counts only.
Value
A data.frame with columns:
- cell_id
Unique cell identifier
- cell_cen_lon, cell_cen_lat
Cell center coordinates
- cell_area_km2
Cell area in km^2
- n_points
Number of data points in this cell
- ...
User-defined summary columns
If geometry = TRUE, returns an sf object with POINT geometry.
See Also
hexify() for creating HexData objects,
get_neighbors() for finding neighboring cells
Examples
df <- data.frame(
lon = runif(100, -10, 10),
lat = runif(100, 40, 55),
temperature = rnorm(100, 15, 5),
species = sample(letters[1:5], 100, replace = TRUE)
)
hd <- hexify(df, lon = "lon", lat = "lat", area_km2 = 500)
# Count points per cell
hex_summarize(hd)
# Custom summaries
hex_summarize(hd, mean_temp = mean(temperature),
n_species = length(unique(species)))
The Triangles of Cells Towards Each Neighbour
Description
Cuts each cell into one triangle per wall, from the centre to that wall: six for a hexagon, five for a pentagon. With values, each triangle carries the change from its cell's value to the neighbour's across the wall, so colouring the triangles shows the change from cell to cell in every direction (Carr et al. 1997, after K. and R. Keister).
Usage
hex_triangles(cell_id, grid, value = NULL)
Arguments
cell_id |
Cell IDs, each listed once. |
grid |
A HexGridInfo or HexData object. |
value |
Optional values, one per cell. A neighbour not in
|
Value
An sf object of POLYGONs with columns cell_id,
neighbor_id and, with values, value, neighbor_value
and change (neighbor_value - value).
References
Carr, D. B., Kahn, R., Sahr, K., Olsen, A. R. (1997). ISEA discrete global grids. Statistical Computing & Graphics Newsletter 8(2/3): 31-39.
See Also
hex_rays, get_neighbors,
wall_metrics
Examples
g <- hex_grid(resolution = 3, aperture = 3)
cells <- grid_rect(c(0, 40, 30, 60), g)$cell_id
ctr <- cell_to_lonlat(cells, g)
tri <- hex_triangles(cells, g, value = ctr$lat_deg)
plot(tri["change"], border = NA)
Uncompact Hex Cells
Description
Expands compacted cells to a target resolution. All cells in the output share the same resolution.
Usage
hex_uncompact(cell_ids, grid, target_resolution)
Arguments
cell_ids |
Character vector of (possibly mixed-resolution) cell IDs. |
grid |
A HexGridInfo object specifying the grid. |
target_resolution |
Integer. The resolution to expand all cells to. |
Details
H3 backend: Uses the vendored H3 uncompactCells function.
ISEA backend: Cells are expanded through get_children(), a level at a
time, until the target resolution is reached. Appending each digit of the
aperture names the children of a cell whose whole ancestry lies inside one
quad, but not those of a cell at an icosahedron vertex, whose children carry
index spellings in the several quads meeting there.
Value
A character vector of cell IDs, all at target_resolution.
See Also
hex_compact() for the inverse operation
Examples
g <- hex_grid(resolution = 3, type = "h3")
parent <- "832830fffffffff"
hex_uncompact(parent, g, target_resolution = 4L)
# ISEA, on the default aperture
g <- hex_grid(resolution = 2, aperture = 3)
hex_uncompact(cell_to_index(40L, g), g, target_resolution = 3L)
Zonal Statistics for Hex Cells
Description
Computes zonal statistics by aggregating all raster pixels falling
within each hexagonal cell polygon. More accurate than hex_extract()
but slower because it requires polygon geometries.
Usage
hex_zonal(raster, grid, fun = "mean", boundary = NULL, cells = NULL)
Arguments
raster |
A |
grid |
A HexGridInfo or HexData object specifying the grid. |
fun |
Summary function name: |
boundary |
Optional sf polygon to limit the analysis extent. |
cells |
Optional cell IDs. If provided, only these cells are included. |
Details
Requires the terra package (in Suggests). The function:
Generates hex polygon geometries via
cell_to_sf()Calls
terra::extract(raster, polygons, fun = fun)Joins results back to cell IDs
For point-based extraction (faster, at cell centers only), use
hex_extract() instead.
Value
A data.frame with columns cell_id, plus one column per raster
layer containing the aggregated values.
See Also
hex_extract() for cell-center extraction,
cell_to_sf() for hex polygon generation
Examples
if (requireNamespace("terra", quietly = TRUE)) {
r <- terra::rast(nrows = 100, ncols = 100,
xmin = -10, xmax = 10, ymin = 40, ymax = 55)
terra::values(r) <- runif(10000)
names(r) <- "temperature"
g <- hex_grid(area_km2 = 500)
df <- data.frame(lon = c(0, 5), lat = c(45, 50))
hd <- hexify(df, lon = "lon", lat = "lat", grid = g)
hex_zonal(r, hd, fun = "mean")
}
Assign Hexagonal DGGS Cell IDs to Geographic Points
Description
Takes a data.frame or sf object with geographic coordinates and returns a HexData object that stores the original data plus cell assignments. The original data is preserved unchanged; cell IDs and centers are stored in separate slots.
Usage
hexify(
data,
grid = NULL,
lon = "lon",
lat = "lat",
area_km2 = NULL,
diagonal = NULL,
resolution = NULL,
aperture = 3,
resround = "nearest",
radius_km = EARTH_RADIUS_KM
)
Arguments
data |
A data.frame or sf object containing coordinates |
grid |
A HexGridInfo object from |
lon |
Column name for longitude (ignored if data is sf) |
lat |
Column name for latitude (ignored if data is sf) |
area_km2 |
Target cell area in km^2 (mutually exclusive with diagonal). |
diagonal |
Target cell spacing in km: the short (flat-to-flat) diagonal, equal to the distance between neighbouring cell centres |
resolution |
Grid resolution (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7 on the icosahedron). Alternative to area_km2. |
aperture |
Grid aperture: 3, 4, 7, a mixed family such as "4/3" or
"4/7", or one aperture per resolution level, e.g. |
resround |
How to round resolution: "nearest", "up", or "down" |
radius_km |
Radius of the body the grid covers, in kilometers, or a body
name such as "mars" (default Earth). See |
Details
For sf objects, coordinates are automatically extracted and transformed to 'WGS84' (EPSG:4326) if needed. The geometry column is preserved.
Either area_km2, diagonal, or resolution
must be provided unless a grid object is supplied.
The HexData return type (default) stores the grid specification so downstream
functions like plot(), hexify_cell_to_sf(), etc. don't need
grid parameters repeated.
Value
A HexData object containing:
-
data: The original input data (unchanged) -
grid: The HexGridInfo specification -
cell_id: Cell IDs for each row (integer64 for ISEA, character for H3) -
cell_center: Matrix of cell center coordinates (lon, lat)
Use as.data.frame(result) to extract the original data.
Use cells(result) to get unique cell IDs.
Use result@cell_id to get all cell IDs.
Use result@cell_center to get cell center coordinates.
Grid Specification
You can create a grid specification once and reuse it:
grid <- hex_grid(area_km2 = 1000) result1 <- hexify(df1, grid = grid) result2 <- hexify(df2, grid = grid)
See Also
hex_grid for grid specification,
HexData-class for return object details,
st_as_sf for converting to sf
Other hexify main:
hexify_grid()
Examples
# Simple data.frame
df <- data.frame(
site = c("Vienna", "Paris", "Madrid"),
lon = c(16.37, 2.35, -3.70),
lat = c(48.21, 48.86, 40.42)
)
# New recommended workflow: use grid object
grid <- hex_grid(area_km2 = 1000)
result <- hexify(df, grid = grid, lon = "lon", lat = "lat")
print(result) # Shows grid info
plot(result) # Plot with default styling
# Direct area specification (grid created internally)
result <- hexify(df, lon = "lon", lat = "lat", area_km2 = 1000)
# Extract plain data.frame
df_result <- as.data.frame(result)
# With sf object (any CRS)
library(sf)
pts <- st_as_sf(df, coords = c("lon", "lat"), crs = 4326)
result_sf <- hexify(pts, area_km2 = 1000)
# Different apertures
result_ap4 <- hexify(df, lon = "lon", lat = "lat", area_km2 = 1000, aperture = 4)
# Mixed aperture (ISEA43H)
result_mixed <- hexify(df, lon = "lon", lat = "lat", area_km2 = 1000, aperture = "4/3")
Convert Area to Effective Resolution
Description
Finds the effective resolution that gives approximately the target area.
Usage
hexify_area_to_eff_res(area_km2)
Arguments
area_km2 |
Target area in km^2 |
Value
Effective resolution (may be fractional)
See Also
Other grid statistics:
dg_closest_res_to_area(),
dgearthstat(),
hexify_compare_resolutions(),
hexify_eff_res_to_area(),
hexify_eff_res_to_resolution(),
hexify_resolution_to_eff_res()
Assign Hex Cells ('ISEA3H', Aperture 3) for lon/lat
Description
Forward projection -> quantize -> cell centre -> inverse to lon/lat, on the
aperture-3 pipeline used by hexify(): points fold into the non-negative
quad frame (lonlat_to_cell()), and the centre comes back from the cell
itself (cell_to_lonlat()), so the returned centre is the centre of the
assigned cell.
Usage
hexify_assign(lon, lat, effective_res, make_polygons = FALSE)
Arguments
lon, lat |
numeric vectors (same length), degrees. |
effective_res |
integer effective resolution (>= 1). |
make_polygons |
logical; if TRUE, return an sf with hex polygons. |
Value
data.frame with id (Z3 index string), face (quad, 0-11), effective_res, center_lon, center_lat; if make_polygons=TRUE, an sf with geometry column.
Set the Default Icosahedron Orientation
Description
Sets the orientation read by the functions that take no grid: the
projection functions in this family and the low-level conversions that take
a resolution and an aperture. The standard ISEA orientation (vertex 0 at
11.25E, 58.28N, azimuth 0) is the default until this is called. A grid
carries its own orientation (see the orientation argument of
hex_grid), which this does not change.
Usage
hexify_build_icosa(
vert0_lon = ISEA_VERT0_LON_DEG,
vert0_lat = ISEA_VERT0_LAT_DEG,
azimuth = ISEA_AZIMUTH_DEG
)
Arguments
vert0_lon |
Vertex 0 longitude in degrees (default ISEA_VERT0_LON_DEG) |
vert0_lat |
Vertex 0 latitude in degrees (default ISEA_VERT0_LAT_DEG) |
azimuth |
Azimuth rotation in degrees (default ISEA_AZIMUTH_DEG) |
Value
Invisible NULL. Called for side effect.
See Also
Other projection:
hexify_face_centers(),
hexify_forward(),
hexify_forward_to_face(),
hexify_inverse(),
hexify_which_face()
Examples
# Use standard ISEA3H orientation
hexify_build_icosa()
# Custom orientation
hexify_build_icosa(vert0_lon = 0, vert0_lat = 90, azimuth = 0)
Convert Cell ID to Icosa Triangle Coordinates
Description
Converts DGGRID-compatible cell IDs to icosahedral triangle coordinates (face, x, y). These are the coordinates produced by the 'Snyder' 'ISEA' forward projection.
Usage
hexify_cell_to_icosa_tri(cell_id, resolution, aperture = 3L)
Arguments
cell_id |
Cell IDs, from 1: integer64, or whole numbers below 2^53 |
resolution |
Grid resolution level (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7) |
aperture |
Grid aperture: 3, 4, or 7 |
Details
Compatible with 'dggridR' dgSEQNUM_to_PROJTRI().
Value
Data frame with columns:
icosa_triangle_face |
Triangle face number (0-19) |
icosa_triangle_x |
X coordinate on triangle face |
icosa_triangle_y |
Y coordinate on triangle face |
See Also
hexify_cell_to_quad_ij for conversion to Quad IJ,
hexify_cell_to_lonlat for conversion to lon/lat
Other coordinate conversion:
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Get triangle coordinates for a cell
result <- hexify_cell_to_icosa_tri(cell_id = 1000, resolution = 10, aperture = 3)
print(result)
# Convert back to lon/lat using inverse projection
coords <- hexify_inverse(result$icosa_triangle_face,
result$icosa_triangle_x,
result$icosa_triangle_y)
Convert Cell Coordinates to Index String
Description
Converts cell coordinates (face, i, j) to a hierarchical index string.
The index type is selected from aperture when index_type = "auto".
Usage
hexify_cell_to_index(
face,
i,
j,
resolution,
aperture = 3L,
index_type = c("auto", "z3", "z7", "zorder")
)
Arguments
face |
Face/quad numbers (0-19) |
i |
I coordinates |
j |
J coordinates |
resolution |
Resolution level |
aperture |
Aperture (3, 4, or 7) |
index_type |
Index encoding: "auto" (default), "z3", "z7", or "zorder" |
Details
Default index types by aperture:
Aperture 3: Z3 (optimized digit selection)
Aperture 4: Z-order (Morton curve)
Aperture 7: Z7 (one base-7 child digit per resolution)
A Z7 index has the form BBd1...dr, where BB is the two-digit base
cell (00–11), r is the resolution, and every child digit is in 0–6.
It is IGEO7's Z7 index, the string DGGRID writes for the same cell, and
decoding and re-encoding a valid index returns the same string. BB is
the pentagon the cell descends from, which need not be face. Under each
pentagon one direction is missing: a string whose first nonzero digit is 2
(base cells 00–05) or 5 (06–11) names no cell.
Value
A character vector of index strings, one per cell. face, i and
j are read in step and must be the same length.
See Also
Other hierarchical index:
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Examples
idx <- hexify_cell_to_index(5, 10, 15, resolution = 3, aperture = 3)
# Aperture-7 indices contain a two-digit base cell and one digit per level
z7 <- hexify_cell_to_index(5, 1, 1, resolution = 2, aperture = 7)
nchar(z7) == 4L
Convert Cell ID to Longitude/Latitude
Description
Converts cell identifiers back to cell center coordinates.
This is the inverse of hexify_lonlat_to_cell.
Usage
hexify_cell_to_lonlat(cell_id, resolution, aperture)
Arguments
cell_id |
Cell IDs, from 1: integer64, or whole numbers below 2^53 |
resolution |
Grid resolution (integer >= 0) |
aperture |
Grid aperture (3, 4, or 7) |
Value
Data frame with lon_deg and lat_deg columns
See Also
cell_to_lonlat for the recommended S4 interface,
hexify_lonlat_to_cell for the forward operation
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
coords <- hexify_cell_to_lonlat(1702, resolution = 5, aperture = 3)
Convert Cell ID to PLANE Coordinates
Description
Converts DGGRID-compatible cell IDs directly to PLANE coordinates. Returns the cell center in the unfolded icosahedron layout.
Usage
hexify_cell_to_plane(cell_id, resolution, aperture = 3L)
Arguments
cell_id |
Cell IDs, from 1: integer64, or whole numbers below 2^53 |
resolution |
Grid resolution level (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7) |
aperture |
Grid aperture: 3, 4, or 7 |
Details
Compatible with 'dggridR' dgSEQNUM_to_PLANE().
Value
Data frame with columns:
plane_x |
X coordinate in PLANE space (range ~0 to 5.5) |
plane_y |
Y coordinate in PLANE space (range ~0 to 1.73) |
See Also
hexify_icosa_tri_to_plane for triangle conversion,
hexify_lonlat_to_plane for lon/lat conversion
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Get PLANE coordinates for cells
plane <- hexify_cell_to_plane(cell_id = c(100, 200, 300),
resolution = 5, aperture = 3)
plot(plane$plane_x, plane$plane_y)
Convert Cell ID to Quad IJ Coordinates
Description
Converts DGGRID-compatible cell IDs to Quad IJ coordinates. This is the inverse of hexify_quad_ij_to_cell().
Usage
hexify_cell_to_quad_ij(cell_id, resolution, aperture = 3L)
Arguments
cell_id |
Cell IDs, from 1: integer64, or whole numbers below 2^53 |
resolution |
Grid resolution level (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7) |
aperture |
Grid aperture: 3, 4, or 7 |
Details
Compatible with 'dggridR' dgSEQNUM_to_Q2DI().
Value
Data frame with columns:
quad |
Quad number (0-11) |
i |
Integer cell index along first axis |
j |
Integer cell index along second axis |
See Also
hexify_quad_ij_to_cell for the forward operation,
hexify_cell_to_icosa_tri for conversion to triangle coords
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Get Quad IJ coordinates for a cell
result <- hexify_cell_to_quad_ij(cell_id = 1000, resolution = 10, aperture = 3)
print(result)
# Round-trip test
cell_id <- hexify_quad_ij_to_cell(result$quad, result$i, result$j,
resolution = 10, aperture = 3)
# Should equal original cell_id
Convert Cell ID to Quad XY Coordinates
Description
Converts DGGRID-compatible cell IDs to Quad XY coordinates (continuous quad space). This is the cell center in quad coordinates.
Usage
hexify_cell_to_quad_xy(cell_id, resolution, aperture = 3L)
Arguments
cell_id |
Cell IDs, from 1: integer64, or whole numbers below 2^53 |
resolution |
Grid resolution level (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7) |
aperture |
Grid aperture: 3, 4, or 7 |
Details
Compatible with 'dggridR' dgSEQNUM_to_Q2DD().
Value
Data frame with columns:
quad |
Quad number (0-11) |
quad_x |
Continuous X coordinate in quad space |
quad_y |
Continuous Y coordinate in quad space |
See Also
hexify_quad_xy_to_cell for the inverse operation,
hexify_cell_to_quad_ij for integer grid coordinates
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Get Quad XY coordinates for a cell
result <- hexify_cell_to_quad_xy(cell_id = 1000, resolution = 10, aperture = 3)
print(result)
# Round-trip test
cell_id <- hexify_quad_xy_to_cell(result$quad, result$quad_x, result$quad_y,
resolution = 10, aperture = 3)
# Should equal original cell_id
Convert Cell IDs to sf Polygons
Description
Creates polygon geometries for hexagonal grid cells from their cell IDs. Returns an sf object by default, or a data frame for lightweight workflows.
Usage
hexify_cell_to_sf(
cell_id,
resolution = NULL,
aperture = NULL,
return_sf = TRUE,
grid = NULL,
wrap_dateline = TRUE
)
Arguments
cell_id |
Integer vector of cell identifiers |
resolution |
Grid resolution level. Can be omitted if grid is provided. |
aperture |
Grid aperture: 3, 4, 7, or a mixed spelling as
|
return_sf |
Logical. If TRUE (default), returns sf object with polygon geometries. If FALSE, returns data frame with vertex coordinates. |
grid |
Optional HexGridInfo object. If provided, resolution and aperture are extracted from it. |
wrap_dateline |
Logical. If TRUE (default), calls
|
Details
This function uses a native C++ implementation that is significantly faster than 'dggridR' polygon generation, especially for large numbers of cells.
For the recommended S4 interface, use cell_to_sf instead.
Value
If return_sf = TRUE: sf object with columns:
cell_id |
Cell identifier |
geometry |
POLYGON geometry (sfc_POLYGON) |
If return_sf = FALSE: data frame with columns:
cell_id |
Cell identifier |
lon |
Vertex longitude |
lat |
Vertex latitude |
order |
Vertex order along the ring; the last vertex repeats the first, closing the polygon |
See Also
cell_to_sf for the recommended S4 interface
Other sf conversion:
hex_corners_to_sf(),
hexify_grid_global(),
hexify_grid_rect()
Examples
library(hexify)
# Generate some data with hex cells
df <- data.frame(lon = c(0, 5, 10), lat = c(45, 46, 45))
result <- hexify(df, lon = "lon", lat = "lat", area = 1000)
# Get polygons as sf object (using HexData)
polys <- cell_to_sf(grid = result)
# Or with explicit parameters
polys <- hexify_cell_to_sf(result@cell_id, resolution = 10, aperture = 3)
# Plot with sf
library(sf)
plot(st_geometry(polys), col = "lightblue", border = "blue")
Compare Two Indices
Description
Lexicographic comparison of two index strings.
Usage
hexify_compare_indices(idx1, idx2)
Arguments
idx1 |
First index strings |
idx2 |
Second index strings |
Value
Integer vector: -1 where idx1 < idx2, 0 where equal, 1 where idx1 > idx2. The two are read in step, and either may be length one.
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Compare Grid Resolutions
Description
Generates a table comparing different resolution levels for a given grid configuration. Useful for choosing appropriate resolution.
Usage
hexify_compare_resolutions(
aperture = 3,
res_range = 0:15,
type = c("isea", "h3"),
print = FALSE,
radius_km = EARTH_RADIUS_KM
)
Arguments
aperture |
Grid aperture (3, 4, or 7). Ignored for H3 grids. |
res_range |
Range of resolutions to compare (e.g., 1:10) |
type |
Grid type: "isea" (default) or "h3". |
print |
If TRUE, prints a formatted table to console. If FALSE (default), returns a data frame. |
radius_km |
Radius of the body, in kilometers, or a body name such as
"mars" (default Earth). See |
Value
If print=FALSE: data frame with columns resolution, n_cells, cell_area_km2, cell_spacing_km, cls_km. If print=TRUE: invisibly returns the data frame after printing.
See Also
Other grid statistics:
dg_closest_res_to_area(),
dgearthstat(),
hexify_area_to_eff_res(),
hexify_eff_res_to_area(),
hexify_eff_res_to_resolution(),
hexify_resolution_to_eff_res()
Examples
# Get data frame of resolutions 0-10 for aperture 3
comparison <- hexify_compare_resolutions(aperture = 3, res_range = 0:10)
print(comparison)
# Print formatted table directly
hexify_compare_resolutions(aperture = 3, res_range = 0:10, print = TRUE)
# Find resolution with cells ~1000 km^2
subset(comparison, cell_area_km2 > 900 & cell_area_km2 < 1100)
# Resolutions on another body
hexify_compare_resolutions(aperture = 3, res_range = 0:6, radius_km = "mars")
Get Default Index Type for Aperture
Description
Returns the recommended index type:
Aperture 3: "z3"
Aperture 4: "zorder"
Aperture 7: "z7"
Usage
hexify_default_index_type(aperture)
Arguments
aperture |
Aperture (3, 4, or 7) |
Value
String: "z3", "z7", or "zorder"
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_get_children(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Convert Effective Resolution to Area
Description
Calculates approximate cell area for ISEA3H (aperture 3) grids. Based on calibration: eff_res 10 = 863.8006 km^2.
Usage
hexify_eff_res_to_area(eff_res)
Arguments
eff_res |
Effective resolution (0.5 * resolution for aperture 3) |
Value
Area in km^2
See Also
Other grid statistics:
dg_closest_res_to_area(),
dgearthstat(),
hexify_area_to_eff_res(),
hexify_compare_resolutions(),
hexify_eff_res_to_resolution(),
hexify_resolution_to_eff_res()
Convert Effective Resolution to Index Resolution
Description
For aperture 3: res_index = 2 * eff_res - 1 for odd index resolutions.
Usage
hexify_eff_res_to_resolution(eff_res)
Arguments
eff_res |
Effective resolution |
Value
Index resolution (integer)
See Also
Other grid statistics:
dg_closest_res_to_area(),
dgearthstat(),
hexify_area_to_eff_res(),
hexify_compare_resolutions(),
hexify_eff_res_to_area(),
hexify_resolution_to_eff_res()
Get Face Centers of a Solid
Description
Returns the center coordinates of every face of the solid: 20 on the icosahedron, 8 on the octahedron, 4 on the tetrahedron.
Usage
hexify_face_centers(polyhedron = c("icosahedron", "octahedron", "tetrahedron"))
Arguments
polyhedron |
The solid: "icosahedron" (default), "octahedron" or "tetrahedron", in its default orientation |
Value
Data frame with one row per face and columns lon, lat (radians)
See Also
Other projection:
hexify_build_icosa(),
hexify_forward(),
hexify_forward_to_face(),
hexify_inverse(),
hexify_which_face()
Examples
centers <- hexify_face_centers()
plot(centers$lon, centers$lat)
nrow(hexify_face_centers("octahedron"))
Forward Face Projection
Description
Projects geographic coordinates onto a face of the solid, returning face index and planar coordinates (tx, ty).
Usage
hexify_forward(
lon,
lat,
projection = c("isea", "fuller", "ivea", "ak", "akw"),
polyhedron = c("icosahedron", "octahedron", "tetrahedron")
)
Arguments
lon |
Longitude in degrees |
lat |
Latitude in degrees |
projection |
Face projection: |
polyhedron |
The solid: "icosahedron" (default), "octahedron" or "tetrahedron", in its default orientation. Snyder (1992) gives his equal-area projection for each; its angular distortion grows with the faces' size. |
Details
tx and ty are normalized coordinates within the triangular face, typically in range [0, 1].
Value
Named numeric vector: c(face, tx, ty)
See Also
Other projection:
hexify_build_icosa(),
hexify_face_centers(),
hexify_forward_to_face(),
hexify_inverse(),
hexify_which_face()
Examples
result <- hexify_forward(16.37, 48.21)
# result["face"], result["icosa_triangle_x"], result["icosa_triangle_y"]
hexify_forward(16.37, 48.21, polyhedron = "tetrahedron")
Forward Projection to Specific Face
Description
Projects to a known face (skips face detection).
Usage
hexify_forward_to_face(
face,
lon,
lat,
projection = c("isea", "fuller", "ivea", "ak", "akw"),
polyhedron = c("icosahedron", "octahedron", "tetrahedron")
)
Arguments
face |
Face index (0-19 on the icosahedron) |
lon |
Longitude in degrees |
lat |
Latitude in degrees |
projection |
Face projection: |
polyhedron |
The solid: "icosahedron" (default), "octahedron" or "tetrahedron", in its default orientation. Snyder (1992) gives his equal-area projection for each; its angular distortion grows with the faces' size. |
Value
Named numeric vector: c(icosa_triangle_x, icosa_triangle_y)
See Also
Other projection:
hexify_build_icosa(),
hexify_face_centers(),
hexify_forward(),
hexify_inverse(),
hexify_which_face()
Get Children Indices
Description
Returns all children indices (one resolution finer).
Usage
hexify_get_children(
index,
aperture = 3L,
index_type = c("auto", "z3", "z7", "zorder")
)
Arguments
index |
Character vector of index strings |
aperture |
Aperture (3, 4, or 7) |
index_type |
Index encoding. Default "auto". |
Value
A list of character vectors, the child indices of each input index
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Get Parent Index
Description
Returns the parent index (one resolution coarser).
Usage
hexify_get_parent(
index,
aperture = 3L,
index_type = c("auto", "z3", "z7", "zorder")
)
Arguments
index |
Character vector of index strings |
aperture |
Aperture (3, 4, or 7) |
index_type |
Index encoding. Default "auto". |
Value
Character vector of parent index strings
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Get Index Resolution
Description
Returns the resolution level encoded in an index string.
Usage
hexify_get_resolution(
index,
aperture = 3L,
index_type = c("auto", "z3", "z7", "zorder")
)
Arguments
index |
Character vector of index strings |
aperture |
Aperture (3, 4, or 7) |
index_type |
Index encoding. Default "auto". |
Value
Integer vector of resolution levels
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_parent(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Create a Legacy Grid Specification
Description
Builds the list-based grid specification of earlier hexify versions, kept
for code written against them and for 'dggridR' interchange. New code uses
hex_grid, which returns a HexGridInfo-class
object and covers every grid hexify supports. A hexify_grid prints as one
line.
Usage
hexify_grid(
area,
topology = "HEXAGON",
metric = TRUE,
resround = "nearest",
aperture = 3,
projection = "ISEA",
radius_km = EARTH_RADIUS_KM
)
## S3 method for class 'hexify_grid'
format(x, ...)
## S3 method for class 'hexify_grid'
print(x, ...)
Arguments
area |
Target cell area in km^2 (if metric=TRUE) or area code |
topology |
Grid topology (only "HEXAGON" supported) |
metric |
Whether area is in metric units (km^2) |
resround |
How to round resolution ("nearest", "up", "down") |
aperture |
Aperture sequence (3, 4, or 7) |
projection |
Face projection, DGGRID's |
radius_km |
Radius of the body the grid covers, in kilometers, or a body
name such as "mars" (default Earth). See |
x |
A hexify_grid object |
... |
Ignored |
Value
A hexify_grid object containing:
area |
Target cell area |
resolution |
Calculated resolution level |
aperture |
Grid aperture (3, 4, or 7) |
topology |
Grid topology ("HEXAGON") |
projection |
Face projection ("ISEA" or "FULLER") |
radius_km |
Radius of the body, in kilometers |
index_type |
Index encoding type ("z3", "z7", or "zorder") |
See Also
hexify for the main user function,
hexify_grid_to_cell for coordinate conversion
Other hexify main:
hexify()
Examples
# Create a grid with ~1000 km^2 cells
grid <- hexify_grid(area = 1000, aperture = 3)
print(grid)
# Create a finer resolution grid (~100 km^2 cells)
fine_grid <- hexify_grid(area = 100, aperture = 3, resround = "up")
Convert Cell ID to Longitude/Latitude Using a Grid Object
Description
Grid-based wrapper for hexify_cell_to_lonlat. Converts
DGGRID-compatible cell IDs back to cell center coordinates
using the resolution and aperture from a grid object.
Usage
hexify_grid_cell_to_lonlat(grid, cell_id)
Arguments
grid |
Grid specification from hexify_grid() |
cell_id |
Cell IDs, from 1: integer64, or whole numbers below 2^53 |
Value
Data frame with lon_deg and lat_deg columns
See Also
cell_to_lonlat for the recommended S4 interface,
hexify_grid_to_cell for the forward operation
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
grid <- hexify_grid(area = 1000, aperture = 3)
cell_ids <- hexify_grid_to_cell(grid, lon = 5, lat = 45)
coords <- hexify_grid_cell_to_lonlat(grid, cell_ids)
Generate a Global Grid of Hexagon Polygons
Description
Creates hexagon polygons covering a whole body.
Usage
hexify_grid_global(
area,
aperture = 3L,
resround = "nearest",
radius_km = EARTH_RADIUS_KM
)
Arguments
area |
Target cell area in km^2 |
aperture |
Grid aperture: 3, 4, or 7 |
resround |
Resolution rounding: "nearest", "up", or "down" |
radius_km |
Radius of the body, in kilometers, or a body name such as
"mars" (default Earth). See |
Value
sf object with hexagon polygons covering the globe
See Also
grid_global for the recommended S4 interface,
hexify_grid_rect for regional grids
Other sf conversion:
hex_corners_to_sf(),
hexify_cell_to_sf(),
hexify_grid_rect()
Examples
library(hexify)
library(sf)
# Coarse global grid (~100,000 km^2 cells)
global_grid <- hexify_grid_global(area = 100000)
plot(st_geometry(global_grid), border = "gray")
Generate a Rectangular Grid of Hexagon Polygons
Description
Creates hexagon polygons covering a rectangular geographic region.
Usage
hexify_grid_rect(
minlon,
maxlon,
minlat,
maxlat,
area,
aperture = 3L,
resround = "nearest",
radius_km = EARTH_RADIUS_KM
)
Arguments
minlon, maxlon |
Longitude bounds |
minlat, maxlat |
Latitude bounds |
area |
Target cell area in km^2 |
aperture |
Grid aperture: 3, 4, or 7 |
resround |
Resolution rounding: "nearest", "up", or "down" |
radius_km |
Radius of the body, in kilometers, or a body name such as
"mars" (default Earth). See |
Value
sf object with hexagon polygons covering the specified region
See Also
grid_rect for the recommended S4 interface,
hexify_grid_global for global grids
Other sf conversion:
hex_corners_to_sf(),
hexify_cell_to_sf(),
hexify_grid_global()
Examples
library(hexify)
library(sf)
grid <- hexify_grid_rect(
minlon = -10, maxlon = 20,
minlat = 35, maxlat = 60,
area = 5000
)
plot(st_geometry(grid), border = "gray")
Convert Legacy hexify_grid to HexGridInfo
Description
Convert Legacy hexify_grid to HexGridInfo
Usage
hexify_grid_to_HexGridInfo(x)
Arguments
x |
A hexify_grid object (S3) |
Value
A HexGridInfo object (S4)
Convert Longitude/Latitude to Cell ID Using a Grid Object
Description
Grid-based wrapper for hexify_lonlat_to_cell. Converts
geographic coordinates to DGGRID-compatible cell IDs using
the resolution and aperture from a grid object.
Usage
hexify_grid_to_cell(grid, lon, lat)
Arguments
grid |
Grid specification from hexify_grid() |
lon |
Numeric vector of longitudes in degrees |
lat |
Numeric vector of latitudes in degrees |
Value
bit64::integer64 vector of cell IDs, from 1
See Also
lonlat_to_cell for the recommended S4 interface,
hexify_grid_cell_to_lonlat for the inverse operation
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
grid <- hexify_grid(area = 1000, aperture = 3)
cell_ids <- hexify_grid_to_cell(grid, lon = c(0, 10), lat = c(45, 50))
Convert Hierarchical Index Strings to Longitude/Latitude Centers
Description
Converts hierarchical cell index strings back to geographic coordinates, returning the center point of each cell. This is the inverse operation of hexify_lonlat_to_h_index().
Usage
hexify_h_index_to_lonlat(grid, h_index)
Arguments
grid |
Grid specification from hexify_grid() |
h_index |
Hierarchical index strings (character vector) |
Details
Most users should use hexify_cell_to_lonlat or
hexify_grid_cell_to_lonlat which work with DGGRID-compatible
integer cell IDs.
Value
Data frame with columns:
lon |
Longitude in degrees |
lat |
Latitude in degrees |
Create a ggplot2 Visualization of Hexagonal Grid Cells
Description
Creates a ggplot2-based visualization of hexagonal grid cells, optionally colored by a value column. Supports continuous and discrete color scales, projection transformation, and customizable styling.
Usage
hexify_heatmap(
data,
value = NULL,
basemap = NULL,
crs = NULL,
colors = NULL,
breaks = NULL,
labels = NULL,
hex_border = "#5D4E37",
hex_lwd = 0.3,
hex_alpha = 0.7,
basemap_fill = "gray90",
basemap_border = "gray50",
basemap_lwd = 0.5,
mask_outside = FALSE,
aperture = 3L,
shape = c("hexagon", "gosper", "descendants"),
depth = 3L,
xlim = NULL,
ylim = NULL,
title = NULL,
legend_title = NULL,
na_color = "gray90",
theme_void = TRUE
)
Arguments
data |
A HexData object from |
value |
Column name (as string) to use for fill color. If NULL, cells are drawn with a uniform fill color. If not specified but data has a 'count' or 'n' column, that will be used automatically. |
basemap |
Optional basemap. Can be:
|
crs |
Target CRS for the map projection. Can be:
|
colors |
Color palette for the heatmap. Can be:
A name in neither family is an error naming the families. |
breaks |
Numeric vector of break points for binning continuous values,
or NULL for continuous scale. Use |
labels |
Labels for the breaks (length should be one less than breaks). If NULL, labels are auto-generated. |
hex_border |
Border color for hexagons |
hex_lwd |
Line width for hexagon borders |
hex_alpha |
Transparency for hexagon fill (0-1) |
basemap_fill |
Fill color for basemap polygons |
basemap_border |
Border color for basemap polygons |
basemap_lwd |
Line width for basemap borders |
mask_outside |
Logical. If TRUE and basemap is provided, mask hexagon portions that fall outside the basemap polygons. |
aperture |
Grid aperture (default 3), used if data is from hexify() |
shape |
|
depth |
For |
xlim |
Optional x-axis limits (in target CRS units) as c(min, max) |
ylim |
Optional y-axis limits (in target CRS units) as c(min, max) |
title |
Plot title |
legend_title |
Title for the color legend |
na_color |
Color for NA values |
theme_void |
Logical. If TRUE (default), use a minimal theme without axes, gridlines, or background. |
Details
This function provides publication-quality heatmap visualizations of hexagonal grids using ggplot2. It returns a ggplot object that can be further customized with standard ggplot2 functions.
Value
A ggplot2 object that can be further customized or saved.
Color Scales
The function supports three types of color scales:
- Continuous
Set
breaks = NULLfor a continuous gradient- Binned
Provide
breaksvector to bin values into categories- Discrete
If
valuecolumn is a factor, discrete colors are used
Projections
Common projections:
- 4326
'WGS84' (unprojected lat/lon)
- 3035
LAEA Europe
- 3857
Web Mercator
- "+proj=robin"
Robinson (world maps)
- "+proj=moll"
Mollweide (equal-area world maps)
See Also
plot_grid for base R plotting,
cell_to_sf to generate polygons manually
Other visualization:
plot_world()
Examples
library(hexify)
# Sample data with counts
cities <- data.frame(
lon = c(16.37, 2.35, -3.70, 12.5, 4.9),
lat = c(48.21, 48.86, 40.42, 41.9, 52.4),
count = c(100, 250, 75, 180, 300)
)
result <- hexify(cities, lon = "lon", lat = "lat", area_km2 = 5000)
# Simple plot (uniform fill, no value mapping)
hexify_heatmap(result)
library(ggplot2)
# With world basemap
hexify_heatmap(result, basemap = "world")
# Heatmap with value mapping
hexify_heatmap(result, value = "count")
# With world basemap and custom colors
hexify_heatmap(result, value = "count",
basemap = "world",
colors = "YlOrRd",
title = "City Density")
# Binned values with custom breaks
hexify_heatmap(result, value = "count",
basemap = "world",
breaks = c(-Inf, 100, 200, Inf),
labels = c("Low", "Medium", "High"),
colors = c("#fee8c8", "#fdbb84", "#e34a33"))
# Different projection (LAEA Europe)
hexify_heatmap(result, value = "count",
basemap = "world",
crs = 3035,
xlim = c(2500000, 6500000),
ylim = c(1500000, 5500000))
# Customize further with ggplot2
hexify_heatmap(result, value = "count", basemap = "world") +
labs(caption = "Data source: Example") +
theme(legend.position = "bottom")
Convert Icosa Triangle Coordinates to PLANE Coordinates
Description
Transforms icosahedral triangle coordinates to the 2D PLANE representation (unfolded icosahedron). Each triangle is rotated and translated to its position in the unfolded layout.
Usage
hexify_icosa_tri_to_plane(
icosa_triangle_face,
icosa_triangle_x,
icosa_triangle_y,
polyhedron = c("icosahedron", "octahedron", "tetrahedron")
)
Arguments
icosa_triangle_face |
Triangle face number (0-19 on the icosahedron), integer or vector |
icosa_triangle_x |
X coordinate on triangle face |
icosa_triangle_y |
Y coordinate on triangle face |
polyhedron |
The solid whose faces are unfolded: "icosahedron" (default), "octahedron" or "tetrahedron" |
Details
Equivalent to 'dggridR' dgPROJTRI_to_PLANE().
The PLANE layout of the icosahedron arranges all 20 faces into a roughly rectangular region. Faces 0-4 and 5-9 form the upper row, while faces 10-14 and 15-19 form the lower row. Adjacent faces share edges in this representation. The octahedron lays its four diamonds side by side, each a northern face over its southern one; the tetrahedron lays face 3 in the middle of a triangle of edge 2 with the three faces around vertex 0 at its corners.
Value
Data frame with columns:
plane_x |
X coordinate in PLANE space (range ~0 to 5.5 on the icosahedron) |
plane_y |
Y coordinate in PLANE space (range ~0 to 1.73) |
See Also
hexify_cell_to_plane for direct cell ID conversion,
hexify_lonlat_to_plane for lon/lat to PLANE
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Get PLANE coordinates from triangle coordinates
fwd <- hexify_forward(lon = 2.35, lat = 48.86)
plane <- hexify_icosa_tri_to_plane(
icosa_triangle_face = fwd["face"],
icosa_triangle_x = fwd["icosa_triangle_x"],
icosa_triangle_y = fwd["icosa_triangle_y"]
)
print(plane)
Convert Icosa Triangle to Quad IJ Coordinates
Description
Converts icosahedral triangle coordinates directly to Quad IJ, combining the transformation and quantization steps.
Usage
hexify_icosa_tri_to_quad_ij(
icosa_triangle_face,
icosa_triangle_x,
icosa_triangle_y,
resolution,
aperture = 3L
)
Arguments
icosa_triangle_face |
Triangle face number (0-19) |
icosa_triangle_x |
X coordinate on triangle face |
icosa_triangle_y |
Y coordinate on triangle face |
resolution |
Grid resolution level |
aperture |
Grid aperture: 3, 4, or 7 |
Value
List with components:
quad |
Quad number (0-11) |
i |
Integer cell index along first axis |
j |
Integer cell index along second axis |
See Also
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# First get triangle coordinates from lon/lat
fwd <- hexify_forward(lon = 2.35, lat = 48.86)
# Then convert to quad IJ
quad_ij <- hexify_icosa_tri_to_quad_ij(
icosa_triangle_face = fwd["face"],
icosa_triangle_x = fwd["icosa_triangle_x"],
icosa_triangle_y = fwd["icosa_triangle_y"],
resolution = 10,
aperture = 3
)
print(quad_ij)
Convert Icosa Triangle to Quad XY Coordinates
Description
Converts icosahedral triangle coordinates (from Snyder projection) to quad XY coordinates. This is an intermediate step in the pipeline.
Usage
hexify_icosa_tri_to_quad_xy(
icosa_triangle_face,
icosa_triangle_x,
icosa_triangle_y
)
Arguments
icosa_triangle_face |
Triangle face number (0-19) |
icosa_triangle_x |
X coordinate on triangle face |
icosa_triangle_y |
Y coordinate on triangle face |
Value
List with components:
quad |
Quad number (0-11) |
quad_x |
Continuous X coordinate in quad space |
quad_y |
Continuous Y coordinate in quad space |
See Also
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# First get triangle coordinates from lon/lat
fwd <- hexify_forward(lon = 2.35, lat = 48.86)
# Then convert to quad XY
quad_xy <- hexify_icosa_tri_to_quad_xy(
icosa_triangle_face = fwd["face"],
icosa_triangle_x = fwd["icosa_triangle_x"],
icosa_triangle_y = fwd["icosa_triangle_y"]
)
print(quad_xy)
Convert Index String to Cell Coordinates
Description
Decodes a hierarchical index string back to its cell coordinates and
resolution. For Z7, valid indices round-trip exactly through
hexify_cell_to_index().
Usage
hexify_index_to_cell(
index,
aperture = 3L,
index_type = c("auto", "z3", "z7", "zorder")
)
Arguments
index |
Character vector of index strings |
aperture |
Aperture (3, 4, or 7) |
index_type |
Index encoding used. Default "auto" infers from aperture. |
Value
A data frame with columns face, i, j and resolution, one row
per index.
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Examples
cell <- hexify_index_to_cell("0012012", aperture = 3)
z7_cell <- hexify_index_to_cell("110001", aperture = 7)
hexify_cell_to_index(z7_cell$face, z7_cell$i, z7_cell$j,
z7_cell$resolution, aperture = 7
)
Convert Index String to Longitude/Latitude
Description
Returns the geographic coordinates of an indexed cell's center. This is a
cell-level inverse of hexify_lonlat_to_index(): the returned point is the
center, not necessarily the original input point.
Usage
hexify_index_to_lonlat(
index,
aperture = 3L,
index_type = c("auto", "z3", "z7", "zorder")
)
Arguments
index |
Character vector of index strings |
aperture |
Aperture (3, 4, or 7) |
index_type |
Index encoding. Default "auto" infers from aperture. |
Value
A data frame with lon and lat columns in degrees, one row per
index.
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Examples
coords <- hexify_index_to_lonlat("0012012", aperture = 3)
Inverse Face Projection
Description
Converts face plane coordinates back to geographic coordinates.
Usage
hexify_inverse(
x,
y,
face,
projection = c("isea", "fuller", "ivea", "ak", "akw"),
polyhedron = c("icosahedron", "octahedron", "tetrahedron")
)
Arguments
x |
X coordinate on face plane |
y |
Y coordinate on face plane |
face |
Face index (0-19 on the icosahedron) |
projection |
Face projection: |
polyhedron |
The solid: "icosahedron" (default), "octahedron" or "tetrahedron", in its default orientation. Snyder (1992) gives his equal-area projection for each; its angular distortion grows with the faces' size. |
Value
Named numeric vector: c(lon_deg, lat_deg)
See Also
Other projection:
hexify_build_icosa(),
hexify_face_centers(),
hexify_forward(),
hexify_forward_to_face(),
hexify_which_face()
Examples
coords <- hexify_inverse(0.5, 0.3, face = 2)
Check If Index Type Is Valid for Aperture
Description
Check If Index Type Is Valid for Aperture
Usage
hexify_is_valid_index_type(
aperture,
index_type = c("auto", "z3", "z7", "zorder")
)
Arguments
aperture |
Aperture (3, 4, or 7) |
index_type |
Index type to check |
Value
Logical: TRUE if valid combination
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_lonlat_to_index(),
hexify_z7_canonical()
Convert Longitude/Latitude to Cell ID
Description
Converts geographic coordinates to DGGRID-compatible cell identifiers. This is the primary function for geocoding points to grid cells.
Usage
hexify_lonlat_to_cell(lon, lat, resolution, aperture)
Arguments
lon |
Numeric vector of longitudes in degrees |
lat |
Numeric vector of latitudes in degrees |
resolution |
Grid resolution (integer >= 0) |
aperture |
Grid aperture (3, 4, or 7) |
Details
Returns DGGRID-compatible cell identifiers. The cell ID uniquely identifies each hexagonal cell in the global grid.
For a grid-object interface, use lonlat_to_cell.
Value
bit64::integer64 vector of cell IDs, from 1
See Also
lonlat_to_cell for the recommended S4 interface,
hexify_cell_to_lonlat for the inverse operation
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
cell_id <- hexify_lonlat_to_cell(0, 45, resolution = 5, aperture = 3)
Convert Longitude/Latitude to Hexagonal Cell Hierarchical Index
Description
Converts geographic coordinates (longitude, latitude) to hexagonal cell hierarchical index strings. These strings encode the face, resolution, and cell location in a Z-order (Morton code) format.
Usage
hexify_lonlat_to_h_index(grid, lon, lat)
Arguments
grid |
Grid specification from hexify_grid() |
lon |
Longitude vector in degrees (numeric, -180 to 180) |
lat |
Latitude vector in degrees (numeric, -90 to 90) |
Details
Most users should use hexify_lonlat_to_cell or
hexify_grid_to_cell which return DGGRID-compatible
integer cell IDs.
This function returns hierarchical index strings useful for:
Understanding the cell's position in the hierarchy
Prefix-based spatial queries
Parent/child cell relationships
Value
Data frame with columns:
h_index |
Hierarchical index (character string) |
face |
Icosahedron face number (integer, 0-19) |
Convert Longitude/Latitude to Index String
Description
Projects geographic coordinates to grid cells and returns their hierarchical
index strings. Inputs are vectorized over lon and lat.
Usage
hexify_lonlat_to_index(
lon,
lat,
resolution,
aperture = 3L,
index_type = c("auto", "z3", "z7", "zorder")
)
Arguments
lon |
Longitudes in degrees |
lat |
Latitudes in degrees |
resolution |
Resolution level |
aperture |
Aperture (3, 4, or 7) |
index_type |
Index encoding: "auto" (default), "z3", "z7", or "zorder" |
Value
A character vector of index strings, one per point. lon and lat
must be the same length.
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_z7_canonical()
Examples
idx <- hexify_lonlat_to_index(16.37, 48.21, resolution = 5, aperture = 3)
idx7 <- hexify_lonlat_to_index(16.37, 48.21,
resolution = 4, aperture = 7
)
Convert Longitude/Latitude to PLANE Coordinates
Description
Converts geographic coordinates directly to PLANE coordinates (the unfolded solid). Combines forward 'Snyder' projection with the PLANE transformation.
Usage
hexify_lonlat_to_plane(
lon,
lat,
polyhedron = c("icosahedron", "octahedron", "tetrahedron")
)
Arguments
lon |
Longitude in degrees (-180 to 180) |
lat |
Latitude in degrees (-90 to 90) |
polyhedron |
The solid whose faces are unfolded: "icosahedron" (default), "octahedron" or "tetrahedron", in its standard orientation |
Details
Equivalent to 'dggridR' dgGEO_to_PLANE() on the icosahedron.
Value
Data frame with columns:
plane_x |
X coordinate in PLANE space (range ~0 to 5.5) |
plane_y |
Y coordinate in PLANE space (range ~0 to 1.73) |
See Also
hexify_cell_to_plane for cell ID conversion,
hexify_icosa_tri_to_plane for triangle conversion
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Plot world cities in PLANE coordinates
cities <- data.frame(
lon = c(2.35, -74.00, 139.69, 151.21),
lat = c(48.86, 40.71, 35.69, -33.87)
)
plane <- hexify_lonlat_to_plane(cities$lon, cities$lat)
plot(plane$plane_x, plane$plane_y)
Convert Longitude/Latitude to Quad IJ Coordinates
Description
Converts geographic coordinates to the intermediate Quad IJ representation used internally by ISEA DGGS. Returns the quad number (0-11) and integer cell indices (i, j) within that quad.
Usage
hexify_lonlat_to_quad_ij(lon, lat, resolution, aperture = 3L)
Arguments
lon |
Longitude in degrees (-180 to 180) |
lat |
Latitude in degrees (-90 to 90) |
resolution |
Grid resolution level (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7) |
aperture |
Grid aperture: 3, 4, or 7 |
Details
The 20 icosahedral triangle faces are grouped into 12 quads:
Quad 0: North polar region
Quads 1-5: Upper hemisphere rhombi
Quads 6-10: Lower hemisphere rhombi
Quad 11: South polar region
Value
List with components:
quad |
Quad number (0-11) |
i |
Integer cell index along first axis |
j |
Integer cell index along second axis |
icosa_triangle_face |
Source icosahedral face (0-19) |
icosa_triangle_x |
X coordinate on triangle face |
icosa_triangle_y |
Y coordinate on triangle face |
See Also
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Get Quad IJ coordinates for Paris
result <- hexify_lonlat_to_quad_ij(lon = 2.35, lat = 48.86,
resolution = 10, aperture = 3)
print(result)
Convert Quad IJ Coordinates to Cell ID
Description
Converts Quad IJ coordinates to a global cell identifier. This is the final step in the coordinate pipeline.
Usage
hexify_quad_ij_to_cell(quad, i, j, resolution, aperture = 3L)
Arguments
quad |
Quad number (0-11), integer or vector |
i |
Cell index along first axis, integer or vector |
j |
Cell index along second axis, integer or vector |
resolution |
Grid resolution level (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7) |
aperture |
Grid aperture: 3, 4, or 7 |
Value
bit64::integer64 vector of cell IDs
See Also
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Convert Quad IJ to cell ID
cell_id <- hexify_quad_ij_to_cell(quad = 1, i = 100, j = 50,
resolution = 10, aperture = 3)
print(cell_id)
Convert Quad IJ to Icosa Triangle Coordinates
Description
Converts Quad IJ coordinates to icosahedral triangle coordinates. This is useful for understanding where a cell is located on the icosahedral projection.
Usage
hexify_quad_ij_to_icosa_tri(quad, i, j, resolution, aperture = 3L)
Arguments
quad |
Quad number (0-11), integer or vector |
i |
Cell index along first axis, integer or vector |
j |
Cell index along second axis, integer or vector |
resolution |
Grid resolution level (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7) |
aperture |
Grid aperture: 3, 4, or 7 |
Details
Equivalent to 'dggridR' dgQ2DI_to_PROJTRI().
Value
Data frame with columns:
icosa_triangle_face |
Triangle face number (0-19) |
icosa_triangle_x |
X coordinate on triangle face |
icosa_triangle_y |
Y coordinate on triangle face |
See Also
hexify_icosa_tri_to_quad_ij for the inverse,
hexify_cell_to_icosa_tri for conversion from cell ID
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Get triangle coordinates for a Quad IJ position
result <- hexify_quad_ij_to_icosa_tri(quad = 1, i = 100, j = 50,
resolution = 10, aperture = 3)
print(result)
Convert Quad IJ to Quad XY (Continuous Coordinates)
Description
Converts discrete cell indices to continuous quad coordinates. Useful for computing cell centers or understanding the cell geometry.
Usage
hexify_quad_ij_to_xy(quad, i, j, resolution, aperture = 3L)
Arguments
quad |
Quad number (0-11) |
i |
Cell index along first axis |
j |
Cell index along second axis |
resolution |
Grid resolution level |
aperture |
Grid aperture: 3, 4, or 7 |
Value
List with components:
quad_x |
Continuous X coordinate in quad space |
quad_y |
Continuous Y coordinate in quad space |
See Also
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Get continuous quad coordinates for a cell
xy <- hexify_quad_ij_to_xy(quad = 1, i = 100, j = 50,
resolution = 10, aperture = 3)
print(xy)
Convert Quad XY Coordinates to Cell ID
Description
Converts Quad XY coordinates (continuous quad space) to DGGRID-compatible cell IDs. The coordinates are quantized to the nearest cell.
Usage
hexify_quad_xy_to_cell(quad, quad_x, quad_y, resolution, aperture = 3L)
Arguments
quad |
Quad number (0-11), integer or vector |
quad_x |
Continuous X coordinate in quad space |
quad_y |
Continuous Y coordinate in quad space |
resolution |
Grid resolution level (0-30 for aperture 3, 0-29 for aperture 4, 0-21 for aperture 7) |
aperture |
Grid aperture: 3, 4, or 7 |
Details
Compatible with 'dggridR' dgQ2DD_to_SEQNUM().
Value
bit64::integer64 vector of cell IDs
See Also
hexify_cell_to_quad_xy for the inverse operation,
hexify_quad_ij_to_cell for integer grid coordinates
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_icosa_tri(),
hexify_roundtrip_test()
Examples
# Convert Quad XY to cell ID
cell_id <- hexify_quad_xy_to_cell(quad = 1, quad_x = 0.5, quad_y = 0.3,
resolution = 10, aperture = 3)
print(cell_id)
Convert Quad XY to Icosa Triangle Coordinates
Description
Inverse transformation from quad coordinates back to icosahedral triangle coordinates. Useful for projecting cell centers back to lon/lat.
Usage
hexify_quad_xy_to_icosa_tri(quad, quad_x, quad_y)
Arguments
quad |
Quad number (0-11) |
quad_x |
Continuous X coordinate in quad space |
quad_y |
Continuous Y coordinate in quad space |
Value
List with components:
icosa_triangle_face |
Triangle face number (0-19) |
icosa_triangle_x |
X coordinate on triangle face |
icosa_triangle_y |
Y coordinate on triangle face |
See Also
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_roundtrip_test()
Examples
# Convert quad XY back to triangle coordinates
tri <- hexify_quad_xy_to_icosa_tri(quad = 1, quad_x = 0.5, quad_y = 0.3)
print(tri)
Convert Index Resolution to Effective Resolution
Description
Convert Index Resolution to Effective Resolution
Usage
hexify_resolution_to_eff_res(resolution)
Arguments
resolution |
Index resolution |
Value
Effective resolution
See Also
Other grid statistics:
dg_closest_res_to_area(),
dgearthstat(),
hexify_area_to_eff_res(),
hexify_compare_resolutions(),
hexify_eff_res_to_area(),
hexify_eff_res_to_resolution()
Round-Trip Accuracy Test
Description
Tests the accuracy of the coordinate conversion functions by converting coordinates to cells and back, measuring the distance between original and reconstructed coordinates.
Usage
hexify_roundtrip_test(grid, lon, lat, units = "km")
Arguments
grid |
Grid specification |
lon |
Longitude to test |
lat |
Latitude to test |
units |
Distance units ("km" or "degrees") |
Value
List with:
original |
Original coordinates |
cell |
Cell index |
reconstructed |
Reconstructed coordinates |
error |
Distance between original and reconstructed |
See Also
Other coordinate conversion:
hexify_cell_to_icosa_tri(),
hexify_cell_to_lonlat(),
hexify_cell_to_plane(),
hexify_cell_to_quad_ij(),
hexify_cell_to_quad_xy(),
hexify_grid_cell_to_lonlat(),
hexify_grid_to_cell(),
hexify_icosa_tri_to_plane(),
hexify_icosa_tri_to_quad_ij(),
hexify_icosa_tri_to_quad_xy(),
hexify_lonlat_to_cell(),
hexify_lonlat_to_plane(),
hexify_lonlat_to_quad_ij(),
hexify_quad_ij_to_cell(),
hexify_quad_ij_to_icosa_tri(),
hexify_quad_ij_to_xy(),
hexify_quad_xy_to_cell(),
hexify_quad_xy_to_icosa_tri()
Determine Which Face Contains a Point
Description
Returns the index of the face of the solid containing the given coordinates (0-19 on the icosahedron).
Usage
hexify_which_face(
lon,
lat,
polyhedron = c("icosahedron", "octahedron", "tetrahedron")
)
Arguments
lon |
Longitude in degrees |
lat |
Latitude in degrees |
polyhedron |
The solid: "icosahedron" (default), "octahedron" or "tetrahedron", in its default orientation |
Value
Integer face index
See Also
Other projection:
hexify_build_icosa(),
hexify_face_centers(),
hexify_forward(),
hexify_forward_to_face(),
hexify_inverse()
Examples
face <- hexify_which_face(16.37, 48.21)
hexify_which_face(16.37, 48.21, polyhedron = "tetrahedron")
Simplified World Map
Description
A lightweight sf object containing simplified world country borders, suitable for use as a basemap when visualizing hexagonal grids.
Usage
hexify_world
Format
An sf object with 177 features and 15 fields:
- name
Country short name
- name_long
Country full name
- admin
Administrative name
- sovereignt
Sovereignty
- iso_a2
ISO 3166-1 alpha-2 country code
- iso_a3
ISO 3166-1 alpha-3 country code
- iso_n3
ISO 3166-1 numeric code
- continent
Continent name
- region_un
UN region
- subregion
UN subregion
- region_wb
World Bank region
- pop_est
Population estimate
- gdp_md
GDP in millions USD
- income_grp
Income group classification
- economy
Economy type
- geometry
MULTIPOLYGON geometry in 'WGS84' (EPSG:4326)
Source
Simplified from Natural Earth 1:110m Cultural Vectors (https://www.naturalearthdata.com/)
Examples
library(sf)
# Plot the built-in world map
plot(st_geometry(hexify_world), col = "lightgray", border = "white")
# Filter by continent
europe <- hexify_world[hexify_world$continent == "Europe", ]
plot(st_geometry(europe))
Get Canonical Form of Z7 Index
Description
Decodes and re-encodes a Z7 index until it reaches a stable form. Every valid index is already canonical and comes back unchanged. A string whose first nonzero digit is the direction its pentagon base cell lacks names no cell; it decodes, as in DGGRID, to the lattice point its digits reach, and this function returns the index of the cell there.
Usage
hexify_z7_canonical(index, max_iterations = 128L)
Arguments
index |
Character vector of Z7 index strings. |
max_iterations |
Maximum number of decode/encode iterations; the default is 128. |
Value
A character vector of stable indices.
See Also
Other hierarchical index:
hexify_cell_to_index(),
hexify_compare_indices(),
hexify_default_index_type(),
hexify_get_children(),
hexify_get_parent(),
hexify_get_resolution(),
hexify_index_to_cell(),
hexify_index_to_lonlat(),
hexify_is_valid_index_type(),
hexify_lonlat_to_index()
Examples
# Valid Z7 indices are stable
hexify_z7_canonical("110001")
cell <- hexify_index_to_cell("110001", aperture = 7)
identical(
hexify_cell_to_index(cell$face, cell$i, cell$j,
cell$resolution, aperture = 7
),
"110001"
)
Import External H3 Cell IDs into hexify
Description
Ingests H3 cell IDs from an external source (another H3 library, a database, or a CSV file) into hexify. Validates cell IDs, infers the H3 resolution, and optionally attaches data to build a HexData object.
Usage
import_h3(cell_ids, data = NULL, validate = TRUE, radius_km = EARTH_RADIUS_KM)
Arguments
cell_ids |
Character vector of H3 cell ID strings |
data |
Optional data frame to attach. Must have the same number of rows
as |
validate |
If |
radius_km |
Radius of the body the cells cover, in kilometers, or a body
name (default Earth). See |
Details
For converting between grid specs, use
hex_grid(type = "h3") directly. For cell-level ISEA/H3
mapping, use h3_crosswalk.
H3 cell IDs encode their resolution in the index itself, so no resolution argument is needed. The resolution is inferred automatically. All cell IDs must share the same resolution; mixed resolutions produce an error.
Value
If data = NULL, a HexGridInfo object for the inferred H3
resolution. If data is provided, a HexData object with data
attached at the specified cells.
See Also
hex_grid for creating grids directly,
h3_crosswalk for cell-level ISEA/H3 mapping
Examples
# Import external H3 cell IDs (grid spec only)
h3_ids <- c("8528342bfffffff", "85283473fffffff", "85283447fffffff")
grid <- import_h3(h3_ids)
grid
# Import with data attached
df <- data.frame(species = c("oak", "pine", "birch"), count = c(10, 5, 3))
hd <- import_h3(h3_ids, data = df)
hd
Convert Hierarchical Index to Cell ID
Description
The inverse of cell_to_index(): the cells of grid that index strings,
IGEO7 integer forms or OGC zone identifiers name.
Usage
index_to_cell(
index,
grid,
form = c("string", "int", "hex", "monotonic", "textZIRS", "uint64ZIRS")
)
Arguments
index |
Identifiers in the form |
grid |
A HexGridInfo or HexData object |
form |
The form of |
Details
A packed or hexadecimal IGEO7 index carries its resolution in its
trailing 7 digits, and an OGC identifier in its level; a monotonic ID is
read at the grid's resolution. See cell_to_index() for the forms.
Value
Cell IDs of grid: integer64 for ISEA grids, character for H3
grids. Every index must name a cell of the grid's resolution; an OGC
identifier that names no zone of the grid reads as NA.
See Also
Examples
g <- hex_grid(resolution = 4, aperture = 7)
index_to_cell("033000", g)
index_to_cell("3600ffffffffffff", g, form = "hex")
index_to_cell(bit64::as.integer64("8232"), g, form = "monotonic")
ogc <- hex_grid(resolution = 8, aperture = 3, ellipsoid = "WGS84",
orientation = "ogc")
cell_to_lonlat(index_to_cell("E6-317-A", ogc, form = "textZIRS"), ogc)
Check If an Object Is a HexData
Description
Check If an Object Is a HexData
Usage
is_hex_data(x)
Arguments
x |
Object to check |
Value
Logical
Examples
df <- data.frame(lon = c(0, 10), lat = c(45, 50))
is_hex_data(hexify(df, lon = "lon", lat = "lat", area_km2 = 1000))
is_hex_data(df)
Check If an Object Is a HexGridInfo
Description
Check If an Object Is a HexGridInfo
Usage
is_hex_grid(x)
Arguments
x |
Object to check |
Value
Logical
Examples
is_hex_grid(hex_grid(resolution = 3))
is_hex_grid(list(resolution = 3))
Detect Pentagon Cells
Description
Identifies which cells are pentagons. A hexagonal grid on the icosahedron has exactly 12 pentagons, one at each icosahedron vertex, with 5 neighbors instead of 6. Grids on the octahedron and the tetrahedron have none: their vertex cells are six squares and four triangles.
Usage
is_pentagon(cell_id, grid)
Arguments
cell_id |
Cell IDs to check. integer64 for ISEA, character for H3. |
grid |
A HexGridInfo or HexData object specifying the grid. |
Details
H3 backend: Uses the vendored H3 isPentagon function.
ISEA backend: A vertex cell sits at a vertex of the solid, which is the (i, j) = (0, 0) cell of its quad, and has one side per face meeting there. Each input cell ID is decoded to its own (quad, i, j) and tested, rather than by re-deriving each vertex's cell ID (the forward direction has aperture-specific quirks – e.g. aperture 7's substrate/surrogate coordinate distinction – that make a single fixed formula for "the (0,0) cell ID of quad Q" unreliable across apertures).
Value
A logical vector. TRUE for pentagon cells, FALSE for hexagons.
See Also
get_neighbors() for neighbor finding (pentagons have 5 neighbors)
Examples
# H3 pentagon detection
g <- hex_grid(resolution = 1, type = "h3")
cells <- grid_global(g)
pent <- is_pentagon(cells$cell_id, g)
sum(pent) # Should be 12
Convert Longitude/Latitude to Cell ID
Description
Converts geographic coordinates to DGGS cell IDs using a grid specification.
Usage
lonlat_to_cell(lon, lat, grid)
Arguments
lon |
Numeric vector of longitudes in degrees |
lat |
Numeric vector of latitudes in degrees |
grid |
A HexGridInfo or HexData object, or legacy hexify_grid |
Details
ISEA cell IDs number a grid's cells from 1 and pass 2^53, the largest whole number a double holds exactly, at fine resolutions, so they are returned as 64-bit integers. Functions taking cell IDs also accept whole numbers below 2^53 and character strings of digits.
This function accepts either a HexGridInfo object from hex_grid() or
a HexData object from hexify(). If a HexData object is provided,
its grid specification is extracted automatically.
Value
Cell IDs: a bit64::integer64 vector for an ISEA grid, a
character vector of H3 indices for an H3 grid
See Also
cell_to_lonlat for the inverse operation,
hex_grid for creating grid specifications
Examples
grid <- hex_grid(area_km2 = 1000)
cells <- lonlat_to_cell(lon = c(0, 10), lat = c(45, 50), grid = grid)
# Or use HexData object
df <- data.frame(lon = c(0, 10, 20), lat = c(45, 50, 55))
result <- hexify(df, lon = "lon", lat = "lat", area_km2 = 1000)
cells <- lonlat_to_cell(lon = 5, lat = 48, grid = result)
Get Number of Cells
Description
Counts cells: those a dataset occupies, or those a grid contains.
Usage
n_cells(x)
Arguments
x |
A HexData or HexGridInfo object |
Value
For a HexData, the number of distinct cells its rows fall in. For a HexGridInfo, the number of cells the grid divides the body into, which runs past integer range at fine resolutions and so comes back as a double.
Examples
grid <- hex_grid(area_km2 = 100000)
n_cells(grid)
df <- data.frame(lon = c(0, 10, 20), lat = c(45, 50, 55))
n_cells(hexify(df, lon = "lon", lat = "lat", grid = grid))
The Parts of Cells on a Net Layout
Description
Cuts each cell into its parts on the pieces of a net layout and places them in the plane. A cell on one piece has one part. A cell that crosses from one piece to another stays whole on the map where the two pieces are joined, and is split where a seam of the net runs through it: its parts then lie apart, and Carr et al. (1997) call it a cloned cell. A cell on a piece the layout shows twice also has a part on each copy.
Usage
net_cells(layout, grid, cells = NULL)
Arguments
layout |
A |
grid |
The HexGridInfo object the layout was built for. |
cells |
Cell IDs; |
Details
Cell walls are straight on the faces of the solid and the layout moves
pieces rigidly (or, for "rhombic", by one shear that keeps areas
to one constant), so a part's map area is exact. Snyder's projection is
equal-area, so on a grid built on it the map areas of a cell's parts add
up to the cell's share of the sphere: a face of the net has area
\sqrt{3}/4, and 4\pi/n of the unit sphere for a solid of
n faces.
Value
A data frame with one row per part: cell_id, piece
(position in layout$pieces), group (parts of a cell that
the map joins share a group, numbered from 1 within the cell),
area (map area in units of a face edge squared) and the centroid
x, y. A cell whose parts fall into more than one group is
cut by a seam.
References
Carr, D. B., Kahn, R., Sahr, K., Olsen, A. R. (1997). ISEA discrete global grids. Statistical Computing & Graphics Newsletter 8(2/3): 31-39.
See Also
Examples
g <- hex_grid(resolution = 3, aperture = 3)
net <- net_layout(g, "plane")
parts <- net_cells(net, g)
cut <- tapply(parts$group, parts$cell_id, max) > 1
sum(cut)
# On Snyder's equal-area projection every hexagon has the same map area,
# however the net cuts it
area <- tapply(parts$area, parts$cell_id, sum)
hexagon <- !is_pentagon(as.numeric(names(area)), g)
range(area[hexagon])
Lay Out the Faces of a Grid's Solid in the Plane
Description
Builds a flat map of the sphere from the faces of the solid an ISEA grid is
built on: the face projection of the grid (Snyder's equal-area projection,
or Fuller's) maps the sphere onto the faces, and the layout cuts the faces
into pieces and places each piece in the plane by a rotation and a
translation (the rhombic layout also shears). Draw a grid on it with
plot(grid, surface = "net",
layout = ), and place points on it with net_project.
Usage
net_layout(
x,
layout = c("plane", "gosper", "gosper_flower", "gosper_land", "rhombic", "land"),
centre = NULL,
mirror = FALSE,
land = TRUE
)
Arguments
x |
A HexGridInfo object from |
layout |
Name of the layout; see Details. |
centre |
For the Gosper layouts, the point |
mirror |
For the Gosper layouts, |
land |
For |
Details
The layouts are:
"plane"The faces in the PLANE layout of DGGRID, the layout
hexify_cell_to_planereads: five strips of four triangles on the icosahedron, four diamonds side by side on the octahedron, one triangle of edge 2 on the tetrahedron."gosper"Van de Sande's Gosper World on the octahedron: four regular hexagons, each one face of the octahedron and a third of each of its three neighbours, the three neighbouring faces cut along the lines from their centres to their corners. The tile holding
centrelies in the middle and the other three are attached on alternate sides."gosper_flower"The tile holding
centresurrounded by the six tiles that border it, so each of the other three tiles appears twice (Van de Sande 2024, Fig. 5). The map is continuous across the sides of the middle tile; the three seams run out from its corners that are vertices of the octahedron."gosper_land"The four Gosper tiles joined along the three hexagon sides, out of the twelve, that cross the most land of
land, so the continents stay whole where they can, as in Van de Sande's Fig. 1 (2024)."rhombic"DGGAL's 5 x 6 rhombic space on the icosahedron (Jacovella-St-Louis et al. 2025): each face sheared onto half of a unit square, the ten diamonds a staircase of squares. Areas keep one constant. DGGAL's y axis points down the page, so a point at DGGAL's (x, y) is placed at (x, -y).
"land"A net cut along the solid's edges that cross the least land of
land, so the faces stay joined across land where they can, in the spirit of Fuller's Dymaxion map, which also splits two faces. Withhex_grid(orientation = "dymaxion", projection = "fuller")it is a Dymaxion-style map of whole faces.
On the octahedron with Snyder's projection the Gosper World is equal-area,
where Van de Sande built it from a gnomonic projection onto a rhombic
dodecahedron. His poles lie at midpoints of octahedron edges, which is
hex_grid(polyhedron = "octahedron", orientation = "gosper"); Rus's
four-hexagon map puts them at octahedron vertices, which is the standard
orientation of the octahedron.
Value
A hexify_net object: a list with the layout's name,
the grid's solid in polyhedron, the icosa argument of the
grid, and pieces, one list per placed piece with its face
(from 0), its region (three corners in the face's triangle
coordinates), their labels, the affine map A and b
placing a point t at A t + b, and
the tile it belongs to.
References
Van de Sande, A. (2024). Gosper World: A Hexagonal Map Using Gosper Fractals. Bridges 2024 Conference Proceedings, 507-510.
Rus, J. (2017). Flowsnake Earth. Bridges 2017 Conference Proceedings, 237-244.
Jacovella-St-Louis, J., Padilla Ruiz, M., Moreira de Sousa, L., Peterson, P., Stefanakis, E. (2025). Interoperable global and local indexing of discrete global grid systems based on the ISEA projection for efficient storage, processing and transmission. Abstracts of the International Cartographic Association 10, 126. doi:10.5194/ica-abs-10-126-2025
See Also
net_project to place points on a layout
Examples
grid <- hex_grid(resolution = 3, aperture = 4, polyhedron = "octahedron",
orientation = "gosper")
world <- net_layout(grid, "gosper")
plot(grid, surface = "net", layout = world, seams = TRUE)
plot(grid, surface = "net", layout = "gosper_flower", land = TRUE)
Place Points on a Net Layout
Description
Projects longitude/latitude points onto their face of the grid's solid and places them where the layout puts that part of the face. A point on a piece the layout shows more than once, or on a cut between two pieces, has one row per place.
Usage
net_project(layout, lon, lat)
Arguments
layout |
A |
lon, lat |
Longitudes and latitudes in degrees |
Value
A data frame with columns point (position in lon),
piece (position in layout$pieces), x and y,
in units of a face edge.
Examples
grid <- hex_grid(resolution = 3, aperture = 4, polyhedron = "octahedron",
orientation = "gosper")
world <- net_layout(grid, "gosper")
net_project(world, c(16.37, -74.0), c(48.21, 40.71))
Create a HexData Object (Internal)
Description
Internal constructor for HexData objects. Users should use hexify()
instead.
Usage
new_hex_data(data, grid, cell_id, cell_center)
Arguments
data |
Data frame or sf object (original user data, untouched) |
grid |
HexGridInfo object |
cell_id |
Cell IDs for each row: integer64, or whole numbers below 2^53 |
cell_center |
Matrix with columns lon, lat for cell centers |
Value
A HexData object
Plot Hexagonal Grid Clipped to a Polygon Boundary
Description
A convenience function that creates a grid, clips it to a boundary polygon, and plots the result in a single call.
Usage
plot_grid(
boundary,
grid,
crop = TRUE,
boundary_fill = "gray95",
boundary_border = "gray40",
boundary_lwd = 0.5,
grid_fill = "steelblue",
grid_border = "steelblue",
grid_lwd = 0.3,
grid_alpha = 0.3,
title = NULL,
expand = 0.05
)
Arguments
boundary |
An sf/sfc polygon to clip to (e.g., country boundary) |
grid |
A HexGridInfo object from |
crop |
If TRUE (default), cells are cropped to boundary. If FALSE, only complete hexagons within boundary are shown. |
boundary_fill |
Fill color for the boundary polygon (default "gray95") |
boundary_border |
Border color for boundary (default "gray40") |
boundary_lwd |
Line width for boundary (default 0.5) |
grid_fill |
Fill color for grid cells (default "steelblue") |
grid_border |
Border color for grid cells (default "steelblue") |
grid_lwd |
Line width for cell borders (default 0.3) |
grid_alpha |
Transparency for cell fill (0-1, default 0.3) |
title |
Plot title. If NULL (default), auto-generates title with cell area. |
expand |
Expansion factor for plot limits (default 0.05) |
Details
This is a convenience wrapper around grid_clip() that handles the
common use case of visualizing a hexagonal grid over a geographic region.
Value
A ggplot object that can be further customized
See Also
grid_clip for the underlying clipping function,
hex_grid for grid specification
Examples
# Metropolitan France: the world map also carries the overseas departements,
# and grid_clip() covers the bounding box of whatever it is given.
france <- sf::st_crop(
sf::st_geometry(hexify_world[hexify_world$name == "France", ]),
c(xmin = -5, ymin = 41, xmax = 10, ymax = 52)
)
grid <- hex_grid(area_km2 = 2000)
plot_grid(france, grid)
# Customize colors
plot_grid(france, grid,
grid_fill = "coral", grid_alpha = 0.5,
boundary_fill = "lightyellow")
# Keep only complete hexagons
plot_grid(france, grid, crop = FALSE)
# Add ggplot2 customizations
library(ggplot2)
plot_grid(france, grid) +
labs(subtitle = "ISEA3H Discrete Global Grid") +
theme_void()
Quick World Map Plot
Description
Simple wrapper to plot the built-in world map.
Usage
plot_world(fill = "gray90", border = "gray50", ...)
Arguments
fill |
Fill color for countries |
border |
Border color for countries |
... |
Additional arguments passed to plot() |
Value
NULL invisibly. Creates a plot as side effect.
See Also
Other visualization:
hexify_heatmap()
Examples
# Quick world map
plot_world()
# Custom colors
plot_world(fill = "lightblue", border = "darkblue")
Distortion of a Grid's Face Projection
Description
Tissot's indicatrix of the projection that maps the sphere onto the faces
of the grid's solid (Snyder's or the vertex-oriented equal-area projection,
or Fuller's): a small
circle on the sphere maps to an ellipse on the face, with semi-axes
a and b times the circle's radius.
Usage
projection_distortion(x, lon, lat, stage = c("face", "lambert", "nudge"))
Arguments
x |
A HexGridInfo object from |
lon, lat |
Longitudes and latitudes in degrees. |
stage |
|
Details
The scale factors are the singular values of the projection's derivative,
computed exactly by forward-mode automatic differentiation of the
projection code. Face-plane lengths are measured on the plane triangle
that has the face's area, so the areal scale a * b is 1 everywhere
under Snyder's projection and IVEA, and its mean over a face is 1 under
Fuller's.
Snyder's projection bends along the arcs from each face's centre to its corners, where its derivative jumps, and IVEA along those and the arcs to the edge midpoints; there and on face edges the result is the derivative on one side. Its angular deformation is largest at the face centre, approached along those arcs: 17.27 degrees, with scale factors 1.163 and 0.860 (Snyder 1992, Table 1). At a face centre the projection has a different derivative along each direction, and the result is the limit along the azimuth the point's coordinates give.
stage reads the indicatrix at an earlier step of Lambert's
construction of Snyder's projection (see projection_stages):
"lambert", Lambert's azimuthal equal-area projection about the face
centre onto the tangent plane, with scale factors
1 / \cos(z / 2) across the radius and \cos(z / 2) along it at
arc z from the centre; "nudge", Snyder's point on the tangent
plane before the scaling onto the face plane, whose scale factors are those
of "face" over R', so its areal scale is 1 / R'^2
everywhere. Both read lengths on the tangent plane in units of the
sphere's radius.
Value
A data frame with one row per point: lon, lat,
face (from 0), the scale factors a (largest) and b
(smallest), the maximum angular deformation angular
2 \arcsin((a - b) / (a + b)) in degrees, the areal scale
areal a b, and angle, the direction of the longer
axis on the face plane in degrees anticlockwise from the face's x axis.
References
Snyder, J. P. (1992). An equal-area map projection for polyhedral globes. Cartographica 29(1), 10-21. doi:10.3138/27H7-8K88-4882-1752
van Leeuwen, D. and Strebe, D. (2006). A "slice-and-dice" approach to area equivalence in polyhedral map projections. Cartography and Geographic Information Science 33(4), 269-286. doi:10.1559/152304006779500687
See Also
plot with
distortion and tissot to map it;
projection_stages for the points at each step of Lambert's
construction
Examples
g <- hex_grid(resolution = 3, aperture = 3)
projection_distortion(g, c(0, 16.37), c(0, 48.21))
projection_distortion(g, c(0, 16.37), c(0, 48.21), stage = "lambert")
gf <- hex_grid(resolution = 3, aperture = 3, projection = "fuller")
d <- projection_distortion(gf, runif(1000, -180, 180),
asin(runif(1000, -1, 1)) * 180 / pi)
range(d$areal)
Points Through the Steps of Snyder's Projection
Description
Snyder's equal-area projection of a face is Lambert's azimuthal equal-area projection about the face's centre, adjusted to fill the face's plane triangle. Lambert's projection has a construction with compass and ruler, and this function returns each point at every step of it, on one face.
Usage
projection_stages(x, lon, lat, face = NULL)
Arguments
x |
A HexGridInfo object from |
lon, lat |
Longitudes and latitudes in degrees (geodetic on the grid's ellipsoid, if it has one: the construction starts from the point's place on the authalic sphere). |
face |
|
Details
With T the face centre on the sphere and S a point at arc
z from it and azimuth Az:
- sphere
Sitself.- lambert
Sswings aboutT, in the plane ofSand the normal atT, down onto the tangent plane atT, keeping its distance|TS| = 2 \sin(z / 2): the Lambert pointL, at azimuthAz. This map is equal-area and takes the spherical face to a triangle with curved edges.- nudge
Within the tangent plane, Snyder's adjustment moves
Lto azimuthAz'and radius2 f \sin(z / 2), which fill each of the face's six right triangles in the plane with area in proportion (Snyder 1992, eqs. 6-11).- snyder
The tangent plane scales by
R'about the sphere's centre onto the face plane, at distanceR'from it; the point lands on Snyder's pointP, at radius2 R' f \sin(z / 2), and the face on the plane triangle of the face's area.
Plane coordinates (u, v) run from the face centre along the
x and y axes of the face's plane triangle, the axes of tx and
ty, in units of the sphere's radius; an azimuth a lies along
(\sin a, \cos a). Seen from the sphere's centre the planes are
parallel, and the point's height along the face's normal is
\cos z for S, 1 on the tangent plane and R' on the
face plane. The sphere point's u and v are its projection
onto the planes along the normal.
The scale factors at every step come from
projection_distortion with its stage argument; they
and these points are computed by the same code as the forward projection,
and tx, ty are those hexify_forward returns.
Value
A data frame with one row per point: lon, lat,
face (from 0); arc, z in degrees; az
(Az) and az_prime (Az') in degrees from the face's
first vertex, clockwise seen from outside the sphere; Snyder's factor
f; the plane coordinates sphere_u, sphere_v,
lambert_u, lambert_v, nudge_u, nudge_v,
snyder_u, snyder_v; and tx, ty, Snyder's
point in triangle coordinates (a face edge is 1). The attribute
"r1" holds R'.
References
Snyder, J. P. (1992). An equal-area map projection for polyhedral globes. Cartographica 29(1), 10-21. doi:10.3138/27H7-8K88-4882-1752
See Also
projection_distortion;
hex_globe with lambert to follow the construction
on a globe
Examples
g <- hex_grid(resolution = 3, aperture = 3)
s <- projection_stages(g, c(0, 10, 16.37), c(40, 45, 48.21))
s
# The Lambert point keeps its distance from the face centre
cbind(lambert = sqrt(s$lambert_u^2 + s$lambert_v^2),
chord = 2 * sin(s$arc * pi / 360))
Objects exported from other packages
Description
These objects are imported from other packages. Follow the links below to see their documentation.
Spacing Metrics of Neighbouring Cells: Wall Length, Centre Distance and Cell Wall Midpoint Ratio
Description
Measures every wall between a cell and an adjacent cell: how long it is, how far apart the two cell centres are, and how far the wall's midpoint lies from the line between the centres.
Usage
wall_metrics(cell_id = NULL, grid)
Arguments
cell_id |
Cell IDs. When |
grid |
A HexGridInfo or HexData object. |
Details
The centre distance is the great-circle distance between the two cell centres. Gregory et al. (2008) measure the spread of a grid's intercell distances by their coefficient of variation.
The cell wall midpoint ratio (Gregory et al. 2008, after Heikes and Randall
1995) is the distance from the wall's midpoint to the midpoint of the
great-circle arc joining the two centres, over the wall's length. It is 0
where the arc between the centres crosses the wall at its middle, as it does
between two regular hexagons; a finite-volume scheme that evaluates a flux
at the wall's midpoint is most accurate there. The wall's midpoint is the
point halfway along the wall as the grid draws it (see
cell_metrics).
Value
Data frame with one row per wall: cell_id,
neighbor_id, wall_km, center_distance_km and
midpoint_ratio. A wall between two of the given cells appears once,
on the row of the cell given first; a wall to a cell not given appears on
the given cell's row.
References
Gregory, M. J., Kimerling, A. J., White, D. and Sahr, K. (2008). A comparison of intercell metrics on discrete global grid systems. Computers, Environment and Urban Systems 32(3), 188-203. doi:10.1016/j.compenvurbsys.2007.11.003
Heikes, R. and Randall, D. A. (1995). Numerical integration of the shallow-water equations on a twisted icosahedral grid. Part II. A detailed description of the grid and an analysis of numerical accuracy. Monthly Weather Review 123(6), 1881-1887. doi:10.1175/1520-0493(1995)123<1881:NIOTSW>2.0.CO;2
See Also
cell_metrics for cell shape,
get_neighbors
Examples
g <- hex_grid(resolution = 3, aperture = 3)
w <- wall_metrics(grid = g)
sd(w$center_distance_km) / mean(w$center_distance_km)
summary(w$midpoint_ratio)
# The walls around one cell
cell <- lonlat_to_cell(16.37, 48.21, g)
wall_metrics(cell, g)