% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/vcg-collision.R
\name{vcg_detect_collision}
\alias{vcg_detect_collision}
\title{Detect collisions between two geometries}
\usage{
vcg_detect_collision(
  x,
  y,
  mode_x = c("auto", "points", "segments", "mesh"),
  mode_y = c("auto", "points", "segments", "mesh"),
  radius = 0,
  early_stop = FALSE,
  include_interior = FALSE
)
}
\arguments{
\item{x}{the geometry that gets indexed; a matrix with \code{n} rows and 2
or 3 columns, or a surface (see \code{\link{ensure_mesh3d}})}

\item{y}{the geometry that gets queried; results are aligned to this side.
Same accepted types as \code{x}}

\item{mode_x, mode_y}{how to interpret \code{x} and \code{y}: \code{'points'}
treats each row as an isolated point, \code{'segments'} chains consecutive
rows together (\code{p1-p2}, \code{p2-p3}, ...), and \code{'mesh'} uses
the triangular faces. The default \code{'auto'} resolves to \code{'mesh'}
for a surface that has faces and \code{'points'} otherwise, so a matrix of
connected line segments must ask for \code{'segments'} explicitly}

\item{radius}{distance tolerance; a collision is reported when the minimum
distance is at most \code{radius}. Defaults to \code{0}, meaning literal
contact; a positive tolerance is usually what is wanted}

\item{early_stop}{whether to stop as soon as a collision is found, scanning
independently within each group of \code{y} delimited by \code{NA} rows. A
matrix carrying no \code{NA} rows is a single group, so a point cloud stops
after one hit overall rather than per row; likewise \code{mode_y = 'mesh'}
stops at the first colliding face. Skipped elements report \code{hit = NA},
meaning \emph{not evaluated} rather than \emph{no collision}, and the
collision reported is the first in row order, not the closest. Use
\code{FALSE} (the default) whenever the per-element profile or a minimum
distance is wanted}

\item{include_interior}{whether geometry lying strictly inside a closed
\code{x} surface counts as a collision even when it never comes within
\code{radius} of the surface itself; requires \code{mode_x = 'mesh'}.
Default is \code{FALSE}}
}
\value{
A list of three vectors, each aligned one-to-one with the rows of
\code{y} (or with the faces of \code{y} when \code{mode_y = 'mesh'}):
\describe{
  \item{\code{hit}}{logical. \code{NA} marks an element with nothing to
    test: a separator row, or the final vertex of each group when
    \code{mode_y = 'segments'}. When \code{early_stop = TRUE}, \code{NA}
    also marks elements the scan never reached}
  \item{\code{distance}}{the exact minimum distance where \code{hit} is
    \code{TRUE}, and \code{NA} everywhere else. Distances beyond
    \code{radius} are never computed, so a \code{FALSE} element carries no
    distance}
  \item{\code{index}}{1-based index of the closest element of \code{x}
    within \code{radius}: a row when \code{mode_x} is \code{'points'}, the
    row where the segment starts when \code{'segments'}, or a face column
    when \code{'mesh'}. \code{NA} where there is no collision}
}
}
\description{
Reports, for every element of \code{y}, whether it comes within
\code{radius} of \code{x}, together with the exact minimum distance. Each
side may be a point cloud, a set of connected line segments (for example
diffusion streamlines or an electrode shaft), or a triangular mesh, so the
function covers all nine pairings with one call.

The test is exact: it produces neither false negatives nor false positives,
and \code{distance} is the true minimum distance rather than a
vertex-sampled approximation.
}
\details{
\code{x} is indexed once into a uniform spatial grid and \code{y} is
streamed against it, so put the larger or repeatedly-reused geometry in
\code{x} and the geometry you want per-element answers about in \code{y}.

Several chains share one matrix and are delimited by rows of \code{NA}; any
row that is not fully finite is treated as a separator. This lets a whole
bundle of streamlines be passed as a single matrix:

\preformatted{
  rbind(
    c(0, 0, 0), c(1, 0, 0), c(2, 0, 0),   # first streamline
    c(NA, NA, NA),                        # separator
    c(0, 5, 0), c(1, 5, 0)                # second streamline
  )
}

Those separators also define the unit that \code{early_stop} works on: it
stops once per group, so a bundle of streamlines yields at most one hit per
streamline.

When \code{mode_y = 'segments'}, row \code{i} of the result describes the
segment running from row \code{i} to row \code{i + 1}.

Both geometries must already share one coordinate space. Surface
coordinates, volume \verb{IJK} indices, and scanner coordinates are all
different spaces, and no transform is applied here.

\code{include_interior} relies on ray casting and therefore needs \code{x}
to be watertight with coherently oriented faces; see
\code{\link{vcg_fix_defects}} to repair a surface that is not.

Multi-threading follows \code{\link{ravetools_threads}}. The interior test
always runs single-threaded.
}
\section{Coercing Surface Inputs}{

The surface objects are converted to \code{'mesh3d'} object before
applying further calculations.

When \code{surface} is a surface \pkg{ieegio} object, the returned
\code{mesh3d$vb} contains vertices that have been left-multiplied by
\code{surface$geometry$transforms[[1]]} (the first transform stored in the
geometry, typically the \code{ScannerAnat} or voxel-to-world transform).

\strong{Breaking change:} Earlier versions (before 0.2.6) of \pkg{ravetools}
returned the raw \code{surface$geometry$vertices} without applying any
transform, so downstream code often multiplied by
\code{surface$geometry$transforms[[1]]} (or an equivalent) manually before
working in world space. Such code will now \emph{double}
apply the transform and produce incorrect coordinates. If you previously
applied a transform from \code{surface$geometry$transforms} by hand after
calling a \pkg{ravetools} mesh function on an \code{'ieegio_surface'},
remove that manual step.

Surfaces with an empty or missing \code{geometry$transforms} list (for
example, surfaces produced by \pkg{ieegio}'s \code{volume_to_surface},
which stores an identity transform) are unaffected.

If \code{geometry$transforms} contains multiple transforms targeting
different coordinate spaces, only the first one is used. Callers that need
a specific target space should select and apply that transform themselves
before calling \pkg{ravetools} mesh functions.
}

\examples{

library(ravetools)

# A spherical region of interest
roi <- vcg_sphere()

# Two streamlines in one matrix, separated by an NA row: the first passes
# through the sphere, the second stays well clear of it
streamlines <- rbind(
  cbind(seq(-3, 3, by = 0.5), 0, 0),
  c(NA, NA, NA),
  cbind(seq(-3, 3, by = 0.5), 5, 0)
)

result <- vcg_detect_collision(
  x = roi,
  y = streamlines,
  mode_y = "segments",
  radius = 0.1
)

# Which segments touch the sphere, and how close do they get?
data.frame(
  hit = result$hit,
  distance = round(result$distance, 4)
)

# A point cloud against the same region, asking only for proximity
points <- rbind(c(0, 0, 0), c(1.05, 0, 0), c(10, 10, 10))
vcg_detect_collision(roi, points, radius = 0.1)$hit

# The centre of the sphere is far from its surface, so it only counts as a
# collision when the interior is included
vcg_detect_collision(roi, rbind(c(0, 0, 0)), radius = 0.1)$hit
vcg_detect_collision(roi, rbind(c(0, 0, 0)), radius = 0.1,
                     include_interior = TRUE)$hit

}
