The following example shows how to work with data following the NHDPlusV2 schema.

# https://github.com/usgs-r/nhdplusTools
library(nhdplusTools)
#> USGS Support Package: https://owi.usgs.gov/R/packages.html#support
# https://github.com/tidyverse/dplyr
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
# https://github.com/r-spatial/sf
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1

library(hygeo)

sample_data <- system.file("gpkg/nhdplus_subset.gpkg", package = "hygeo")

plot_nhdplus(outlets = list(8895396),
             nhdplus_data = sample_data,
             overwrite = FALSE,
             plot_config = list(basin = list(border = NA),
                                outlets = list(default = list(col = NA))),
             cachedir = tempdir(check = TRUE))
#> Zoom: 14
#> Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
#> Audotdetect projection: assuming Google Mercator (epsg 3857)

fline <- read_sf(sample_data, "NHDFlowline_Network") %>%
  align_nhdplus_names() %>%
  filter(COMID %in% get_UT(., 8895396))

catchment <- read_sf(sample_data, "CatchmentSP") %>%
  align_nhdplus_names() %>%
  filter(FEATUREID %in% fline$COMID)

nexus <- get_nexus(fline)

plot(st_transform(st_geometry(catchment), 3857), add = TRUE)
plot(st_transform(st_geometry(nexus), 3857), add = TRUE)

Given the flowpaths, catchments, and nexuses, we can generate topology edge lists and data representations. The nexuses are outlet points along flowpaths in this case. Waterbodies are 1:1 with flowpath catchment realizations in this example but the data model will support 1:n or n:1 waterbody:catchment relationships.

catchment_prefix <- "catchment_"
nexus_prefix <- "nexus_"
waterbody_prefix <- "flowpath_"

(catchment_edge_list <- get_catchment_edges(fline, 
                                            catchment_prefix = catchment_prefix, 
                                            nexus_prefix = nexus_prefix))
#> # A tibble: 7 x 2
#>   ID                toID             
#>   <chr>             <chr>            
#> 1 catchment_8895442 nexus_250031932  
#> 2 catchment_8895520 nexus_250031930  
#> 3 catchment_8895396 nexus_250031903  
#> 4 catchment_8895402 nexus_250031930  
#> 5 nexus_250031932   catchment_8895402
#> 6 nexus_250031930   catchment_8895396
#> 7 nexus_250031903   catchment_0

(waterbody_edge_list <- get_waterbody_edge_list(fline, waterbody_prefix = waterbody_prefix))
#> Warning in prepare_nhdplus(fline, 0, 0, 0, FALSE, warn = FALSE): Got NHDPlus
#> data without a Terminal catchment. Attempting to find it.
#> # A tibble: 4 x 2
#>   ID               toID            
#>   <chr>            <chr>           
#> 1 flowpath_8895442 flowpath_8895402
#> 2 flowpath_8895520 flowpath_8895396
#> 3 flowpath_8895396 flowpath_0      
#> 4 flowpath_8895402 flowpath_8895396

(catchment_data <- get_catchment_data(catchment, catchment_edge_list))
#> Simple feature collection with 4 features and 3 fields
#> geometry type:  MULTIPOLYGON
#> dimension:      XY
#> bbox:           xmin: -79.16293 ymin: 35.97214 xmax: -79.11032 ymax: 35.99623
#> geographic CRS: WGS 84
#> # A tibble: 4 x 4
#>   ID         area_sqkm                                            geom toID     
#>   <chr>          <dbl>                              <MULTIPOLYGON [°]> <chr>    
#> 1 catchment~      1.86 (((-79.15822 35.98449, -79.15997 35.98514, -79~ nexus_25~
#> 2 catchment~      1.28 (((-79.13297 35.97544, -79.13245 35.9787, -79.~ nexus_25~
#> 3 catchment~      2.12 (((-79.13297 35.97544, -79.13369 35.97596, -79~ nexus_25~
#> 4 catchment~      1.77 (((-79.11932 35.98001, -79.12077 35.98198, -79~ nexus_25~

(flowpath_data <- get_flowpath_data(fline, catchment_edge_list) %>%
    mutate(realized_catchment = gsub(waterbody_prefix, 
                                     catchment_prefix, ID)))
#> Simple feature collection with 4 features and 6 fields
#> geometry type:  MULTILINESTRING
#> dimension:      XYZ
#> bbox:           xmin: -79.16244 ymin: 35.97413 xmax: -79.11841 ymax: 35.99613
#> z_range:        zmin: 0 zmax: 0
#> geographic CRS: WGS 84
#> # A tibble: 4 x 7
#>   ID    length_km slope_percent main_id                      geom toID 
#> * <chr>     <dbl>         <dbl>   <dbl>     <MULTILINESTRING [°]> <chr>
#> 1 catc~      2.78       0.0163   2.50e8 Z ((-79.16244 35.98999 0~ nexu~
#> 2 catc~      1.78       0.00903  2.50e8 Z ((-79.13053 35.97413 0~ nexu~
#> 3 catc~      1.22       0.00424  2.50e8 Z ((-79.12653 35.9883 0,~ nexu~
#> 4 catc~      1.20       0.00652  2.50e8 Z ((-79.13963 35.98956 0~ nexu~
#> # ... with 1 more variable: realized_catchment <chr>

(nexus_data <- get_nexus_data(nexus, catchment_edge_list))
#> Simple feature collection with 3 features and 2 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: -79.13963 ymin: 35.9883 xmax: -79.11841 ymax: 35.99613
#> geographic CRS: WGS 84
#> # A tibble: 3 x 3
#>   ID                          geometry toID             
#>   <chr>                    <POINT [°]> <chr>            
#> 1 nexus_250031932 (-79.13963 35.98956) catchment_8895402
#> 2 nexus_250031930  (-79.12653 35.9883) catchment_8895396
#> 3 nexus_250031903 (-79.11841 35.99613) catchment_0

The outputs can be rendered into csv or json:

hygeo_list <- list(catchment = catchment_data, 
                   flowpath = flowpath_data, 
                   nexus = nexus_data,
                   catchment_edges = catchment_edge_list,
                   waterbody_edges = waterbody_edge_list)

class(hygeo_list) <- "hygeo"

temp_path <- file.path(tempdir(check = TRUE), "hygeo")
dir.create(temp_path, recursive = TRUE, showWarnings = FALSE)

temp_path <- write_hygeo(hygeo_list, out_path = temp_path, overwrite = TRUE)

(hygeo_list_read <- read_hygeo(temp_path))
#> $catchment
#> Simple feature collection with 4 features and 3 fields
#> geometry type:  MULTIPOLYGON
#> dimension:      XY
#> bbox:           xmin: -79.16293 ymin: 35.97214 xmax: -79.11032 ymax: 35.99623
#> geographic CRS: WGS 84
#> # A tibble: 4 x 4
#>   id         area_sqkm toid                                             geometry
#>   <chr>          <dbl> <chr>                                  <MULTIPOLYGON [°]>
#> 1 catchment~      1.86 nexus_250~ (((-79.15822 35.98449, -79.15997 35.98514, -7~
#> 2 catchment~      1.28 nexus_250~ (((-79.13297 35.97544, -79.13245 35.9787, -79~
#> 3 catchment~      2.12 nexus_250~ (((-79.13297 35.97544, -79.13369 35.97596, -7~
#> 4 catchment~      1.77 nexus_250~ (((-79.11932 35.98001, -79.12077 35.98198, -7~
#> 
#> $flowpath
#> Simple feature collection with 4 features and 6 fields
#> geometry type:  MULTILINESTRING
#> dimension:      XY
#> bbox:           xmin: -79.16244 ymin: 35.97413 xmax: -79.11841 ymax: 35.99613
#> geographic CRS: WGS 84
#> # A tibble: 4 x 7
#>   id    length_km slope_percent main_id toid  realized_catchm~
#>   <chr>     <dbl>         <dbl>   <dbl> <chr> <chr>           
#> 1 catc~      2.78       0.0163   2.50e8 nexu~ catchment_88954~
#> 2 catc~      1.78       0.00903  2.50e8 nexu~ catchment_88955~
#> 3 catc~      1.22       0.00424  2.50e8 nexu~ catchment_88953~
#> 4 catc~      1.20       0.00652  2.50e8 nexu~ catchment_88954~
#> # ... with 1 more variable: geometry <MULTILINESTRING [°]>
#> 
#> $nexus
#> Simple feature collection with 3 features and 2 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: -79.13963 ymin: 35.9883 xmax: -79.11841 ymax: 35.99613
#> geographic CRS: WGS 84
#> # A tibble: 3 x 3
#>   id              toid                          geometry
#>   <chr>           <chr>                      <POINT [°]>
#> 1 nexus_250031932 catchment_8895402 (-79.13963 35.98956)
#> 2 nexus_250031930 catchment_8895396  (-79.12653 35.9883)
#> 3 nexus_250031903 catchment_0       (-79.11841 35.99613)
#> 
#> $catchment_edges
#>                  id              toid
#> 1 catchment_8895442   nexus_250031932
#> 2 catchment_8895520   nexus_250031930
#> 3 catchment_8895396   nexus_250031903
#> 4 catchment_8895402   nexus_250031930
#> 5   nexus_250031932 catchment_8895402
#> 6   nexus_250031930 catchment_8895396
#> 7   nexus_250031903       catchment_0
#> 
#> $waterbody_edges
#>                 id             toid
#> 1 flowpath_8895442 flowpath_8895402
#> 2 flowpath_8895520 flowpath_8895396
#> 3 flowpath_8895396       flowpath_0
#> 4 flowpath_8895402 flowpath_8895396
#> 
#> attr(,"class")
#> [1] "hygeo"