--- title: "Getting started with a5R" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting started with a5R} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} library(a5R) ``` ## Index a point Map a longitude/latitude coordinate to a cell at a given resolution (0--30). Higher resolutions produce smaller cells. ```{r} cell <- a5_lonlat_to_cell(-3.19, 55.95, resolution = 10) cell ``` Convert back to the cell centre point: ```{r} a5_cell_to_lonlat(cell) ``` ## Cell boundaries Get the boundary polygon for one or more cells: ```{r boundary-plot, fig.width = 5, fig.height = 4} boundary <- a5_cell_to_boundary(cell) boundary plot(boundary, col = "#206ead20", border = "#206ead", asp = 1) ``` Boundaries are returned as `wk_wkb` vectors by default (set `format = "wkt"` for WKT). Both integrate directly with sf, terra, and other spatial tooling via the wk package. ## Hierarchy and compaction A5 is a hierarchical grid: every cell has a **parent** at a coarser resolution and 4 **children** at the next finer resolution. ```{r} parent <- a5_cell_to_parent(cell) parent children <- a5_cell_to_children(cell) children ``` We can visualise the relationship: the parent (dark outline) contains our cell (blue fill), which in turn contains its 4 children (orange): ```{r hierarchy-plot, fig.width = 8, fig.height = 8} plot(NULL, xlim = c(-3.23, -3), ylim = c(55.98, 55.99), xlab = "", ylab = "", asp = 1 ) plot(a5_cell_to_boundary(a5_cell_to_children(cell)), col = "#ad6e2020", border = "#ad6e20", add = TRUE) plot(a5_cell_to_boundary(cell), col = "#206ead40", border = "#206ead", lwd = 2, add = TRUE) plot(a5_cell_to_boundary(parent), border = "#333333", lwd = 2, add = TRUE) ``` Cell area decreases geometrically: each level is roughly 4x smaller. ```{r} a5_cell_area(0:5) ``` ### Compact and uncompact When a complete set of siblings is present, `a5_compact()` merges them back into their shared parent. This is the inverse of `a5_cell_to_children()` and is useful for reducing the size of large cell sets without losing coverage. ```{r} children a5_compact(children) # round-trips back to the original a5_uncompact(a5_compact(children), resolution = 11) ``` Many a5R functions return compacted output automatically. For example, `a5_grid_disk()` and `a5_spherical_cap()` compact their results; use `a5_uncompact()` when you need a uniform-resolution grid (see [Traversal](#traversal) below). ## Traversal Find neighbouring cells by hop count with `a5_grid_disk()`, or by great-circle distance with `a5_spherical_cap()`: ```{r traversal, fig.width = 7} disk <- a5_grid_disk(cell, k = 10) cap <- a5_spherical_cap(cell, radius = 50000) plot(a5_cell_to_boundary(cap), col = "#6ead2020", border = "#6ead20", asp = 1) plot(a5_cell_to_boundary(disk), col = "#206ead20", border = "#206ead", asp = 1) ``` Both functions return a **compacted** cell vector: sibling groups are merged into coarser parent cells to save space. To recover a uniform grid at the original resolution, pass the result through `a5_uncompact()`: ```{r traversal-uncompact, fig.width = 7} disk_grid <- a5_uncompact(disk, resolution = a5_get_resolution(cell)) plot(a5_cell_to_boundary(disk_grid), col = "#206ead20", border = "#206ead", asp = 1) ``` ## Converting geometries to a5 cells `a5_polygon_to_cells()` returns the cells whose centres lie inside a polygon. It accepts any geometry that wk can handle (a `wk::rct()` bounding box, a WKT or WKB polygon, an `sf` / `sfc` feature) and also terra `SpatVector` polygons. ```{r grid-plot, fig.width = 7} cells <- a5_polygon_to_cells(wk::rct(-3.3, 55.9, -3.1, 56.0), resolution = 12) length(cells) plot(a5_cell_to_boundary(cells), col = "#206ead20", border = "#206ead", asp = 1) ``` The returned vector is sorted and compacted: whenever four sibling cells all sit inside the polygon, they are merged into their parent so the result uses fewer slots without losing coverage. Call `a5_uncompact()` to expand back to a uniform grid at the target resolution: ```{r} cells_uncom <- a5_uncompact(cells, 12) length(cells_uncom) plot(a5_cell_to_boundary(cells_uncom), col = "#206ead20", border = "#206ead", asp = 1) ``` Multi-part inputs are handled natively: a `MULTIPOLYGON` or an `sfc` of multiple polygons returns the union of cells across all parts, and a `POLYGON` with holes returns the outer ring's cells with the hole cells properly subtracted. ```{r, eval = requireNamespace("sf", quietly = TRUE)} library(sf) demo(nc, ask = FALSE, echo = FALSE) nca5 <- a5_polygon_to_cells(nc, resolution = 9) |> a5_uncompact(9) plot(a5_cell_to_boundary(nca5), col = "#03030320", border = "#6d20adff", asp = 1) ``` ## Tracing a line `a5_linestring_to_cells()` returns the cells whose pentagons are crossed by a great-circle polyline. Output is in discovery order along the path. Consecutive waypoints are connected by great-circle arcs, so antimeridian-crossing routes work transparently. Multi-part inputs (`MULTILINESTRING` or an `sfc` of several linestrings) are handled natively: per-feature outputs are concatenated in feature order with first-seen deduplication. To show what cell-by-cell tracing looks like, we can write a short phrase as a `MULTILINESTRING` (one stroke per letter) and ask A5 to fill in the cells: ```{r linestring-a5R, fig.width = 7, fig.height = 3} a5R_strokes <- wk::wkt( "MULTILINESTRING ( (1.8 52.5, 1.2 52.8, 0.6 52.5, 0.4 52, 0.6 51.5, 1.2 51.2, 1.8 51.5, 2 52, 1.8 52.5, 2 51.2), (5 53, 3.5 53, 3.5 52.2, 4 52.2, 4.7 52, 5 51.6, 4.7 51.2, 4 51, 3.5 51.1), (6.5 51, 6.5 53, 7.5 53, 8 52.8, 8.2 52.5, 8 52.2, 7.5 52, 6.5 52, 8.2 51) )" ) cells <- a5_linestring_to_cells(a5R_strokes, resolution = 9) length(cells) plot(a5_cell_to_boundary(cells), col = "#206ead80", border = "#37af6d", asp = 1) ``` Each stroke is one continuous linestring; the function walks the great-circle path, expanding cell neighbours along the way, and returns the union across all strokes.