# R/ArcIntersection.R In laurasoul/dispeRse: Models For Paleobiogeography

#### Documented in ArcIntersection

```#' Point(s) at which two arcs intersect on a sphere
#'
#' Given two arcs returns point(s) at which they intersect on a sphere.
#' @param longitude_1 Decimalised longitude of first point on first arc.
#' @param latitude_1 Decimalised latitude of first point on first arc.
#' @param longitude_2 Decimalised longitude of second point on first arc.
#' @param latitude_2 Decimalised latitude of second point on first arc.
#' @param longitude_3 Decimalised longitude of first point on second arc.
#' @param latitude_3 Decimalised latitude of first point on second arc.
#' @param longitude_4 Decimalised longitude of second point on second arc.
#' @param latitude_4 Decimalised latitude of second point on second arc.
#' @param type Vector to indicate if elements are arcs or Great Circles.
#' @return Matrix of longitude-latitude points at which intersection(s) occur.
#' @details Assumes shortest distance between points describes arc. Can define Great Circle-arc intersection with \code{type} option.
#' @author Graeme T. Lloyd \email{graemetlloyd@@gmail.com}
#' @export
#' @examples
#' longitude_1 <- stats::runif(1, -180, 180)
#' longitude_2 <- stats::runif(1, -180, 180)
#' longitude_3 <- stats::runif(1, -180, 180)
#' longitude_4 <- stats::runif(1, -180, 180)
#' latitude_1 <- stats::runif(1, -90, 90)
#' latitude_2 <- stats::runif(1, -90, 90)
#' latitude_3 <- stats::runif(1, -90, 90)
#' latitude_4 <- stats::runif(1, -90, 90)
#' ArcIntersection(longitude_1, latitude_1, longitude_2, latitude_2,
#'   longitude_3, latitude_3, longitude_4, latitude_4, EarthRad = 6367.4447)

ArcIntersection <- function(longitude_1, latitude_1, longitude_2, latitude_2, longitude_3, latitude_3, longitude_4, latitude_4, type = c("arc", "arc"), EarthRad = 6367.4447) {

# Check type is of correct length:
if(length(type) != 2) stop("ERROR: Type must be of length two.")

# Check elements of type are of the correct type:
if(sum((type == "GC") + (type == "arc")) != 2) stop("ERROR: Elements of type must be either \"arc\" or \"GC\" only.")

# Get intersection points of the two Great Circles described by the arcs:
res <- GreatCircleIntersection(longitude_1, latitude_1, longitude_2, latitude_2, longitude_3, latitude_3, longitude_4, latitude_4, EarthRad = EarthRad)

# Only proceed if at least one element is an arc (otherwise res already shows GC-GC intersection pointsand no changes needed):
if(length(sort(match("arc", type)))) {

# Calculate distance from first point on first arc to first intersection point:
distance_to_first_intersection_1 <- GreatCircleDistanceFromLongLat(longitude_1, latitude_1, res[, "lon1"], res[, "lat1"], EarthRad = EarthRad, Warn = FALSE)

# Calculate distance from first point on first arc to second intersection point:
distance_to_second_intersection_1 <- GreatCircleDistanceFromLongLat(longitude_1, latitude_1, res[, "lon2"], res[, "lat2"], EarthRad = EarthRad, Warn = FALSE)

# Calculate distance from first point on second arc to first intersection point:
distance_to_first_intersection_2 <- GreatCircleDistanceFromLongLat(longitude_3, latitude_3, res[, "lon1"], res[, "lat1"], EarthRad = EarthRad, Warn = FALSE)

# Calculate distance from first point on second arc to second intersection point:
distance_to_second_intersection_2 <- GreatCircleDistanceFromLongLat(longitude_3, latitude_3, res[, "lon2"], res[, "lat2"], EarthRad = EarthRad, Warn = FALSE)

# If first element is an arc:
if(type[1] == "arc") {

# Set distance as smallest Great Circle distance between the two points:
distance_to_other_point_1 <- GreatCircleDistanceFromLongLat(longitude_1, latitude_1, longitude_2, latitude_2, EarthRad = EarthRad, Warn = FALSE)

# If first element is a Great Circle:
} else {

# Set distance as full circumference of planet:
distance_to_other_point_1 <- 2 * pi * EarthRad

}

# If second element is an arc:
if(type[2] == "arc") {

# Set distance as smallest Great Circle distance between the two points:
distance_to_other_point_2 <- GreatCircleDistanceFromLongLat(longitude_3, latitude_3, longitude_4, latitude_4, EarthRad = EarthRad, Warn = FALSE)

# If second element is a Great Circle:
} else {

# Set distance as full circumference of planet:
distance_to_other_point_2 <- 2 * pi * EarthRad

}

# Create empty delete rows vector (will store intersection points outside of arcs):
delete.rows <- vector(mode="numeric")

# Make result into matrix:
res <- matrix(res, ncol=2, byrow=TRUE, dimnames=list(c(), c("Longitude", "Latitude")))

# Case if first point is not an actual intersection:
if(!(distance_to_other_point_1 >= distance_to_first_intersection_1 && distance_to_other_point_2 >= distance_to_first_intersection_2)) delete.rows <- c(delete.rows, 1)

# Case if second point is not an actual intersection:
if(!(distance_to_other_point_1 >= distance_to_second_intersection_1 && distance_to_other_point_2 >= distance_to_second_intersection_2)) delete.rows <- c(delete.rows, 2)

# Remove intersections outside of arcs:
res <- res[-delete.rows, ]

# Ensure res is still a matrix:
if(!is.matrix(res)) res <- matrix(res, ncol=2, byrow=TRUE, dimnames=list(c(), c("Longitude", "Latitude")))

# Case if a Great Circle-Great Circle intersection:
} else {

# Make result into matrix:
res <- matrix(res, ncol=2, byrow=TRUE, dimnames=list(c(), c("Longitude", "Latitude")))

}

# Return matrix of zero, one, or two rows (depending on number of intersection points):
return(res)

}
```
laurasoul/dispeRse documentation built on May 25, 2021, 4:50 a.m.