I managed to implement the approach suggested by @Spacedman to calculate slope. I am leaving the code here as a possible starter to calculate aspect. (the data called up here from the sample is a dummy and doesn't fit the names used)
I borrowed extensively from: https://www.r-spatial.org/r/2019/09/26/spatial-networks.html
if(!"remotes" %in% installed.packages()) {
install.packages("remotes")
}
cran_pkgs = c(
#"sf",
"tidygraph",
"igraph",
"osmdata",
#"dplyr",
#"tibble",
#"ggplot2",
"units",
# "tmap",
#"rgrass7",
"link2GI",
"nabor"
)
remotes::install_cran(cran_pkgs)
library(sf)
library(tidygraph)
library(igraph)
library(dplyr)
library(tibble)
library(ggplot2)
library(units)
library(tmap)
library(osmdata)
library(rgrass7)
library(link2GI)
library(nabor)
#for sample dataset taken from slopes package
if(!require(slopes)){install.packages("slopes")}
library(slopes)
data(dem_lisbon_raster)
data(lisbon_road_segments)
dem<-dem_lisbon_raster
stream_split<-lisbon_road_segments%>% select(OBJECTID) %>% rename(edgeID=OBJECTID)
#assign identifier to each stream segment
stream_split <- stream_split %>%
mutate(edgeID = c(1:n()))
#extract start and end nodes
nodes<-stream_split %>%st_coordinates() %>% as_tibble %>%
rename(edgeID=L1) %>% group_by(edgeID)%>%slice(c(1, n())) %>%
ungroup() %>%
mutate(start_end = rep(c('start', 'end'), times = n()/2))
#assign a unique index to each node (duplicate coordinates get the same index)
nodes <- nodes %>%
mutate(xy = paste(.$X, .$Y)) %>%
mutate(nodeID = group_indices(., factor(xy, levels = unique(xy)))) %>%
select(-xy)
#convert nodes to sf object
nodes_sf <- nodes %>%
distinct(nodeID, .keep_all = TRUE) %>%
select(-c(edgeID, start_end)) %>%
st_as_sf(coords = c('X', 'Y')) %>%
st_set_crs(st_crs(stream_split))
#extract elevation at each node
nodes_sf$elev<-raster::extract(dem, nodes_sf)
##add notes to each edge
source_nodes <- nodes %>%
filter(start_end == 'start') %>%
pull(nodeID)
target_nodes <- nodes %>%
filter(start_end == 'end') %>%
pull(nodeID)
stream_split = stream_split %>%
mutate(from = source_nodes, to = target_nodes)
#convert elevations to tibble
nodes.tib<-as_tibble(nodes_sf)%>%select(-geometry)
#add start and end elevations to segments
stream_split<-inner_join(stream_split, nodes.tib, by=c("from"="nodeID")) %>% rename(elev_start=elev)
stream_split<-inner_join(stream_split, nodes.tib, by=c("to"="nodeID")) %>% rename(elev_end=elev)
stream_split$length<-st_length(stream_split)#caculate segment length
stream_split$slope<-(stream_split$elev_end-stream_split$elev_start)/stream_split$length
However, I do not get the same result as when I use the slopes
package.
stream_split$slope_package = slope_raster(stream_split, e = dem)
sqrt(dx^2+dy^2)/dz
, and aspect byatan2(dx, dy)
where thed
s are differences in coordinates.slopes
was so straightforward! Hours of searching culminating in a two-minute function. @Spacedman Could you provide more detail on determining the aspect?