Skip to content

Commit

Permalink
add isoverts fn
Browse files Browse the repository at this point in the history
  • Loading branch information
mpadge committed Sep 9, 2019
1 parent 3979ea0 commit 422790f
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 10 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export(dodgr_full_cycles)
export(dodgr_fundamental_cycles)
export(dodgr_isochrones)
export(dodgr_isodists)
export(dodgr_isoverts)
export(dodgr_paths)
export(dodgr_sample)
export(dodgr_sflines_to_poly)
Expand Down
84 changes: 81 additions & 3 deletions R/iso.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,20 @@ dodgr_isodists <- function (graph, from = NULL, dlim = NULL, heap = 'BHeap')
dat <- iso_pre (graph, from, heap)

d <- rcpp_get_iso (dat$graph, dat$vert_map, dat$from_index$index,
dlim, dat$heap)
# verts inside the isohull are flagged with -1, and are removed here:
d [d < 0] <- NA
sort (dlim), dat$heap)

if (!is.null (dat$from_index$id))
rownames (d) <- dat$from_index$id
else
rownames (d) <- dat$vert_map$vert
colnames (d) <- dat$vert_map$vert

# verts ON isohulls are flagged with negative values at isodistance;
# terminal verts are also negative at their specified distance; all other
# points inside any hulls are positive. The latter are removed here:
d [d >= 0] <- NA
d <- -d # convert negative-flagged iso-values to positive

return (dmat_to_pts (d, dat$from_index$id, dat$v, dlim))
}

Expand Down Expand Up @@ -132,6 +136,76 @@ dodgr_isochrones <- function (graph, from = NULL, tlim = NULL, heap = 'BHeap')
return (res)
}

#' dodgr_isoverts
#'
#' Calculate isodistance or isochrone contours from specified points, and return
#' lists of all network vertices contained within the contours. Function is
#' fully vectorized to calculate accept vectors of central points and vectors
#' defining multiple isochrone thresholds. Provide one or more `dlim` values for
#' isodistances, or one or more `tlim` values for isochrones.
#'
#' @inheritParams dodgr_isodists
#'
#' @param from Vector or matrix of points **from** which isodistances or
#' isochrones are to be calculated.
#' @param tlim Vector of desired limits of isochrones in seconds
#' @return A single `data.frame` of vertex IDs, with columns denoting the `from`
#' points and `tlim` value(s). The isochrones are given as `id` values and
#' associated coordinates of the series of points from each `from` point at the
#' specified isochrone times.
#'
#' @export
#' @examples
#' \dontrun{
#' # Use osmdata package to extract 'SC'-format data:
#' library (osmdata)
#' dat <- opq ("hampi india") %>%
#' add_osm_feature (key = "highway") %>%
#' osmdata_sc ()
#' graph <- weight_streetnet (dat)
#' from <- sample (graph$from_id, size = 100)
#' tlim <- c (5, 10, 20, 30, 60) * 60 # times in seconds
#' x <- dodgr_isoverts (graph, from = from, tlim)
#' }
dodgr_isoverts <- function (graph, from = NULL, dlim = NULL, tlim = NULL,
heap = 'BHeap')
{
if (!methods::is (graph, "dodgr_streetnet_sc"))
stop ("isochrones can only be calculated from SC-class networks ",
"generated by osmdata_sc.")
if (!is.null (dlim) & !is.null (tlim))
stop ("Only one of dlim or tlim can be provided")

if (!is.null (tlim))
{
graph$d_weighted <- graph$time_weighted
graph$d <- graph$time
dlim <- tlim
}

dat <- iso_pre (graph, from, heap)

d <- rcpp_get_iso (dat$graph, dat$vert_map, dat$from_index$index,
sort (dlim), dat$heap)
index <- which (!is.na (d))

if (!is.null (dat$from_index$id))
rownames (d) <- dat$from_index$id
else
rownames (d) <- dat$vert_map$vert
colnames (d) <- dat$vert_map$vert

# convert d-values to the *next highest* specified dlim value. breaks need
# to start < 0 to include 0 in lowest class
breaks <- c (-0.001, dlim)
na_index <- which (!is.na (d))
f <- cut (d [na_index], breaks = breaks)
index <- match (f, attr (f, "levels"))
d [na_index] <- breaks [-1] [index]

return (dmat_to_pts (d, dat$from_index$id, dat$v, dlim))
}

# convert distance matrix with values equal to various isodistances into list of
# lists of points ordered around the central points
dmat_to_pts <- function (d, from, v, dlim)
Expand All @@ -143,6 +217,10 @@ dmat_to_pts <- function (d, from, v, dlim)
o <- v [match (from [i], v$id), ]
pts [[i]] <- lapply (dlim, function (j) {
res <- pt_names [which (d [i, ] == j)]
# Then any additional terminal vertices
index <- which (!d [i, ] %in% dlim &
d [i, ] < j)
res <- c (res, pt_names [index])
res <- v [match (res, v$id), ]
if (nrow (res) > 0)
{
Expand Down
2 changes: 1 addition & 1 deletion man/match_pts_to_graph.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 20 additions & 4 deletions src/run_sp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,32 @@ struct OneIso : public RcppParallel::Worker

pathfinder->DijkstraLimit (d, w, prev, from_i, dlimit_max);

// Get the set of terminal vertices.
std::set <int> terminal_verts;
for (auto j: prev)
if (w [j] > INFINITE_INT && w [j] < dlimit_max)
{
if (prev [j] < INFINITE_INT)
{
terminal_verts.erase (j);
terminal_verts.emplace (prev [j]);
}
}


for (size_t j = 0; j < nverts; j++)
{
if (prev [j] < INFINITE_INT && w [j] < INFINITE_DOUBLE)
if (terminal_verts.find (j) != terminal_verts.end ())
{
dout (i, j) = -w [j]; // Flag terminal verts with -d
} else if (prev [j] < INFINITE_INT && w [j] < dlimit_max)
{
for (auto k: dlimit)
{
if (w [j] > k && w [prev [j]] < k)
dout (i, prev [j]) = k;
else if (w [j] < k)
dout (i, j) = -1.0; // flag verts within isohull
dout (i, prev [j]) = -k; // flag isohull verts with -k
else
dout (i, j) = w [j]; // distance of other internal verts
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/testthat/test-iso.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test_that("isodists", {
# some points may give no iso countours, so the following 2 may
# not always be equal:
expect_true ((npts - length (unique (d$from))) >= 0)
expect_true (length (unique (d$dlim)) == length (dlim))
expect_true (length (unique (d$dlim)) <= length (dlim))
})

test_that ("errors", {
Expand Down Expand Up @@ -57,5 +57,5 @@ test_that("isochrones", {
# some points may give no iso countours, so the following 2 may
# not always be equal:
expect_true ((npts - length (unique (x$from))) >= 0)
expect_true (length (unique (x$tlim)) == length (tlim))
expect_true (length (unique (x$tlim)) <= length (tlim))
})

0 comments on commit 422790f

Please sign in to comment.