Skip to contents

Ensures that a polygon layer has a reproducible, deterministic identifier column by sorting features using representative point coordinates (and secondary tie-breakers) and then assigning sequential IDs.

Usage

ensure_stable_poly_id(
  polygons_sf,
  id_col = "poly_id",
  method = c("centroid", "surface_point", "bbox_center"),
  make_valid = TRUE,
  transform_for_sort = 4326
)

Arguments

polygons_sf

An sf or sfc object containing polygonal features.

id_col

Character scalar; name of the identifier column.

method

One of "centroid", "surface_point", "bbox_center".

make_valid

Logical; apply st_make_valid() first. Default TRUE.

transform_for_sort

CRS used only for computing sort-key coordinates. Default 4326. This is the whole mechanism by which the IDs are stable (sorting in one common CRS is what makes the same layer get the same IDs whichever projection it arrives in), so if the transform fails the function says so rather than quietly sorting in the input's own CRS. The sort key is rounded to 7 decimal degrees (about 1 cm) before ordering, so the floating-point noise of a round trip through a different projection does not usually reverse two neighbouring cells. It can where two cells' centres lie within about that step of the same longitude, as fine cells stacked north-south near a projection's central meridian do: 36 of 2,500 100 m cells straddling a UTM central meridian changed ID after a transform to EPSG:3035. No rounding step removes that, so to match cells computed in different projections, join them on geometry rather than on the ID. The key is computed on the sphere (s2) whether or not sf::sf_use_s2() is on, so the session setting does not change the IDs. Set to NULL to sort in the input CRS, which gives IDs that are reproducible but not comparable across projections.

Value

An sf polygon layer re-ordered with sequential IDs in id_col. Non-polygonal rows are dropped (with a warning), so the result can have fewer rows than the input; if no polygonal rows remain, an error is raised.

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))
g <- create_grid_polygons(bnd, target_cells = 9)
# Reverse the rows and re-derive the IDs: the SAME cell gets the same ID,
# which is the property a row-position ID does not have.  The check joins
# the two layers on geometry, because comparing sorted ID vectors would
# pass for any two permutations of 1:9.
fwd <- ensure_stable_poly_id(g)
rev <- ensure_stable_poly_id(g[nrow(g):1, ])
same_cell <- match(st_as_text(st_geometry(rev)), st_as_text(st_geometry(fwd)))
all(rev$poly_id == fwd$poly_id[same_cell])
#> [1] TRUE