Create square or hexagonal grid polygons over a boundary
Source:R/tessellation.R
create_grid_polygons.RdLays a regular grid of equal-area cells over boundary and clips it to that
boundary. Reach for this rather than create_voronoi_polygons() when cell
size should be a decision you make, instead of one dictated by where the
observations happen to be. That is the case when you need per-cell rates
comparable across the map, or a resolution that stays fixed as the sample
grows. Hexagons (type = "hex") avoid the axis-aligned artefacts of squares
and give every cell the same distance to all six neighbours, which matters
for anything that reads neighbourhoods.
Usage
create_grid_polygons(
boundary,
target_cells = NULL,
type = c("square", "hex"),
cellsize = NULL,
n = NULL,
clip = TRUE,
crs = NULL,
quiet = FALSE,
max_cells = 1e+06
)Arguments
- boundary
Polygonal sf or sfc object.
- target_cells
Optional approximate desired number of cells. The cell size is derived from it as
sqrt(area / target_cells), whereareais that of the boundary's bounding box, so square grids get square cells; for hex grids the count is adjusted for hexagonal packing density and the size rounded so that a whole number of hexagon widths spans the longer side of the box. The size does not depend on which way the boundary lies; the count can, because hexagon rows are 0.87cellsizeapart while columns arecellsizeapart (about 10 percent on a moderately elongated box, up to 1.7 times on a strip narrower than one hexagon). The word "approximate" is load bearing: a grid of square cells over an elongated bounding box needs more of them than a grid of rectangles would (a 1000 x 1 strip attarget_cells = 9yields cells of side 10.5 and about 95 of them), and clipping to an irregular boundary moves the count again. Passcellsizewhen the count matters more than the shape.- type
Grid type:
"square"(the default) or"hex".- cellsize
Optional numeric cell size (length 1 or 2), in the units of the working CRS. Takes precedence over
n: if both are supplied,cellsizeis used,nis ignored and a warning is logged. Supply exactly one oftarget_cells,cellsizeandn. Fortype = "hex"a hexagon is defined by a single edge-to-edge distance, so onlycellsize[1]is used and a differingcellsize[2]is ignored with a logged warning.- n
Optional grid resolution (integer, length 1 or 2) giving the number of columns and rows to divide the boundary's bounding box into; the cell size is derived from it.
sf::st_make_grid()derives hexagon placement fromcellsizealone, so fortype = "hex"ndoes not set the number of cells, although it does change the grid, because thecellsizederived from it is what the hexagons are built with. Ignored (with a logged warning) whencellsizeis also supplied. Passing both would otherwise truncate the grid ton[1]xn[2]cells anchored at the bounding-box corner, covering only part of the boundary.- clip
Logical; clip grid to boundary.
- crs
Optional target CRS: anything
sf::st_crs()accepts, including an sf or sfc layer, whose CRS is used. WhenNULL(default) a lon/lat boundary is projected withensure_projected(), which changes the CRS of the returned grid; a message reports this unlessquiet = TRUE. When that CRS would distort cell areas across the boundary by more than 1 percent (Web Mercator over a near-global extent, a UTM zone stretched well past its width),ensure_projected(purpose = "area")is used instead, with a logged warning, so the cells stay equal-area; a local extent keeps its UTM zone. A geographiccrs(EPSG:4326, say) is the CRS the grid is returned in: a grid sized bytarget_cellsornis laid in that projected CRS and then transformed, with long edges densified. Acellsizeis in the units ofcrs, so with a geographiccrsit is in degrees and the grid is laid in degrees, as asked; such cells are not equal-area.- quiet
Logical; suppress this function's progress
message()s. It does not silence R warnings, nor the package's console log echo (seespatialkit_quietfor that). DefaultFALSE.- max_cells
Upper bound on the number of cells the grid may have, estimated from the boundary's bounding box before anything is built. Default
1e6. Acellsizein the wrong units (metres on a boundary in kilometres, say) asks for a grid that cannot be built, and this refuses it with a message before memory is exhausted. Set toInfto disable.
Details
Size the grid with exactly one of target_cells (roughly how many cells you
want, the package derives the rest), cellsize (a fixed edge length in CRS
units) or n (a fixed number of columns and rows). See @param cellsize
for what happens when more than one is given.
Examples
library(sf)
bnd <- st_sf(geometry = st_sfc(st_polygon(list(rbind(
c(0, 0), c(100, 0), c(100, 100), c(0, 100), c(0, 0)
))), crs = 32632))
grid_sq <- create_grid_polygons(bnd, target_cells = 100, type = "square")
grid_hex <- create_grid_polygons(bnd, target_cells = 100, type = "hex")
nrow(grid_sq)
#> [1] 100
# Hex counts run above target because clipping keeps every hexagon that
# merely overhangs the boundary; the inflation is proportionally larger
# at small target_cells.
nrow(grid_hex)
#> [1] 114