Skip to content

Commit

Permalink
Merge pull request #12 from anirudhgovind/dev
Browse files Browse the repository at this point in the history
add: st_orientation
  • Loading branch information
anirudhgovind authored Apr 19, 2024
2 parents 06074f4 + 1ce5e4d commit fc38135
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 0 deletions.
41 changes: 41 additions & 0 deletions R/convenience_functions.R
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,47 @@ euclideanDistance <- function (pointA, pointB) {
sqrt(((pointA[, 1] - pointB[, 1]) ^ 2) + ((pointA[, 2] - pointB[, 2]) ^ 2))
}

#' Calculate the angle between a line and the horizontal given two
#' coordinate locations.
#'
#' @param x1 the x-coordinate of the first point.
#' @param y1 the y-coordinate of the first point.
#' @param x2 the x-coordinate of the second point.
#' @param y2 the y-coordinate of the second point.
#'
#' @return The angle between the line and the horizontal.
#' @keywords internal
#' @noRd
calc_angle <- function(x1,
y1,
x2,
y2) {

# Get the height

height <- abs(y2 - y1)

# Get the base

base <- abs(x2 - x1)

# Get the angle

angle <- round(rad_to_deg(atan(height/base)),
3)
}

#' Convert an angle in radians to degrees.
#'
#' @param radians the angle in radians.
#'
#' @return The angle in degrees.
#' @keywords internal
#' @noRd
rad_to_deg <- function(radians) {
return(radians * 180 / pi)
}

#' Add a unique identifier to each observation.
#'
#' @param x a `sf` object with geometries.
Expand Down
114 changes: 114 additions & 0 deletions R/st_nest_coordinates.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#' Nest `POINT` geometries to `LINESTRING`
#'
#' @param x a `df` containing coordinates in columns named `x1`, `y1`, `x2`,
#' and `y2`.
#'
#' @return A `sf` object containing `LINESTRING` geometries **without** a CRS.
#' @export
#'
#' @examples
st_nest_coordinates <- function(x) {

# Housekeeping

x1 <- y1 <- x2 <- y2 <- NULL

# If cols are present in the data run the following:

if (any(c("x1", "y1", "x2", "y2") %in% colnames(x))) {
# Keep other columns

x_other <- x |>
dplyr::select(-x1,
-y1,
-x2,
-y2)

# Convert to an sf object

x_nested <- sf::st_sf(data.frame(geometry = sf::st_as_sfc(
paste0("LINESTRING (",
x$x1,
" ",
x$y1,
", ",
x$x2,
" ",
x$y2,
")")
)))

# Add the other columns back in

x_nested <- cbind(x_nested,
x_other)

return(x_nested)

} else {
stop("Coordinates must be provided in columns x1, y1, x2, and y2.")
}

}


#' Unnest `POINT` geometries from `LINESTRINGS`
#'
#' @param x a `sf` object containing `LINESTRING` geometries.
#'
#' @return A `df` where each row contains the `x1`, `y1`, `x2`, and `y2`
#' coordinates for a line.
#'
#' @export
#'
#' @examples
st_unnest_coordinates <- function(x) {

# Housekeeping

id <- temp_id <- x1 <- y1 <- x2 <- y2 <- NULL

# Check types and convert to linestrings.

x_lines <- process_linestrings(x)

# Keep other columns

x_other <- x |>
add_unique_id() |>
sf::st_set_geometry(NULL)

# Get coordinates

x_coords <- as.data.frame(sf::st_coordinates(x_lines))

# Set colnames

colnames(x_coords) <- c("x1", "y1", "id")

# Group by id. Mutate x2 and y2 as lead values.
# This should result in a number of NAs.
# Drop them.

# Add x2 and y2

x_coords <- x_coords |>
dplyr::group_by(id) |>
dplyr::mutate(x2 = dplyr::lead(x1,
n = 1,
order_by = id),
y2 = dplyr::lead(y1,
n = 1,
order_by = id)) |>
dplyr::ungroup() |>
stats::na.omit()

# Add other columns

x_coords <- dplyr::left_join(x_coords,
x_other,
by = c("id" = "temp_id")) |>
dplyr::select(-id)

return(x_coords)
}
56 changes: 56 additions & 0 deletions R/st_orientation.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#' Determine the interior angle between a `LINESTRING` and the horizontal.
#'
#' @param x a `sf` object containing `LINESTRING` geometries.
#'
#' @return An unnested `sf` object containing the orientation of each line
#' segment making up the original `LINESTRING` geometries.
#' @export
#'
#' @examples
st_orientation <- function(x) {

# Housekeeping

id <- x1 <- y1 <- x2 <- y2 <- NULL

# Keep track of the crs

x_crs <- sf::st_crs(x)

# The extract coordinates function adds columns titled x1, y1, x2, and y2
# It then computes the angles of each line string.

x_orientation <- st_unnest_coordinates(x) |>
dplyr::mutate(
orientation = dplyr::case_when(
x2 > x1 & y2 < y1 ~ -calc_angle(x1,
y1,
x2,
y2),
x2 < x1 &
y2 > y1 ~ -calc_angle(x1,
y1,
x2,
y2),
y2 == y1 ~ 0,
x2 == x1 ~ 90,
TRUE ~ calc_angle(x1,
y1,
x2,
y2)
)
)

# Nest the columns to form line strings

x_orientation <- st_nest_coordinates(x_orientation)

# Add the crs back in

sf::st_crs(x_orientation) <- x_crs

return(x_orientation)

}


1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ reference:
contents:
- add_unique_id
- st_merge_spatialunits
- st_orientation
- st_survey_spatialunits

- subtitle: Datasets
Expand Down

0 comments on commit fc38135

Please sign in to comment.