Returns the subpath between two positions on one aggregate
flowpath. An aggregate flowpath is the run of flowlines that share an
aggregate_id and link end to end, such as an identified mainstem. A
subpath is the part of it between two positions, each given as a flowline
id and id_measure. The result lists the flowlines of the subpath from
downstream to upstream, with the two end flowlines cut at the positions'
measures. This is how to pull a stretch of river, such as the river between
a gage and a confluence, out of any network that carries aggregate_id.
Both positions must be on the same aggregate flowpath. A stretch that crosses a confluence of two mainstems takes two calls, one for each mainstem, split at the confluence.
Support for cross-aggregate_id paths may be included in a future release.
Usage
get_subpath(from, to, x, snap_m = 0)
# S3 method for class 'data.frame'
get_subpath(from, to, x, snap_m = 0)
# S3 method for class 'hy'
get_subpath(from, to, x, snap_m = 0)
# S3 method for class 'hy_topo'
get_subpath(from, to, x, snap_m = 0)
# S3 method for class 'hy_node'
get_subpath(from, to, x, snap_m = 0)Arguments
- from
data.frame. One end of each subpath, with
idandid_measure; the ends are unordered. An optionalline_idcolumn labels the output; without it the row number is used.- to
data.frame. The other end, row-aligned with
from.- x
hy_topoorhy_node, or a data.frame coercible withhy(). Carriesaggregate_idandlength_km. Atopo_sortcolumn keeps building the aggregate flowpath axis cheap; without it a full topological sort is run.- snap_m
numeric. An end within this many meters of a flowline boundary snaps to it. Default 0.
Value
data.frame with line_id, segment_order (1 at the downstream
end), id, id_from_measure, id_to_measure, length_km and reversed,
one or more rows per subpath, plus piece geometry when x is sf and
lwgeom is installed.
Details
from and to can be given in either order. Each position is converted to
kilometers along the aggregate flowpath axis (the aggregate flowpath
measured from its downstream end in x), and the subpath covers the
kilometer span between the two. Pieces always come back downstream to
upstream. If a from position is upstream of its to, reversed is
TRUE on every row for that pair.
snap_m keeps small offsets from cutting slivers. An end within snap_m
meters of a flowline boundary moves to that boundary before cutting, so a node a
few meters inside a flowline does not leave a sliver, and two source
flowlines that share a node share one cut. Zero-length pieces are dropped.
If both ends land on one point after snapping, the result for that
line_id is a single row with an NA id and zero length_km.
When x is sf and lwgeom is installed, each piece's geometry is cut
with lwgeom::st_linesubstring() and attached.
Measures
id_measure is an interpolative measure along a single flowline: a percent
of the line from its outlet, 0 at the outlet (downstream end) and 100 at the
inlet (upstream, head end).
Examples
g <- sf::read_sf(system.file("extdata/new_hope.gpkg", package = "hydroloom"))
csv <- utils::read.csv(
system.file("extdata/new_hope_mainstems.csv", package = "hydroloom"))
g$mainstemid <- csv$mainstem_uri[match(g$COMID, csv$comid)]
g$REACHCODE <- NULL
g <- sf::st_cast(g, "LINESTRING", warn = FALSE)
net <- add_toids(hy(g))
# flowlines of one mainstem, bottom and top by topo_sort
nh <- "https://geoconnex.us/ref/mainstems/2408056"
on_nh <- net[!is.na(net$aggregate_id) & net$aggregate_id == nh, ]
from <- data.frame(id = on_nh$id[which.min(on_nh$topo_sort)], id_measure = 0)
to <- data.frame(id = on_nh$id[which.max(on_nh$topo_sort)], id_measure = 100)
get_subpath(from, to, net)
#> Simple feature collection with 75 features and 7 fields
#> Geometry type: LINESTRING
#> Dimension: XY
#> Bounding box: xmin: 1496152 ymin: 1551922 xmax: 1516513 ymax: 1573365
#> Projected CRS: +proj=aea +lat_0=23 +lon_0=-96 +lat_1=29.5 +lat_2=45.5 +x_0=0 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
#> # A tibble: 75 × 8
#> line_id segment_order id id_from_measure id_to_measure length_km reversed
#> <int> <int> <int> <dbl> <dbl> <dbl> <lgl>
#> 1 1 1 8.90e6 0 100 1.39 FALSE
#> 2 1 2 8.89e6 0 100 0.0450 FALSE
#> 3 1 3 8.89e6 0 100 1.07 FALSE
#> 4 1 4 8.89e6 0 100 0.507 FALSE
#> 5 1 5 8.89e6 0 100 1.48 FALSE
#> 6 1 6 8.89e6 0 100 2.33 FALSE
#> 7 1 7 8.89e6 0 100 2.73 FALSE
#> 8 1 8 8.89e6 0 100 0.343 FALSE
#> 9 1 9 8.89e6 0 100 0.254 FALSE
#> 10 1 10 8.89e6 0 100 0.0340 FALSE
#> # ℹ 65 more rows
#> # ℹ 1 more variable: geometry <LINESTRING [m]>
