Skip to content

Commit

Permalink
feat: added table_getDistanceFromTarget()
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathancallahan committed May 6, 2022
1 parent fc6d2f6 commit 70b39e8
Show file tree
Hide file tree
Showing 65 changed files with 552 additions and 114 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Type: Package
Package: MazamaLocationUtils
Version: 0.3.4
Version: 0.3.6
Title: Manage Spatial Metadata for Known Locations
Authors@R: c(
person("Jonathan", "Callahan", email="[email protected]", role=c("aut","cre")),
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export(table_addSingleLocation)
export(table_filterByDistance)
export(table_findAdjacentDistances)
export(table_findAdjacentLocations)
export(table_getDistanceFromTarget)
export(table_getLocationID)
export(table_getNearestDistance)
export(table_getNearestLocation)
Expand Down
10 changes: 10 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# MazamaLocationUtils 0.3.6

* Added `table_getDistanceFromTarget()` and edited the description of other
distance functions to make clear what each does.

# MazamaLocationUtils 0.3.5

* Removed `validateMazamaSpatialUtils()` test from `table_addCoreMetadata()` as
this function just adds empty columns and does not need any spatial data.

# MazamaLocationUtils 0.3.4

* Updated `table_addOpenCageInfo()` to handle address components that are
Expand Down
2 changes: 0 additions & 2 deletions R/table_addCoreMetadata.R
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ table_addCoreMetadata <- function(
locationTbl = NULL
) {

validateMazamaSpatialUtils()

# ----- Validate parameters --------------------------------------------------

MazamaLocationUtils::validateLocationTbl(locationTbl, locationOnly = TRUE)
Expand Down
106 changes: 106 additions & 0 deletions R/table_getDistanceFromTarget.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#' @rdname table_getDistanceFromTarget
#' @export
#' @importFrom MazamaCoreUtils stopIfNull
#' @importFrom rlang .data
#'
#' @title Return distances and directions from a target location to known locations
#'
#' @param locationTbl Tibble of known locations.
#' @param longitude Target longitude in decimal degrees E.
#' @param latitude Target latitude in decimal degrees N.
#' @param measure One of "haversine" "vincenty", "geodesic", or "cheap"
#' specifying desired method of geodesic distance calculation.
#'
#' @return Tibble of distances in meters and cardinal directions from a target location.
#'
#' @description Returns a tibble with the same number of rows as \code{locationTbl}
#' containing the distance and direction from the target location specified by
#' \code{longitude} and \code{latitude} to each known location found in
#' \code{locationTbl}.
#'
#' @note Only a single target location is allowed.
#'
#' @examples
#' library(MazamaLocationUtils)
#'
#' locationTbl <- get(data("wa_monitors_500"))
#'
#' locationTbl %>%
#' table_getDistanceFromTarget(
#' longitude = -117.3647,
#' latitude = 47.6725
#' ) %>%
#' dplyr::glimpse()
#'


table_getDistanceFromTarget <- function(
locationTbl = NULL,
longitude = NULL,
latitude = NULL,
measure = c("geodesic", "haversine", "vincenty", "cheap")
) {

# ----- Validate parameters --------------------------------------------------

MazamaLocationUtils::validateLocationTbl(locationTbl, locationOnly = TRUE)
MazamaLocationUtils::validateLonLat(longitude, latitude)
measure <- match.arg(measure)

if ( length(longitude) > 1 || length(latitude) > 1 )
stop("Only a single target location is allowed.")

# ----- Calculate distances --------------------------------------------------

distanceMatrix <-
geodist::geodist(
y = cbind(
"x" = longitude,
"y" = latitude
),
x = cbind(
"x" = locationTbl$longitude,
"y" = locationTbl$latitude
),
paired = FALSE,
sequential = FALSE,
pad = FALSE,
measure = measure
)

# NOTE: distanceMatrix is nrow(locationTbl) X 1

returnTbl <-
locationTbl %>%
dplyr::select(c("locationID")) %>%
dplyr::mutate(
distanceFromTarget = round(distanceMatrix[,1])
)

# ----- Add direction --------------------------------------------------------

# https://stackoverflow.com/questions/30794729/find-angle-from-two-points-formula

x1 <- longitude * pi/180
x2 <- locationTbl$longitude * pi/180
y1 <- latitude * pi/180
y2 <- locationTbl$latitude * pi/180

angle = atan2(y2 - y1, x2 - x1) * 180/pi

# NOTE: Mathematical angle is zero facing East and increases counter-clockwise
# NOTE: Cover everything between -180:180

returnTbl$directionFromTarget <-
cut(
angle,
breaks = c(-202.5, -157.5, -112.5, -67.5, -22.5, 22.5, 67.5, 112.5, 157.5, 202.5),
labels = c("W", "SW", "S", "SE", "E", "NE", "N", "NW", "W")
) %>%
as.character()

# ----- Return ---------------------------------------------------------------

return(returnTbl)

}
55 changes: 34 additions & 21 deletions R/table_getNearestDistance.R
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@

#' @title Return distances to nearest known locations
#' @description Returns distances between known locations in \code{locationTbl},
#' and a vector of target locations specified by \code{longitude} and \code{latitude}.
#' Only a single distance to the closest known location is returned for each
#' incoming target location. If no known location is found within
#' \code{distanceThreshold} meters for a particular
#' incoming location, that distance in the vector will be \code{NA}.
#' @rdname table_getNearestDistance
#' @export
#' @importFrom MazamaCoreUtils stopIfNull
#' @importFrom geodist geodist
#' @importFrom rlang .data
#'
#' @note The measure \code{"cheap"} may be used to speed things up depending on
#' the spatial scale being considered. Distances calculated with
#' \code{measure = "cheap"} will vary by a few meters compared with those
#' calculated using \code{measure = "geodesic"}.
#' @title Return distances to nearest known locations
#'
#' @param locationTbl Tibble of known locations.
#' @param longitude Vector of longitudes in decimal degrees E.
#' @param latitude Vector of latitudes in decimal degrees N.
#' @param longitude Vector of target longitudes in decimal degrees E.
#' @param latitude Vector of target latitudes in decimal degrees N.
#' @param distanceThreshold Distance in meters.
#' @param measure One of "haversine" "vincenty", "geodesic", or "cheap"
#' specifying desired method of geodesic distance calculation.
#'
#' @description Returns distances between target locations and the closest
#' location found in \code{locationTbl} (if any). Target locations are specified
#' with \code{longitude} and \code{latitude}.
#'
#' For each target location, only a single distance to the closest known location
#' is returned. If no known location is found within
#' \code{distanceThreshold}, the distance associated with that target location
#' will be \code{NA}. The length and order of resulting distances will match the
#' order of the incoming target locations.
#'
#' @section Use Case:
#' You may have a set of locations of interest for which you want to assess whether
#' any monitoring locations are nearby. In this case, the locations of interest
#' will provide \code{longitude} and \code{latitude} while \code{locationTbl}
#' will be the known location table associated with the monitoring locations.
#'
#' The resulting vector of distances will tell you the distance, for each
#' target location, to the nearst monitoring location.
#'
#' @note The measure \code{"cheap"} may be used to speed things up depending on
#' the spatial scale being considered. Distances calculated with
#' \code{measure = "cheap"} will vary by a few meters compared with those
#' calculated using \code{measure = "geodesic"}.
#'
#' See \code{geodist::\link[geodist:geodist]{geodist}} for details.
#'
#' @return Vector of distances from known locations.
#' @return Vector of closest distances between target locations and known locations.
#' @examples
#' library(MazamaLocationUtils)
#'
Expand All @@ -37,11 +55,6 @@
#' # Expanding the distanceThreshold will find one
#' table_getNearestDistance(locationTbl, lon, lat, distanceThreshold = 5000)
#'
#' @rdname table_getNearestDistance
#' @export
#' @importFrom MazamaCoreUtils stopIfNull
#' @importFrom geodist geodist
#' @importFrom rlang .data
table_getNearestDistance <- function(
locationTbl = NULL,
longitude = NULL,
Expand All @@ -66,7 +79,7 @@ table_getNearestDistance <- function(

# NOTE: For the case where the incoming longitude and latitude have many
# NOTE: duplicated locations (a "tidy" dataframe perhaps), we need to speed
# NOTE: things up by only calculating distance for unique locations and then
# NOTE: things up by only calculating distances for unique locations and then
# NOTE: merging with all incoming locations.

myTbl <- dplyr::tibble(longitude = longitude, latitude = latitude)
Expand Down
2 changes: 1 addition & 1 deletion docs/404.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/LICENSE-text.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions docs/articles/MazamaLocationUtils.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/articles/index.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/authors.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/index.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 17 additions & 1 deletion docs/news/index.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ pkgdown: 1.6.1
pkgdown_sha: ~
articles:
MazamaLocationUtils: MazamaLocationUtils.html
last_built: 2022-04-04T21:00Z
last_built: 2022-05-06T18:49Z

2 changes: 1 addition & 1 deletion docs/reference/LocationDataDir.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/reference/MazamaLocationUtils.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/reference/coreMetadataNames.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/reference/getAPIKey.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/reference/getLocationDataDir.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/reference/id_monitors_500.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 70b39e8

Please sign in to comment.