% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/geom_expr.R
\name{geom_expressions}
\alias{geom_expressions}
\title{Geometry functions inside mutate(), filter(), and summarise()}
\description{
vectra recognizes a family of \verb{st_*} geometry functions directly inside
expression verbs. They run on the GEOS C library straight off the hex-WKB
geometry column, one row at a time, with no per-batch round-trip through
\pkg{sf}: \code{tbl(f) |> filter(st_area(geometry) > 1e6)} prunes the stream in C,
and \code{mutate(centroid = st_centroid(geometry))} adds a new hex-WKB geometry
column. The computation is planar, in the geometry's own coordinate units,
exactly as the streaming spatial verbs are.
}
\details{
These names are interpreted by the expression engine; they are not exported R
functions and are not called as such. They are available only inside
\code{\link[=mutate]{mutate()}}, \code{\link[=transmute]{transmute()}}, \code{\link[=filter]{filter()}}, and a grouped \code{\link[=summarise]{summarise()}} over a
\code{vectra_node}. The geometry argument is the hex-WKB column (named \code{geometry}
by convention). A function that returns a geometry produces another hex-WKB
column; materialize it with \code{\link[=collect_sf]{collect_sf()}} (point it at the column with
\verb{geom =}), or write it with \code{\link[=write_tiff]{write_tiff()}}/\code{sf::st_write()}.
}
\section{Measures (return a number)}{

\describe{
\item{\code{st_area(g)}}{Area of polygonal geometry (0 for lines and points).}
\item{\code{st_length(g)}, \code{st_perimeter(g)}}{Length of a line, or the perimeter
(boundary length) of a polygon. The two names are aliases.}
\item{\code{st_x(g)}, \code{st_y(g)}}{Coordinate of a point geometry; \code{NA} for a
non-point.}
\item{\code{st_npoints(g)}}{Number of coordinates in the geometry.}
\item{\code{st_ngeometries(g)}}{Number of sub-geometries in a collection or
multi-geometry (1 for a single geometry).}
\item{\code{st_distance(a, b)}}{Shortest planar distance between two geometries
(see the binary second argument below).}
}
}

\section{Predicates (return TRUE / FALSE)}{

Unary: \code{st_is_valid(g)}, \code{st_is_empty(g)}, \code{st_is_simple(g)}.

Binary topological relations, each taking a second geometry: \code{st_intersects},
\code{st_within}, \code{st_contains}, \code{st_overlaps}, \code{st_touches}, \code{st_crosses},
\code{st_equals}, \code{st_disjoint}, \code{st_covers}, \code{st_covered_by}. Used in \code{\link[=filter]{filter()}}
they keep the rows where the relation holds.
}

\section{Type (returns a string)}{

\code{st_geometry_type(g)} gives the GEOS geometry type name (\code{"Point"},
\code{"Polygon"}, \code{"MultiPolygon"}, ...).
}

\section{Transforms (return a geometry)}{

\describe{
\item{\code{st_centroid(g)}}{Area (or length, or vertex) centroid.}
\item{\code{st_point_on_surface(g)}}{A point guaranteed to lie on the geometry.}
\item{\code{st_boundary(g)}}{The topological boundary.}
\item{\code{st_envelope(g)}}{The axis-aligned bounding rectangle.}
\item{\code{st_convex_hull(g)}}{The convex hull.}
\item{\code{st_make_valid(g)}}{Repair an invalid geometry.}
\item{\code{st_buffer(g, dist)}}{Buffer by \code{dist} (round joins, 8 segments per
quadrant).}
\item{\code{st_simplify(g, tol)}}{Topology-preserving Douglas-Peucker
simplification with tolerance \code{tol}.}
}
}

\section{The second geometry of a binary op}{

For \code{st_distance} and the binary predicates, the second argument can be
another geometry column (compared row by row), a constant \code{sf}/\code{sfc} object
(a multi-feature object is unioned to one geometry), or a hex-WKB string. A
constant is parsed once and reused across every row, so testing a whole
stream against one area of interest stays cheap.
}

\section{Missing geometry}{

A missing (\code{NA}) or unparseable geometry, or an operation that has no answer
(a coordinate of a non-point, distance to a missing geometry), yields \code{NA}
for that row rather than an error.
}

\examples{
if (requireNamespace("sf", quietly = TRUE)) {
  nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
  f <- tempfile(fileext = ".vtr")
  write_vtr(data.frame(
    NAME     = nc$NAME,
    geometry = sf::st_as_binary(sf::st_geometry(nc), hex = TRUE)
  ), f)

  # measures: add area and perimeter columns
  tbl(f) |>
    mutate(area = st_area(geometry), perim = st_perimeter(geometry)) |>
    select(NAME, area, perim) |>
    collect() |>
    head()

  # predicate: keep counties intersecting an area of interest
  aoi <- sf::st_as_sfc(sf::st_bbox(
    c(xmin = -81.5, ymin = 36.2, xmax = -80.5, ymax = 36.6)))
  tbl(f) |> filter(st_intersects(geometry, aoi)) |> collect() |> nrow()

  # transform: replace each county with its centroid, materialize as sf
  tbl(f) |>
    mutate(geometry = st_centroid(geometry)) |>
    select(NAME, geometry) |>
    collect_sf()

  unlink(f)
}
}
\seealso{
\code{\link[=mutate]{mutate()}}, \code{\link[=filter]{filter()}}, \code{\link[=collect_sf]{collect_sf()}} to materialize a geometry
result as \code{sf}; \code{\link[=spatial_map]{spatial_map()}} for an arbitrary per-feature \pkg{sf}
transform; \code{\link[=spatial_filter]{spatial_filter()}} and \code{\link[=spatial_join]{spatial_join()}} for relating a stream to
a resident reference layer.
}
