% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/spatial_topology.R
\name{spatial_line_merge}
\alias{spatial_line_merge}
\title{Merge contiguous line segments into maximal lines}
\usage{
spatial_line_merge(
  x,
  by = NULL,
  geom = "geometry",
  crs = NA,
  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{by}{Character vector of attribute columns to merge within: one set of
maximal lines per distinct combination of their values. \code{NULL} (default)
merges the whole layer at once.}

\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{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 maximal merged line, carrying the \code{by}
columns and the input CRS, backed by temporary \code{.vtr} spills removed when
the node is garbage-collected.
}
\description{
Sews the line segments of each group into the longest possible linestrings
(\code{sf::st_line_merge}, the line counterpart of a dissolve): segments that meet
end to end become one chain, and each chain is emitted as its own row. Where a
plain union of lines returns a single multilinestring of all the parts, this
joins the parts through their shared endpoints; at a crossing where more than
two segments meet the merge is ambiguous and the segments stay separate. 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, then
each group's segments are merged together. Peak memory is the routing budget
during the pass, then one group's geometry while it is merged. With no \code{by},
the whole layer is merged at once.
}
\details{
Each merged line is new geometry built from the whole group, so it carries the
\code{by} columns only, not the attributes of any single source segment. Geometry
travels through the engine as hex-encoded WKB in a string column and the CRS
is carried on the returned node. The \pkg{sf} package is an optional
dependency (Suggests).
}
\examples{
\dontshow{if (requireNamespace("sf", quietly = TRUE)) withAutoprint(\{ # examplesIf}
seg <- sf::st_sfc(
  sf::st_linestring(rbind(c(0, 0), c(1, 0))),
  sf::st_linestring(rbind(c(1, 0), c(2, 0))),
  sf::st_linestring(rbind(c(2, 0), c(3, 0))))
f <- tempfile(fileext = ".vtr")
write_vtr(data.frame(
  geometry = sf::st_as_binary(seg, hex = TRUE)
), f)

# The three end-to-end segments become one line.
tbl(f) |> spatial_line_merge() |> collect_sf()
unlink(f)
\dontshow{\}) # examplesIf}
}
\seealso{
\code{\link[=spatial_dissolve]{spatial_dissolve()}} to union geometries by group,
\code{\link[=spatial_explode]{spatial_explode()}} for the opposite direction (multipart to single part),
\code{\link[=collect_sf]{collect_sf()}} to materialize as \code{sf}.
}
