% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/spatial_topology.R
\name{spatial_topology}
\alias{spatial_topology}
\title{Build the shared-edge topology of a polygon coverage}
\usage{
spatial_topology(
  x,
  id = NULL,
  by = NULL,
  geom = "geometry",
  crs = NA,
  face_cols = c("face1", "face2"),
  flush_rows = NULL
)
}
\arguments{
\item{x}{A \code{vectra_node} (from \code{\link[=tbl]{tbl()}}, \code{\link[=tbl_tiff]{tbl_tiff()}}, any verb chain, ...).
It is consumed by the stream.}

\item{id}{Optional name of a column of \code{x} whose value identifies each polygon
in the face columns. \code{NULL} (default) uses the 1-based feature order within
the group.}

\item{by}{Character vector of attribute columns whose groups are each built as
an independent coverage. \code{NULL} (default) treats the whole layer as one
coverage.}

\item{geom}{Name of the input geometry column holding hex-WKB or WKT strings.
Default \code{"geometry"}. Ignored when \code{coords} is given.}

\item{crs}{Coordinate reference system of the input geometry, in any form
\code{\link[sf:st_crs]{sf::st_crs()}} accepts (EPSG integer, WKT, proj string). Defaults to the
CRS the upstream node carries, or unknown.}

\item{face_cols}{Length-2 character vector naming the two output columns that
hold the identifiers of the polygons on either side of each arc. Default
\code{c("face1", "face2")}.}

\item{flush_rows}{Transformed rows buffered before a spill flush. Larger
values mean fewer, bigger temporary files. Defaults to
\code{getOption("vectra.spatial_flush", 5e5)}.}
}
\value{
A \code{vectra_node} of one row per arc -- the arc geometry plus the two
face-identifier columns (and any \code{by} columns) -- carrying the input CRS and
backed by temporary \code{.vtr} spills removed when the node is garbage-collected.
}
\description{
Decomposes a polygon coverage into the arcs of its planar topology: each
border is returned once, tagged with the polygons on either side. Where the
raw boundaries of adjacent polygons each carry their own copy of a shared
edge, this nodes the unioned boundaries so a shared border is a single arc
carrying the identifiers of both neighbours -- the "build topology" of a GIS,
and the adjacency a dissolve or a coverage edit needs. An internal arc names
two faces; an outer arc names one and leaves the other side \code{NA}. Like
\code{\link[=spatial_dissolve]{spatial_dissolve()}} it rides the \strong{partition tier}: \code{x} is spilled once and
routed into one disjoint shard per \code{by} group in a single bounded pass, and
each group is treated as an independent coverage. Peak memory is the routing
budget during the pass, then one group's geometry while its arcs are built.
}
\details{
Geometry travels through the engine as hex-encoded WKB in a string column and
the CRS is carried on the returned node; the noding is \pkg{sf}/GEOS and
expects projected or unprojected planar data. The \pkg{sf} package is an
optional dependency (Suggests).
}
\examples{
\dontshow{if (requireNamespace("sf", quietly = TRUE)) withAutoprint(\{ # examplesIf}
p1 <- sf::st_polygon(list(rbind(c(0, 0), c(1, 0), c(1, 1), c(0, 1), c(0, 0))))
p2 <- sf::st_polygon(list(rbind(c(1, 0), c(2, 0), c(2, 1), c(1, 1), c(1, 0))))
f <- tempfile(fileext = ".vtr")
write_vtr(data.frame(
  id = c("a", "b"),
  geometry = sf::st_as_binary(sf::st_sfc(p1, p2), hex = TRUE)
), f)

# The shared edge appears once, tagged with both neighbours.
tbl(f) |> spatial_topology(id = "id") |> collect()
unlink(f)
\dontshow{\}) # examplesIf}
}
\seealso{
\code{\link[=spatial_polygonize]{spatial_polygonize()}} to rebuild faces from arcs,
\code{\link[=spatial_dissolve]{spatial_dissolve()}} to merge geometries by group, \code{\link[=collect_sf]{collect_sf()}} to
materialize as \code{sf}.
}
