Title: | Fast, Dependency-Free Geodesic Distance Calculations |
---|---|
Description: | Dependency-free, ultra fast calculation of geodesic distances. Includes the reference nanometre-accuracy geodesic distances of Karney (2013) <doi:10.1007/s00190-012-0578-z>, as used by the 'sf' package, as well as Haversine and Vincenty distances. Default distance measure is the "Mapbox cheap ruler" which is generally more accurate than Haversine or Vincenty for distances out to a few hundred kilometres, and is considerably faster. The main function accepts one or two inputs in almost any generic rectangular form, and returns either matrices of pairwise distances, or vectors of sequential distances. |
Authors: | Mark Padgham [aut, cre], Michael D. Sumner [aut], Charles F.F Karney [cph] (Original author of included code for geodesic distances) |
Maintainer: | Mark Padgham <[email protected]> |
License: | MIT + file LICENSE |
Version: | 0.1.0 |
Built: | 2024-08-28 05:20:51 UTC |
Source: | https://github.com/hypertidy/geodist |
Dependency-free, ultra fast calculation of geodesic distances. Includes the reference nanometre-accuracy geodesic distances of Karney (2013) doi:10.1007/s00190-012-0578-z, as used by the 'sf' package, as well as Haversine and Vincenty distances. Default distance measure is the "Mapbox cheap ruler" which is generally more accurate than Haversine or Vincenty for distances out to a few hundred kilometres, and is considerably faster. The main function accepts one or two inputs in almost any generic rectangular form, and returns either matrices of pairwise distances, or vectors of sequential distances.
Convert one or two rectangular objects containing lon-lat coordinates into vector or matrix of geodesic distances in metres.
geodist( x, y, paired = FALSE, sequential = FALSE, pad = FALSE, measure = "cheap", quiet = FALSE )
geodist( x, y, paired = FALSE, sequential = FALSE, pad = FALSE, measure = "cheap", quiet = FALSE )
x |
Rectangular object (matrix, |
y |
Optional second object which, if passed, results in distances
calculated between each object in |
paired |
If |
sequential |
If |
pad |
If |
measure |
One of "haversine" "vincenty", "geodesic", or "cheap" specifying desired method of geodesic distance calculation; see Notes. |
quiet |
If |
If only x
passed and sequential = FALSE
, a square
symmetric matrix containing distances between all items in x
; If only
x
passed and sequential = TRUE
, a vector of sequential
distances between rows of x
; otherwise if y
is passed, a matrix
of nrow(x)
rows and nrow(y)
columns. All return values are
distances in metres.
measure = "cheap"
denotes the mapbox cheap ruler
https://github.com/mapbox/cheap-ruler-cpp; measure = "geodesic"
denotes the very accurate geodesic methods given in Karney (2013)
"Algorithms for geodesics" J Geod 87:43-55, and as provided by the
'st_dist()' function from the sf package.
Maintainer: Mark Padgham [email protected]
Authors:
Michael D. Sumner
Other contributors:
Charles F.F Karney (Original author of included code for geodesic distances) [copyright holder]
Useful links:
Report bugs at https://github.com/hypertidy/geodist/issues
n <- 50 # Default "cheap" distance measure is only accurate for short distances: x <- cbind (runif (n, -0.1, 0.1), runif (n, -0.1, 0.1)) y <- cbind (runif (2 * n, -0.1, 0.1), runif (2 * n, -0.1, 0.1)) colnames (x) <- colnames (y) <- c ("x", "y") d0 <- geodist (x) # A 50-by-50 matrix d1 <- geodist (x, y) # A 50-by-100 matrix d2 <- geodist (x, sequential = TRUE) # Vector of length 49 d2 <- geodist (x, sequential = TRUE, pad = TRUE) # Vector of length 50 d0_2 <- geodist (x, measure = "geodesic") # nanometre-accurate version of d0 # Input data can also be 'data.frame' objects: xy <- data.frame (x = runif (n, -0.1, 0.1), y = runif (n, -0.1, 0.1)) d <- geodist (xy)
n <- 50 # Default "cheap" distance measure is only accurate for short distances: x <- cbind (runif (n, -0.1, 0.1), runif (n, -0.1, 0.1)) y <- cbind (runif (2 * n, -0.1, 0.1), runif (2 * n, -0.1, 0.1)) colnames (x) <- colnames (y) <- c ("x", "y") d0 <- geodist (x) # A 50-by-50 matrix d1 <- geodist (x, y) # A 50-by-100 matrix d2 <- geodist (x, sequential = TRUE) # Vector of length 49 d2 <- geodist (x, sequential = TRUE, pad = TRUE) # Vector of length 50 d0_2 <- geodist (x, measure = "geodesic") # nanometre-accurate version of d0 # Input data can also be 'data.frame' objects: xy <- data.frame (x = runif (n, -0.1, 0.1), y = runif (n, -0.1, 0.1)) d <- geodist (xy)
Benchmark errors for different geodist measures
geodist_benchmark(lat = 0, d = 1, n = 100L)
geodist_benchmark(lat = 0, d = 1, n = 100L)
lat |
Central latitude where errors should be measured |
d |
Distance in metres over which errors should be measured |
n |
Number of random values used to generate estimates |
A 'data.frame' with three columns respectively comparing the accuracy of the [Haversine, Vincenty, cheap] metrics against geodesic measures in both absolute and relative terms (as two rows of the table).
geodist_benchmark (0.0, 1.0, 100L)
geodist_benchmark (0.0, 1.0, 100L)
Convert two rectangular objects containing lon-lat coordinates into an index vector of the elements in the second matrix corresponding to the minimal distance to each element of the first matrix.
geodist_min(x, y, measure = "cheap", quiet = FALSE)
geodist_min(x, y, measure = "cheap", quiet = FALSE)
x |
Rectangular object (matrix, |
y |
Second rectangular object to be search for minimal distance to each row in the first object. |
measure |
One of "haversine" "vincenty", "geodesic", or "cheap" specifying desired method of geodesic distance calculation; see Notes. |
quiet |
If |
A integer index vector indexing elements of 'y' corresponding to minimal distances to each element of 'x'. The length of this vector is equal to the number of rows in 'x'.
measure = "cheap"
denotes the mapbox cheap ruler
https://github.com/mapbox/cheap-ruler-cpp; measure = "geodesic"
denotes the very accurate geodesic methods given in Karney (2013)
"Algorithms for geodesics" J Geod 87:43-55, and as provided by the
'st_dist()' function from the sf package.
n <- 50 # Default "cheap" distance measure is only accurate for short distances: x <- cbind (runif (n, -0.1, 0.1), runif (n, -0.1, 0.1)) y <- cbind (runif (2 * n, -0.1, 0.1), runif (2 * n, -0.1, 0.1)) colnames (x) <- colnames (y) <- c ("x", "y") index <- geodist_min (x, y, measure = "Haversine") # 'index' is a vector of 50 values indexing elements of `y` corresponding to # minimal distances to each element of `x`. It is exactly the same as the # value returned by these lines: d0 <- geodist (x, y, measure = "Haversine") index0 <- apply (d0, 1, which.min) identical (index, index0)
n <- 50 # Default "cheap" distance measure is only accurate for short distances: x <- cbind (runif (n, -0.1, 0.1), runif (n, -0.1, 0.1)) y <- cbind (runif (2 * n, -0.1, 0.1), runif (2 * n, -0.1, 0.1)) colnames (x) <- colnames (y) <- c ("x", "y") index <- geodist_min (x, y, measure = "Haversine") # 'index' is a vector of 50 values indexing elements of `y` corresponding to # minimal distances to each element of `x`. It is exactly the same as the # value returned by these lines: d0 <- geodist (x, y, measure = "Haversine") index0 <- apply (d0, 1, which.min) identical (index, index0)
An alternative interface to the main geodist function that directly accepts inputs as individual vectors of coordinates, rather than the matrix or 'data.frame' inputs of the main function. This interface is provided for cases where computational efficiency is important, and will generally provide faster results than the main function.
geodist_vec( x1, y1, x2, y2, paired = FALSE, sequential = FALSE, pad = FALSE, measure = "cheap", quiet = FALSE )
geodist_vec( x1, y1, x2, y2, paired = FALSE, sequential = FALSE, pad = FALSE, measure = "cheap", quiet = FALSE )
x1 |
Numeric vector of longitude coordinates |
y1 |
Numeric vector of latitude coordinates |
x2 |
Optional second numeric vector of longitude coordinates |
y2 |
Optional second numeric vector of latitude coordinates |
paired |
If |
sequential |
If |
pad |
If |
measure |
One of "haversine" "vincenty", "geodesic", or "cheap" specifying desired method of geodesic distance calculation; see Notes. |
quiet |
If |
If only (x1, y1)
are passed and sequential = FALSE
, a
square symmetric matrix containing distances between all items in (x1,
y1)
; If only (x1, y1)
are passed and sequential = TRUE
, a
vector of sequential distances between matching elements of (x1, y1)
;
otherwise if (x2, y2)
are passed, a matrix of lenght(x1) ==
length(y1)
rows and length(x2) == length(y2)
columns.
measure = "cheap"
denotes the mapbox cheap ruler
https://github.com/mapbox/cheap-ruler-cpp; measure = "geodesic"
denotes the very accurate geodesic methods given in Karney (2013)
"Algorithms for geodesics" J Geod 87:43-55, and as provided by the
'st_dist()' function from the sf package.
n <- 50 # Default "cheap" distance measure is only accurate for short distances: x1 <- -1 + 2 * runif (n, -0.1, 0.1) y1 <- -1 + 2 * runif (n, -0.1, 0.1) d0 <- geodist_vec (x1, y1) # A 50-by-50 matrix d2 <- geodist_vec (x1, y1, sequential = TRUE) # Vector of length 49 d2 <- geodist_vec (x1, y1, sequential = TRUE, pad = TRUE) # length 50 x2 <- -10 + 20 * runif (2 * n, -0.1, 0.1) y2 <- -10 + 20 * runif (2 * n, -0.1, 0.1) d1 <- geodist_vec (x1, y1, x2, y2) # A 50-by-100 matrix
n <- 50 # Default "cheap" distance measure is only accurate for short distances: x1 <- -1 + 2 * runif (n, -0.1, 0.1) y1 <- -1 + 2 * runif (n, -0.1, 0.1) d0 <- geodist_vec (x1, y1) # A 50-by-50 matrix d2 <- geodist_vec (x1, y1, sequential = TRUE) # Vector of length 49 d2 <- geodist_vec (x1, y1, sequential = TRUE, pad = TRUE) # length 50 x2 <- -10 + 20 * runif (2 * n, -0.1, 0.1) y2 <- -10 + 20 * runif (2 * n, -0.1, 0.1) d1 <- geodist_vec (x1, y1, x2, y2) # A 50-by-100 matrix
Calculate range of distances (min-max) between all points in one or two rectangular objects containing lon-lat coordinates.
georange(x, y, sequential = FALSE, measure = "cheap")
georange(x, y, sequential = FALSE, measure = "cheap")
x |
Rectangular object (matrix, |
y |
Optional second object which, if passed, results in distances
calculated between each object in |
sequential |
If |
measure |
One of "haversine" "vincenty", "geodesic", or "cheap" specifying desired method of geodesic distance calculation; see Notes. |
A named vector of two numeric values: minimum and maximum, giving the respective distances in metres.
measure = "cheap"
denotes the mapbox cheap ruler
https://github.com/mapbox/cheap-ruler-cpp; measure = "geodesic"
denotes the very accurate geodesic methods given in Karney (2013)
"Algorithms for geodesics" J Geod 87:43-55, and as provided by the
'st_dist()' function from the sf package.
n <- 50 x <- cbind (-10 + 20 * runif (n), -10 + 20 * runif (n)) y <- cbind (-10 + 20 * runif (2 * n), -10 + 20 * runif (2 * n)) colnames (x) <- colnames (y) <- c ("x", "y") # All of the following returns vector of two values: minimum and maximum: d0 <- georange (x) d1 <- georange (x, y) d2 <- georange (x, sequential = TRUE) d0_2 <- georange (x, measure = "geodesic") # nanometre-accurate version of d0
n <- 50 x <- cbind (-10 + 20 * runif (n), -10 + 20 * runif (n)) y <- cbind (-10 + 20 * runif (2 * n), -10 + 20 * runif (2 * n)) colnames (x) <- colnames (y) <- c ("x", "y") # All of the following returns vector of two values: minimum and maximum: d0 <- georange (x) d1 <- georange (x, y) d2 <- georange (x, sequential = TRUE) d0_2 <- georange (x, measure = "geodesic") # nanometre-accurate version of d0