Skip to content

Commit af83666

Browse files
authored
Merge pull request #44 from FluvialGeomorph/pkgdown
Added cross section line direction check and reverse functions
2 parents 480e04f + f812231 commit af83666

25 files changed

+726
-28
lines changed

NAMESPACE

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,16 @@ export(planform)
4545
export(planform_dimensions)
4646
export(reach_rhg_graph)
4747
export(sf2csv)
48+
export(sf_line_end_point)
49+
export(sf_line_reverse)
50+
export(sf_point_attributes)
4851
export(shear_stress)
4952
export(slope_sinuosity)
53+
export(start_left)
5054
export(stream_power)
5155
export(table_xs_dimensions)
5256
export(xs2pts)
57+
export(xs_bearing)
5358
export(xs_compare_plot_L1)
5459
export(xs_compare_plot_L2)
5560
export(xs_dimensions)
@@ -63,6 +68,7 @@ export(xs_metrics_plot_L3)
6368
export(xs_plot)
6469
export(xs_profile_plot)
6570
export(xs_regional_metrics)
71+
export(xs_upstream)
6672
importFrom(Metrics,mae)
6773
importFrom(Metrics,rmse)
6874
importFrom(RegionalCurve,RHG)
@@ -73,7 +79,9 @@ importFrom(dplyr,"%>%")
7379
importFrom(dplyr,.data)
7480
importFrom(dplyr,across)
7581
importFrom(dplyr,arrange)
82+
importFrom(dplyr,bind_cols)
7683
importFrom(dplyr,bind_rows)
84+
importFrom(dplyr,case_when)
7785
importFrom(dplyr,distinct)
7886
importFrom(dplyr,filter)
7987
importFrom(dplyr,first)
@@ -83,6 +91,7 @@ importFrom(dplyr,last)
8391
importFrom(dplyr,lead)
8492
importFrom(dplyr,left_join)
8593
importFrom(dplyr,mutate)
94+
importFrom(dplyr,one_of)
8695
importFrom(dplyr,recode)
8796
importFrom(dplyr,right_join)
8897
importFrom(dplyr,select)
@@ -151,10 +160,15 @@ importFrom(scales,rescale)
151160
importFrom(sf,st_as_sf)
152161
importFrom(sf,st_as_sfc)
153162
importFrom(sf,st_bbox)
163+
importFrom(sf,st_cast)
164+
importFrom(sf,st_coordinates)
154165
importFrom(sf,st_crs)
155166
importFrom(sf,st_drop_geometry)
156167
importFrom(sf,st_geometry)
168+
importFrom(sf,st_line_sample)
157169
importFrom(sf,st_read)
170+
importFrom(sf,st_reverse)
171+
importFrom(sf,st_set_geometry)
158172
importFrom(sf,st_sf)
159173
importFrom(sf,st_transform)
160174
importFrom(stats,aggregate)
@@ -173,6 +187,7 @@ importFrom(terra,terrain)
173187
importFrom(terra,vect)
174188
importFrom(terrainr,get_tiles)
175189
importFrom(testthat,expect_true)
190+
importFrom(tibble,as_tibble)
176191
importFrom(tidyr,gather)
177192
importFrom(tmap,opt_tm_text)
178193
importFrom(tmap,tm_add_legend)

R/sf_line_end_point.R

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#' Extract line end points
2+
#'
3+
#' @description Determines the requested line end and returns a new sf point
4+
#' object with x and y coordinate value attributes added. Also adds ReachName
5+
#' XS Seq attributes suitable for joining.
6+
#'
7+
#' @param line sf line object, The input line feature.
8+
#' be calculated.
9+
#' @param end character, Which end of the line? One of "start" or "end".
10+
#'
11+
#' @return sf point object with x and y coordinate value attributes
12+
#' @export
13+
#'
14+
#' @importFrom dplyr %>% mutate
15+
#' @importFrom sf st_cast st_line_sample st_as_sf
16+
#'
17+
sf_line_end_point <- function(line, end) {
18+
if(end == "start") {
19+
sample = 0 # special value for identifying line start
20+
field_names = c("x_start", "y_start")}
21+
if(end == "end") {
22+
sample = 1 # special code for identifying line end
23+
field_names = c("x_end", "y_end")}
24+
25+
end_point <- line %>%
26+
st_cast(., to = "LINESTRING", warn = FALSE, do_split = TRUE) %>%
27+
st_line_sample(., sample = sample) %>%
28+
st_as_sf() %>%
29+
st_cast(., to = "POINT") %>%
30+
mutate(ReachName = line$ReachName) %>%
31+
mutate(Seq = line$Seq) %>%
32+
# write attributes to sf object
33+
fluvgeo::sf_point_attributes(., field_names = field_names)
34+
}

R/sf_line_reverse.R

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#' Reverse line direction
2+
#'
3+
#' @description Reverses the directions of an sf object's lines.
4+
#'
5+
#' @param line_sf sf object of type MULTILINESTRING, LINESTRING
6+
#'
7+
#' @return sf object
8+
#' @export
9+
#'
10+
#' @importFrom sf st_cast st_geometry st_reverse st_set_geometry
11+
#'
12+
sf_line_reverse <- function(line_sf) {
13+
# convert to LINESTRING
14+
ls <- st_cast(line_sf, to = "LINESTRING", warn = FALSE)
15+
16+
# extract geometry
17+
ls_geom <- st_geometry(ls)
18+
19+
# reverse the LINESTRING geometry
20+
rev_ls_geom <- st_reverse(ls_geom)
21+
22+
# assign the reversed geometry back to the original sf object
23+
rev_line_sf <- st_set_geometry(line_sf, rev_ls_geom)
24+
25+
return(rev_line_sf)
26+
}

R/sf_point_attributes.R

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#' Calculate x and y coordinate values as new fields.
2+
#'
3+
#' @param points sf object of type POINT, The input point features.
4+
#' @param fieldnames character, Provide custom names for the coordinate
5+
#' fields to be created. Names must be provided in the
6+
#' sf Dimension order (i.e,, XY, XTM, XYZ, XYZM).
7+
#'
8+
#' @details based on jmlondon suggestion for an `sf_as_cols` function:
9+
#' [sf/issues/231](https://github.com/r-spatial/sf/issues/231)
10+
#'
11+
#' @return sf object of type POINT
12+
#' @export
13+
#'
14+
#' @importFrom sf st_geometry st_coordinates
15+
#' @importFrom tibble as_tibble
16+
#' @importFrom dplyr bind_cols
17+
#'
18+
sf_point_attributes <- function(points, field_names = c("X", "Y")) {
19+
stopifnot(inherits(points, "sf") &&
20+
inherits(sf::st_geometry(points), "sfc_POINT"))
21+
22+
coords <- sf::st_coordinates(points)
23+
coords <- tibble::as_tibble(coords)
24+
25+
# remove duplicate names between points and field_names
26+
points <- points[, !names(points) %in% field_names]
27+
28+
# assign field_names
29+
coords <- setNames(coords, field_names)
30+
dplyr::bind_cols(points, coords)
31+
}

R/start_left.R

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#' Does point C fall on the left side of the AB line?
2+
#'
3+
#' @description Returns TRUE if the point C fall on the left side of the AB
4+
#' line. Orientation of the AB line determines the left and right side (i.e,
5+
#' starting at point A looking toward point B). Used to answer the question:
6+
#' Is point C on the left of the AB line?
7+
#'
8+
#' @param a_x numeric, Point A x coordinate
9+
#' @param a_y numeric, Point A y coordinate
10+
#' @param b_x numeric, Point B x coordinate
11+
#' @param b_y numeric, Point B y coordinate
12+
#' @param c_x numeric, Point C x coordinate
13+
#' @param c_y numeric, Point C y coordinate
14+
#'
15+
#' @details Uses the cross product method. Taken from:
16+
#' [SO](https://stackoverflow.com/questions/1560492/how-to-tell-whether-a-point-is-to-the-right-or-left-side-of-a-line)
17+
#'
18+
#' @return logical
19+
#' @export
20+
#'
21+
start_left <- function(a_x, a_y, b_x, b_y, c_x, c_y) {
22+
cp <- (b_x - a_x)*(c_y - a_y)-(b_y - a_y)*(c_x - a_x)
23+
return(cp > 0)
24+
}

R/xs_bearing.R

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#' Cross Section Bearing
2+
#'
3+
#' @description Calculate the flow direction bearing of the cross section.
4+
#'
5+
#' @export
6+
#' @param cross_section sf; A cross section lines feature class.
7+
#'
8+
#' @return cross_section sf object with a new field bearing
9+
#'
10+
#' @importFrom dplyr mutate case_when
11+
#'
12+
xs_bearing <- function(cross_section) {
13+
# Check data structure
14+
check_cross_section(cross_section, step = "assign_ids")
15+
16+
xs_crs <- st_crs(cross_section)
17+
xs_update <- xs_upstream(cross_section)
18+
19+
# Calculate bearings
20+
xs_dims <- xs_update %>%
21+
# https://math.stackexchange.com/questions/1596513/find-the-bearing-angle-between-two-points-in-a-2d-space
22+
mutate(x_diff = x_end - x_start) %>%
23+
mutate(y_diff = y_end - y_start) %>%
24+
mutate(xs_bearing_rad = atan2(y_diff, x_diff)) %>%
25+
mutate(xs_bearing_rad_pos = case_when(
26+
xs_bearing_rad < 0 ~ xs_bearing_rad + (2 * pi),
27+
xs_bearing_rad >= 0 ~ xs_bearing_rad)) %>%
28+
mutate(xs_bearing_deg = round(xs_bearing_rad_pos * (180/pi))) %>%
29+
mutate(flow_dir = xs_bearing_deg - 90)
30+
31+
return(xs_dims)
32+
}

R/xs_upstream.R

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#' Calculate upstream cross section
2+
#'
3+
#' @description Calculates the upstream cross section coordinates, updates
4+
#' cross section end points, reverses incorrectly digitized cross sections.
5+
#'
6+
#' @param cross_section sf line object, The cross section feature.
7+
#'
8+
#' @return sf line object
9+
#' @export
10+
#'
11+
#' @importFrom dplyr %>% arrange select one_of left_join mutate lead last
12+
#' filter
13+
#' @importFrom sf st_drop_geometry
14+
#'
15+
xs_upstream <- function(cross_section) {
16+
# Calculate xs start/end points
17+
xs_start <- sf_line_end_point(cross_section, end = "start")
18+
xs_end <- sf_line_end_point(cross_section, end = "end")
19+
20+
xs_update <- cross_section %>%
21+
arrange(Seq) %>%
22+
select(-one_of("x_start", "y_start", "x_end", "y_end",
23+
"from_measure", "to_measure", "ReachName")) %>%
24+
left_join(y = st_drop_geometry(xs_start), by = "Seq") %>%
25+
select(-one_of("ReachName")) %>%
26+
left_join(y = st_drop_geometry(xs_end), by = "Seq") %>%
27+
28+
# get next upstream flowline point
29+
mutate(upstream_x = lead(x = POINT_X, n = 1,
30+
default = last(.$POINT_X))) %>%
31+
mutate(upstream_y = lead(x = POINT_Y, n = 1,
32+
default = last(.$POINT_Y))) %>%
33+
34+
# determine if the xs start point is on the left descending bank
35+
mutate(start_left = start_left(upstream_x, upstream_y,
36+
POINT_X, POINT_Y,
37+
x_start, y_start))
38+
# Assure XS's digitized beginning on the left descending bank
39+
# XS's that begin on the left descending bank
40+
xs_left <- xs_update %>%
41+
filter(start_left == TRUE) %>%
42+
mutate(fixed_start = start_left(upstream_x, upstream_y,
43+
POINT_X, POINT_Y,
44+
x_start, y_start))
45+
# XS's that do not begin on the left descending bank; need to be flipped
46+
xs_right <- xs_update %>%
47+
filter(start_left == FALSE) %>%
48+
sf_line_reverse()
49+
50+
# update XS start and end points of the backward XS's
51+
xs_start <- sf_line_end_point(xs_right, end = "start")
52+
xs_end <- sf_line_end_point(xs_right, end = "end")
53+
54+
# check that the reverse works
55+
xs_right_rev <- xs_right %>%
56+
select(-one_of("x_start", "y_start", "x_end", "y_end", "ReachName")) %>%
57+
left_join(y = st_drop_geometry(xs_start), by = "Seq") %>%
58+
select(-one_of("ReachName")) %>%
59+
left_join(y = st_drop_geometry(xs_end), by = "Seq") %>%
60+
mutate(fixed_start = start_left(upstream_x, upstream_y,
61+
POINT_X, POINT_Y,
62+
x_start, y_start))
63+
# combine
64+
xs_fixed <- bind_rows(xs_left, xs_right_rev) %>%
65+
arrange(Seq)
66+
67+
return(xs_fixed)
68+
}

README.Rmd

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,37 +28,45 @@ ArcGIS toolbox](https://github.com/FluvialGeomorph/FluvialGeomorph). The Fluvial
2828
* Produce reports of stream channel and planform dimensions
2929
* Tools for choosing a bankfull elevation for ungaged streams
3030

31-
<img src="man/figures/HDQLO-03_h120.jpg" width=125 align="right" />
32-
3331
## Funding
32+
33+
<img src="man/figures/chl.png" width=125 align="right" />
34+
3435
Funding for development and maintenance of FluvialGeomorph has been provided by the following US Army Corps of Engineers (USACE) programs:
3536

36-
* [Ecosystem Management and Restoration Research Program (EMRRP)](https://emrrp.el.erdc.dren.mil).
37+
* [Flood and Coastal Risk Management](https://www.erdc.usace.army.mil/Locations/CHL/Flood-Coastal-Risk-Management/)
38+
* [Ecosystem Management and Restoration Research Program (EMRRP)](https://emrrp.el.erdc.dren.mil)
3739
* [Regional Sediment Management Program (RSM)](https://rsm.usace.army.mil/)
3840
* [Mississippi River Geomorphology and Potamology Program (MRG&P)](https://www.mvd.usace.army.mil/Missions/Mississippi-River-Science-Technology/MS-River-Geomorphology-Potamology/)
3941
* [Flood Risk Management Program (FRM)](https://www.iwr.usace.army.mil/Missions/Flood-Risk-Management/Flood-Risk-Management-Program/)
4042
* [Engineering With Nature (EWN)](https://ewn.el.erdc.dren.mil/)
4143

42-
<img src="man/figures/EWN_200.png" height=75 align="right" />
43-
<img src="man/figures/SilverJackets_200.png" height=75 align="right" />
44-
<img src="man/figures/FRMP_200.png" height=75 align="right" />
45-
<img src="man/figures/MRG&P_300.png" height=75 align="right" />
46-
<img src="man/figures/RSM_200.png" height=75 align="right" />
47-
<img src="man/figures/EMRRP_logo_200.png" height=75 align="right" />
44+
<p float="left">
45+
<img src="man/figures/chl.png" height=75 />
46+
<img src="man/figures/EMRRP_logo_200.png" height=75 />
47+
<img src="man/figures/RSM_200.png" height=75 />
48+
<img src="man/figures/MRG&P_300.png" height=75 />
49+
<img src="man/figures/FRMP_200.png" height=75 />
50+
<img src="man/figures/SilverJackets_200.png" height=75 />
51+
<img src="man/figures/EWN_200.png" height=75 />
52+
</p>
4853

4954
## Latest Updates
5055
Check out the [NEWS](NEWS.md) for details on the latest updates.
5156

5257
## Authors
5358

59+
* Christopher Haring, Fluvial Geomorphologist/Research Physical Scientist, U.S. Army Corps of Engineers
60+
<div itemscope itemtype="https://schema.org/Person"><a itemprop="sameAs" content="https://orcid.org/0009-0004-3834-9811" href="https://orcid.org/0009-0004-3834-9811" target="orcid.widget" rel="me noopener noreferrer" style="vertical-align:top;"><img src="https://orcid.org/sites/default/files/images/orcid_16x16.png" alt="ORCID iD icon" style="width:1em;margin-right:.5em;"/>https://orcid.org/0009-0004-3834-9811</a></div>
61+
5462
* Michael Dougherty, Geographer, U.S. Army Corps of Engineers
5563
<div itemscope itemtype="https://schema.org/Person"><a itemprop="sameAs" content="https://orcid.org/0000-0002-1465-5927" href="https://orcid.org/0000-0002-1465-5927" target="orcid.widget" rel="me noopener noreferrer" style="vertical-align:top;"><img src="https://orcid.org/sites/default/files/images/orcid_16x16.png" style="width:1em;margin-right:.5em;" alt="ORCID iD icon">https://orcid.org/0000-0002-1465-5927</a></div>
56-
* Christopher Haring, Fluvial Geomorphologist/Research Physical Scientist, U.S. Army Corps of Engineers
64+
5765
* Barrie Chileen Martinez, Geographer, U.S. Army Corps of Engineers
5866
<div itemscope itemtype="https://schema.org/Person"><a itemprop="sameAs" content="https://orcid.org/0000-0002-6960-8167" href="https://orcid.org/0000-0002-6960-8167" target="orcid.widget" rel="me noopener noreferrer" style="vertical-align:top;"><img src="https://orcid.org/sites/default/files/images/orcid_16x16.png" style="width:1em;margin-right:.5em;" alt="ORCID iD icon">https://orcid.org/0000-0002-6960-8167</a></div>
5967

6068
## Install
61-
To install the `fluvgeo` package, install from GitHub using the `devtools` package:
69+
To install the `fluvgeo` package, install from GitHub using the `remotes` package:
6270

6371
```{r install, eval=FALSE}
6472
remotes::install_github(repo = "FluvialGeomorph/fluvgeo@*release")

0 commit comments

Comments
 (0)