% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/spatial.R
\name{spatial_filter}
\alias{spatial_filter}
\title{Keep streamed rows by their spatial relation to a resident layer}
\usage{
spatial_filter(
  x,
  y,
  predicate = NULL,
  negate = FALSE,
  geom = "geometry",
  coords = NULL,
  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{y}{An \code{sf} or \code{sfc} object: the resident locator layer to test against.}

\item{predicate}{An \pkg{sf} binary predicate function, e.g.
\link[sf:st_intersects]{sf::st_intersects} (default), \link[sf:st_within]{sf::st_within}, \link[sf:st_covered_by]{sf::st_covered_by},
\link[sf:st_is_within_distance]{sf::st_is_within_distance}. A left row is kept when the predicate reports
at least one match against \code{y}.}

\item{negate}{If \code{TRUE}, keep the rows with no match instead (the inverted
select-by-location). Default \code{FALSE}.}

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

\item{coords}{Optional length-2 character vector naming the x and y
coordinate columns to assemble point geometry from (e.g. \code{c("x", "y")}),
for inputs such as \code{\link[=tiff_extract_points]{tiff_extract_points()}} output. The coordinate columns
are retained.}

\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)}.}

\item{...}{Further arguments passed to \code{predicate}, e.g. \verb{dist =} for
\link[sf:st_is_within_distance]{sf::st_is_within_distance}.}
}
\value{
A \code{vectra_node} of the kept rows with \code{x}'s schema, backed by
temporary \code{.vtr} spills and carrying the input CRS.
}
\description{
Streams a large left side \code{x} through the engine and keeps each row whose
geometry satisfies an \pkg{sf} binary predicate against a small resident
layer \code{y} (select by location). This is the spatial counterpart to a
\code{\link[=semi_join]{semi_join()}}: rows are filtered, never duplicated, and no columns are added,
so the output carries \code{x}'s schema unchanged. With \code{negate = TRUE} it keeps
the rows that do \emph{not} match (select by location, inverted). The billion-row
left stream never materializes; \code{y} (a study region, habitat patches, a
coastline buffer, ...) stays resident.
}
\details{
For the recognised predicates -- the topological ones (intersects, within,
contains, overlaps, covers, covered by, touches, crosses), equals, disjoint,
and within-distance (\link[sf:st_is_within_distance]{sf::st_is_within_distance}, whose radius is passed as
\verb{dist =}) -- on projected or unprojected planar data, the test runs natively
on the GEOS C API straight off the hex-WKB column: \code{y} is parsed once into a
spatial index and each batch is tested in C, with no per-batch round-trip
through \pkg{sf}. Coordinate-assembled (\code{coords}) point input runs natively
too, building each point in C rather than through \pkg{sf}; disjoint is the
one exception there (its matches are the bounding boxes the index prunes
away) and keeps the \pkg{sf} loop, as it does for the join. Geographic
coordinates with spherical geometry on (\code{sf::sf_use_s2()}) and any other
predicate use \pkg{sf} instead, preserving its semantics. When \code{y} carries no
CRS it inherits the stream's so the predicate does not reject on a mismatch.
}
\examples{
\dontshow{if (requireNamespace("sf", quietly = TRUE)) withAutoprint(\{ # examplesIf}
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
region <- nc[nc$NAME \%in\% c("Ashe", "Alleghany", "Surry"), "NAME"]

set.seed(1)
pts <- sf::st_coordinates(sf::st_sample(nc, 300))
f <- tempfile(fileext = ".vtr")
write_vtr(data.frame(id = seq_len(nrow(pts)), x = pts[, 1], y = pts[, 2]), f)

# Keep only the points that fall inside the three-county region, streaming.
inside <- tbl(f) |>
  spatial_filter(region, coords = c("x", "y"), crs = sf::st_crs(nc))
nrow(collect(inside))
unlink(f)
\dontshow{\}) # examplesIf}
}
\seealso{
\code{\link[=spatial_join]{spatial_join()}} to tag rows with \code{y}'s attributes, \code{\link[=spatial_clip]{spatial_clip()}}
to cut geometry against a mask, \code{\link[=filter]{filter()}} for attribute predicates.
}
