diff --git a/DESCRIPTION b/DESCRIPTION index aa28b6d74..ae613864c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: dodgr Title: Distances on Directed Graphs -Version: 0.2.14.084 +Version: 0.2.14.085 Authors@R: c( person("Mark", "Padgham", , "mark.padgham@email.com", role = c("aut", "cre")), person("Andreas", "Petutschnig", role = "aut"), diff --git a/NAMESPACE b/NAMESPACE index 67a27e906..e50034a3b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -42,7 +42,9 @@ export(dodgr_vertices) export(estimate_centrality_threshold) export(estimate_centrality_time) export(igraph_to_dodgr) +export(match_points_to_graph) export(match_points_to_verts) +export(match_pts_to_graph) export(match_pts_to_verts) export(merge_directed_graph) export(weight_railway) diff --git a/NEWS.md b/NEWS.md index 16a416d7b..e043d83ec 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,7 @@ ## Breaking changes: - `match_pts_to_graph()` renamed to `match_pts_to_verts()` +- New `match_pts_to_graph()` function matches to graph edges, using nearest perpendicular intersection (issue #103) ## Major changes: diff --git a/R/match-points.R b/R/match-points.R index 8b20b413f..3ac1c8c3d 100644 --- a/R/match-points.R +++ b/R/match-points.R @@ -90,3 +90,90 @@ match_points_to_verts <- function (verts, xy, connected = FALSE) { match_pts_to_verts (verts, xy, connected = connected) } + +#' match_pts_to_graph +#' +#' Match spatial points to the edges of a spatial graph, through finding the +#' edge with the closest perpendicular intersection. NOTE: Intersections are +#' calculated geometrically, and presume planar geometry. It is up to users of +#' projected geometrical data, such as those within a `dodgr_streetnet` object, +#' to ensure that either: (i) Data span an sufficiently small area that errors +#' from presuming planar geometry may be ignored; or (ii) Data are re-projected +#' to an equivalent planar geometry prior to calling this routine. +#' +#' @param graph A `dodgr` graph with spatial coordinates, such as a +#' `dodgr_streetnet` object. +#' @inheritParams match_pts_to_verts +#' +#' @return A vector index matching the `xy` coordinates to nearest edges. For +#' bi-directional edges, only one match is returned, and it is up to the user to +#' identify and suitably process matching edge pairs. +#' @family misc +#' @export +#' @examples +#' net <- weight_streetnet (hampi, wt_profile = "foot") +#' # Then generate some random points to match to graph +#' npts <- 10 +#' xy <- data.frame ( +#' x = min (verts$x) + runif (npts) * diff (range (verts$x)), +#' y = min (verts$y) + runif (npts) * diff (range (verts$y)) +#' ) +#' edges <- match_pts_to_graph (graph, xy) +#' graph [edges, ] # The edges of the graph closest to `xy` +match_pts_to_graph <- function (graph, xy, connected = FALSE) { + + if (!(is.matrix (xy) || is.data.frame (xy))) { + stop ("xy must be a matrix or data.frame") + } + if (!is (xy, "sf")) { + if (ncol (xy) != 2) { + stop ("xy must have only two columns") + } + } + + if (!is_graph_spatial (graph)) { + stop ("Points may only be matched to spatial graphs.") + } + + if (connected) { + graph <- graph [which (graph$component == 1), ] + } + + if (is (xy, "tbl")) { + xy <- data.frame (xy) + } + if (is (xy, "sf")) { + if (!"geometry" %in% names (xy)) { + stop ("xy has no sf geometry column") + } # nocov + if (!is (xy$geometry, "sfc_POINT")) { + stop ("xy$geometry must be a collection of sfc_POINT objects") + } + xy <- unlist (lapply (xy$geometry, as.numeric)) %>% + matrix (nrow = 2) %>% + t () + xy <- data.frame (x = xy [, 1], y = xy [, 2]) + } else { + xyi <- find_xy_col_simple (xy) + xy <- data.frame (x = xy [, xyi [1]], y = xy [, xyi [2]]) + } + + gr_cols <- dodgr_graph_cols (graph) + gr_cols <- unlist (gr_cols [which (!is.na (gr_cols))]) + graph <- graph [, gr_cols] + names (graph) <- names (gr_cols) + + # rcpp_points_index is 0-indexed, so ... + rcpp_points_to_edges_par (graph, xy) + 1L +} + +#' match_points_to_graph +#' +#' Alias for \link{match_pts_to_graph} +#' @inherit match_pts_to_graph +#' @family misc +#' @export +match_points_to_graph <- function (graph, xy, connected = FALSE) { + + match_pts_to_graph (graph, xy, connected = connected) +} diff --git a/codemeta.json b/codemeta.json index 1790a44f5..5409e7bd4 100644 --- a/codemeta.json +++ b/codemeta.json @@ -7,7 +7,7 @@ "codeRepository": "https://github.com/ATFutures/dodgr", "issueTracker": "https://github.com/ATFutures/dodgr/issues", "license": "https://spdx.org/licenses/GPL-3.0", - "version": "0.2.14.084", + "version": "0.2.14.085", "programmingLanguage": { "@type": "ComputerLanguage", "name": "R", diff --git a/man/compare_heaps.Rd b/man/compare_heaps.Rd index 6dc3ccac0..57f827798 100644 --- a/man/compare_heaps.Rd +++ b/man/compare_heaps.Rd @@ -45,7 +45,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/dodgr_flowmap.Rd b/man/dodgr_flowmap.Rd index 6e810628c..5df6521ef 100644 --- a/man/dodgr_flowmap.Rd +++ b/man/dodgr_flowmap.Rd @@ -49,7 +49,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/dodgr_full_cycles.Rd b/man/dodgr_full_cycles.Rd index e709b2866..56c11e873 100644 --- a/man/dodgr_full_cycles.Rd +++ b/man/dodgr_full_cycles.Rd @@ -46,7 +46,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/dodgr_fundamental_cycles.Rd b/man/dodgr_fundamental_cycles.Rd index 620bb5c97..8e7aa0dad 100644 --- a/man/dodgr_fundamental_cycles.Rd +++ b/man/dodgr_fundamental_cycles.Rd @@ -65,7 +65,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/dodgr_insert_vertex.Rd b/man/dodgr_insert_vertex.Rd index 994cef6d3..9d7718d49 100644 --- a/man/dodgr_insert_vertex.Rd +++ b/man/dodgr_insert_vertex.Rd @@ -50,7 +50,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/dodgr_sample.Rd b/man/dodgr_sample.Rd index e2c295145..8686d27ed 100644 --- a/man/dodgr_sample.Rd +++ b/man/dodgr_sample.Rd @@ -40,7 +40,9 @@ Other misc: \code{\link{dodgr_insert_vertex}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/dodgr_sflines_to_poly.Rd b/man/dodgr_sflines_to_poly.Rd index 0b6dd7280..67960e7c5 100644 --- a/man/dodgr_sflines_to_poly.Rd +++ b/man/dodgr_sflines_to_poly.Rd @@ -32,7 +32,9 @@ Other misc: \code{\link{dodgr_insert_vertex}()}, \code{\link{dodgr_sample}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/dodgr_vertices.Rd b/man/dodgr_vertices.Rd index 4f7a26ad0..d3c9c69fc 100644 --- a/man/dodgr_vertices.Rd +++ b/man/dodgr_vertices.Rd @@ -34,7 +34,9 @@ Other misc: \code{\link{dodgr_insert_vertex}()}, \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/match_points_to_graph.Rd b/man/match_points_to_graph.Rd new file mode 100644 index 000000000..8fbb28190 --- /dev/null +++ b/man/match_points_to_graph.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/match-points.R +\name{match_points_to_graph} +\alias{match_points_to_graph} +\title{match_points_to_graph} +\usage{ +match_points_to_graph(graph, xy, connected = FALSE) +} +\arguments{ +\item{graph}{A \code{dodgr} graph with spatial coordinates, such as a +\code{dodgr_streetnet} object.} + +\item{xy}{coordinates of points to be matched to the vertices, either as +matrix or \pkg{sf}-formatted \code{data.frame}.} + +\item{connected}{Should points be matched to the same (largest) connected +component of graph? If \code{FALSE} and these points are to be used for a +\code{dodgr} routing routine (\link{dodgr_dists}, \link{dodgr_paths}, or +\link{dodgr_flows_aggregate}), then results may not be returned if points are +not part of the same connected component. On the other hand, forcing them to +be part of the same connected component may decrease the spatial accuracy of +matching.} +} +\value{ +A vector index matching the \code{xy} coordinates to nearest edges. For +bi-directional edges, only one match is returned, and it is up to the user to +identify and suitably process matching edge pairs. +} +\description{ +Alias for \link{match_pts_to_graph} +} +\examples{ +net <- weight_streetnet (hampi, wt_profile = "foot") +# Then generate some random points to match to graph +npts <- 10 +xy <- data.frame ( + x = min (verts$x) + runif (npts) * diff (range (verts$x)), + y = min (verts$y) + runif (npts) * diff (range (verts$y)) +) +edges <- match_pts_to_graph (graph, xy) +graph [edges, ] # The edges of the graph closest to `xy` +} +\seealso{ +Other misc: +\code{\link{compare_heaps}()}, +\code{\link{dodgr_flowmap}()}, +\code{\link{dodgr_full_cycles}()}, +\code{\link{dodgr_fundamental_cycles}()}, +\code{\link{dodgr_insert_vertex}()}, +\code{\link{dodgr_sample}()}, +\code{\link{dodgr_sflines_to_poly}()}, +\code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, +\code{\link{match_pts_to_verts}()}, +\code{\link{merge_directed_graph}()}, +\code{\link{summary.dodgr_dists_categorical}()}, +\code{\link{write_dodgr_wt_profile}()} +} +\concept{misc} diff --git a/man/match_points_to_verts.Rd b/man/match_points_to_verts.Rd index 7ed47f89a..07024c3a5 100644 --- a/man/match_points_to_verts.Rd +++ b/man/match_points_to_verts.Rd @@ -51,6 +51,8 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, diff --git a/man/match_pts_to_graph.Rd b/man/match_pts_to_graph.Rd new file mode 100644 index 000000000..62fc404b0 --- /dev/null +++ b/man/match_pts_to_graph.Rd @@ -0,0 +1,66 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/match-points.R +\name{match_pts_to_graph} +\alias{match_pts_to_graph} +\title{match_pts_to_graph} +\usage{ +match_pts_to_graph(graph, xy, connected = FALSE) +} +\arguments{ +\item{graph}{A \code{dodgr} graph with spatial coordinates, such as a +\code{dodgr_streetnet} object.} + +\item{xy}{coordinates of points to be matched to the vertices, either as +matrix or \pkg{sf}-formatted \code{data.frame}.} + +\item{connected}{Should points be matched to the same (largest) connected +component of graph? If \code{FALSE} and these points are to be used for a +\code{dodgr} routing routine (\link{dodgr_dists}, \link{dodgr_paths}, or +\link{dodgr_flows_aggregate}), then results may not be returned if points are +not part of the same connected component. On the other hand, forcing them to +be part of the same connected component may decrease the spatial accuracy of +matching.} +} +\value{ +A vector index matching the \code{xy} coordinates to nearest edges. For +bi-directional edges, only one match is returned, and it is up to the user to +identify and suitably process matching edge pairs. +} +\description{ +Match spatial points to the edges of a spatial graph, through finding the +edge with the closest perpendicular intersection. NOTE: Intersections are +calculated geometrically, and presume planar geometry. It is up to users of +projected geometrical data, such as those within a \code{dodgr_streetnet} object, +to ensure that either: (i) Data span an sufficiently small area that errors +from presuming planar geometry may be ignored; or (ii) Data are re-projected +to an equivalent planar geometry prior to calling this routine. +} +\examples{ +net <- weight_streetnet (hampi, wt_profile = "foot") +# Then generate some random points to match to graph +npts <- 10 +xy <- data.frame ( + x = min (verts$x) + runif (npts) * diff (range (verts$x)), + y = min (verts$y) + runif (npts) * diff (range (verts$y)) +) +edges <- match_pts_to_graph (graph, xy) +graph [edges, ] # The edges of the graph closest to `xy` +} +\seealso{ +Other misc: +\code{\link{compare_heaps}()}, +\code{\link{dodgr_flowmap}()}, +\code{\link{dodgr_full_cycles}()}, +\code{\link{dodgr_fundamental_cycles}()}, +\code{\link{dodgr_insert_vertex}()}, +\code{\link{dodgr_sample}()}, +\code{\link{dodgr_sflines_to_poly}()}, +\code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, +\code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_verts}()}, +\code{\link{merge_directed_graph}()}, +\code{\link{summary.dodgr_dists_categorical}()}, +\code{\link{write_dodgr_wt_profile}()} +} +\concept{misc} diff --git a/man/match_pts_to_verts.Rd b/man/match_pts_to_verts.Rd index 548a91b7c..8f120f5c8 100644 --- a/man/match_pts_to_verts.Rd +++ b/man/match_pts_to_verts.Rd @@ -51,7 +51,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}, \code{\link{write_dodgr_wt_profile}()} diff --git a/man/merge_directed_graph.Rd b/man/merge_directed_graph.Rd index 20f18fa9a..8e00a0f4b 100644 --- a/man/merge_directed_graph.Rd +++ b/man/merge_directed_graph.Rd @@ -54,7 +54,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{summary.dodgr_dists_categorical}()}, \code{\link{write_dodgr_wt_profile}()} diff --git a/man/summary.dodgr_dists_categorical.Rd b/man/summary.dodgr_dists_categorical.Rd index 4d6df3a52..4b031c517 100644 --- a/man/summary.dodgr_dists_categorical.Rd +++ b/man/summary.dodgr_dists_categorical.Rd @@ -27,7 +27,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{write_dodgr_wt_profile}()} diff --git a/man/write_dodgr_wt_profile.Rd b/man/write_dodgr_wt_profile.Rd index 415702a2c..ccc60bd92 100644 --- a/man/write_dodgr_wt_profile.Rd +++ b/man/write_dodgr_wt_profile.Rd @@ -29,7 +29,9 @@ Other misc: \code{\link{dodgr_sample}()}, \code{\link{dodgr_sflines_to_poly}()}, \code{\link{dodgr_vertices}()}, +\code{\link{match_points_to_graph}()}, \code{\link{match_points_to_verts}()}, +\code{\link{match_pts_to_graph}()}, \code{\link{match_pts_to_verts}()}, \code{\link{merge_directed_graph}()}, \code{\link{summary.dodgr_dists_categorical}()}