Skip to content

Commit

Permalink
updating examples and docs for get_haversine_distance and read_gpx
Browse files Browse the repository at this point in the history
  • Loading branch information
pegeler committed Dec 11, 2023
1 parent 8ffa6bf commit 4bbf8ce
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 85 deletions.
2 changes: 1 addition & 1 deletion R/package/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: eddington
Title: Compute a Cyclist's Eddington Number
Version: 4.1.1
Version: 4.1.2
Authors@R: c(
person('Paul', 'Egeler', email = 'paulegeler@gmail.com', role = c('aut','cre')),
person('Tashi', 'Reigle', role = 'ctb'))
Expand Down
25 changes: 16 additions & 9 deletions R/package/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
# eddington 4.1.2 (Release date: 2023-12-12)

Changes:

- Enhanced and fixed typos in examples.
- Changed API to `get_haversine_distance()`.

# eddington 4.1.1 (Release date: 2023-12-11)

Changes:

- Adding examples for `read_gpx` and `get_haversine_distance`.
- Adding examples for `read_gpx()` and `get_haversine_distance()`.

# eddington 4.1.0 (Release date: 2023-11-24)

Expand All @@ -18,11 +25,11 @@ Changes:
- Minimum R version is now 4.3.0 and requires compiler capable of C++17 standard.
- Full re-implementation of C++ code. As a result, memory usage will be reduced
for typical datasets.
- Introduction of `EddingtonModule` Rcpp module. This class maintains algorithm
- Introduction of `EddingtonModule()` Rcpp module. This class maintains algorithm
state, and so can be updated multiple times as new data comes in.
- Introduction of `Eddington` R6 class. This provides similar functionality to
the `EddingtonModule` Rcpp module. All methods are implemented in pure R. It
uses R's new `hashtab` data structure, which is experimental as of this
- Introduction of `Eddington()` R6 class. This provides similar functionality to
the `EddingtonModule()` Rcpp module. All methods are implemented in pure R. It
uses R's new `hashtab()` data structure, which is experimental as of this
package release.

# eddington 2.1.2 (Release date: 2020-03-24)
Expand Down Expand Up @@ -58,9 +65,9 @@ Changes:
Changes:

- R version of `Eddington_number` and c++ `E_fast` are now defunct.
- `E_num` is now the method for getting the single maximum Eddington number of a dataset.
- Added `E_sat` that checks to see if a dataset satisfies a certain Eddington number.
- Added `E_req` that determines the minimum number of rides to increment Eddington number.
- `E_num()` is now the method for getting the single maximum Eddington number of a dataset.
- Added `E_sat()` that checks to see if a dataset satisfies a certain Eddington number.
- Added `E_req()` that determines the minimum number of rides to increment Eddington number.

# eddington 0.1.1 (Release date: 2018-12-15)

Expand All @@ -72,7 +79,7 @@ Changes:

Changes:

- Added cumulative function, `E_cum`.
- Added cumulative function, `E_cum()`.

# eddington 0.0.0 (Release date: 2018-11-27)

Expand Down
4 changes: 2 additions & 2 deletions R/package/R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ E_next <- function(rides) {
.Call(`_eddington_E_next`, rides)
}

get_haversine_distance_ <- function(lat_1, long_1, lat_2, long_2, r) {
.Call(`_eddington_get_haversine_distance_`, lat_1, long_1, lat_2, long_2, r)
get_haversine_distance_ <- function(lat_1, lon_1, lat_2, lon_2, r) {
.Call(`_eddington_get_haversine_distance_`, lat_1, lon_1, lat_2, lon_2, r)
}

# Register entry points for exported C++ functions
Expand Down
60 changes: 34 additions & 26 deletions R/package/R/gpx.r
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,61 @@ TIMESTAMP_FORMAT <- "%FT%T.000Z"
#' Uses the Haversine great-circle distance formula to compute the distance
#' between two latitude/longitude points.
#'
#' @param lat_1,long_1,lat_2,long_2 The coordinates
#' @param lat_1,lon_1,lat_2,lon_2 The coordinates
#' used to compute the distance.
#' @param units The units of the output distance.
#' @examples
#' # In NYC, 20 blocks == 1 mile. Thus, computing the distance of two points along
#' # 7th Ave from W 39 St to W 59 St should return ~1 mile.
#' w39_coords <- list(lat=40.75406905512651, long=-73.98830604245481)
#' w59_coords <- list(lat=40.76684156255418, long=-73.97908243833855)
#' # In NYC, 20 blocks == 1 mile. Thus, computing the distance between two
#' # points along 7th Ave from W 39 St to W 59 St should return ~1 mile.
#' w39_coords <- list(lat=40.75406905512651, lon=-73.98830604245481)
#' w59_coords <- list(lat=40.76684156255418, lon=-73.97908243833855)
#'
#' get_haversine_distance(
#' w39_coords$lat,
#' w39_coords$long,
#' w39_coords$lon,
#' w59_coords$lat,
#' w59_coords$long,
#' w59_coords$lon,
#' "miles"
#' )
#'
#' # The combined distance of multiple points on a track can be computed as well.
#' # The total distance along a sequence of points can be computed. Consider the
#' # following sequence of points along Park Ave in the form of a list of points
#' # where each point is a list containing a `lat` and `lon` tag.
#' park_ave_coords <- list(
#' list(lat=40.735337983655434, long=-73.98973648773142), # E 15 St / Park Ave
#' list(lat=40.74772623378332, long=-73.98066078090876), # E 35 St / Park Ave
#' list(lat=40.76026319186414, long=-73.97149360922498), # E 55 St / Park Ave
#' list(lat=40.77301604875587, long=-73.96217737679450) # E 75 St / Park Ave
#' list(lat=40.735337983655434, lon=-73.98973648773142), # E 15 St
#' list(lat=40.74772623378332, lon=-73.98066078090876), # E 35 St
#' list(lat=40.76026319186414, lon=-73.97149360922498), # E 55 St
#' list(lat=40.77301604875587, lon=-73.96217737679450) # E 75 St
#' )
#'
#' sum(
#' sapply(
#' seq_along(park_ave_coords)[-1],
#' \(i) get_haversine_distance(
#' park_ave_coords[[i]]$lat,
#' park_ave_coords[[i]]$long,
#' park_ave_coords[[i - 1]]$lat,
#' park_ave_coords[[i - 1]]$long,
#' "miles"
#' # We can create a function to compute the total distance as follows:
#' compute_total_distance <- function(coords) {
#' sum(
#' sapply(
#' seq_along(coords)[-1],
#' \(i) get_haversine_distance(
#' coords[[i]]$lat,
#' coords[[i]]$lon,
#' coords[[i - 1]]$lat,
#' coords[[i - 1]]$lon,
#' "miles"
#' )
#' )
#' )
#' )
#' }
#'
#' # Then applying the function to our sequence results in a total distance.
#' compute_total_distance(park_ave_coords)
#' @returns The distance between two points in the requested units.
#' @references <https://en.wikipedia.org/wiki/Haversine_formula>
#' @export
get_haversine_distance <- function(lat_1,
long_1,
lon_1,
lat_2,
long_2,
lon_2,
units = c("miles", "kilometers")) {
r <- switch(match.arg(units), miles = R_E_MI, kilometers = R_E_KM)
.Call(`_eddington_get_haversine_distance_`, lat_1, long_1, lat_2, long_2, r)
.Call(`_eddington_get_haversine_distance_`, lat_1, lon_1, lat_2, lon_2, r)
}

#' Read a GPX file into a data frame containing dates and distances
Expand Down Expand Up @@ -82,7 +90,7 @@ get_haversine_distance <- function(lat_1,
#' )
#'
#' # Read in all files and combine them into a single data frame
#' rides <- do.call(rbind, lapply(activity_files, read_gpx))
#' rides <- do.call(rbind, lapply(gpx_export_files, read_gpx))
#' }
#' @returns A data frame containing up to two columns:
#' \describe{
Expand Down
56 changes: 32 additions & 24 deletions R/package/man/get_haversine_distance.Rd

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

2 changes: 1 addition & 1 deletion R/package/man/read_gpx.Rd

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

10 changes: 5 additions & 5 deletions R/package/src/RcppExports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,17 @@ RcppExport SEXP _eddington_E_next(SEXP ridesSEXP) {
return rcpp_result_gen;
}
// get_haversine_distance_
double get_haversine_distance_(double lat_1, double long_1, double lat_2, double long_2, double r);
RcppExport SEXP _eddington_get_haversine_distance_(SEXP lat_1SEXP, SEXP long_1SEXP, SEXP lat_2SEXP, SEXP long_2SEXP, SEXP rSEXP) {
double get_haversine_distance_(double lat_1, double lon_1, double lat_2, double lon_2, double r);
RcppExport SEXP _eddington_get_haversine_distance_(SEXP lat_1SEXP, SEXP lon_1SEXP, SEXP lat_2SEXP, SEXP lon_2SEXP, SEXP rSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< double >::type lat_1(lat_1SEXP);
Rcpp::traits::input_parameter< double >::type long_1(long_1SEXP);
Rcpp::traits::input_parameter< double >::type lon_1(lon_1SEXP);
Rcpp::traits::input_parameter< double >::type lat_2(lat_2SEXP);
Rcpp::traits::input_parameter< double >::type long_2(long_2SEXP);
Rcpp::traits::input_parameter< double >::type lon_2(lon_2SEXP);
Rcpp::traits::input_parameter< double >::type r(rSEXP);
rcpp_result_gen = Rcpp::wrap(get_haversine_distance_(lat_1, long_1, lat_2, long_2, r));
rcpp_result_gen = Rcpp::wrap(get_haversine_distance_(lat_1, lon_1, lat_2, lon_2, r));
return rcpp_result_gen;
END_RCPP
}
Expand Down
8 changes: 4 additions & 4 deletions R/package/src/haversine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ static inline double deg2rad(double deg) {

// [[Rcpp::export]]
double get_haversine_distance_(double lat_1,
double long_1,
double lon_1,
double lat_2,
double long_2,
double lon_2,
double r) {
const double dlat = deg2rad(lat_2 - lat_1);
const double dlong = deg2rad(long_2 - long_1);
const double h = hav(dlat) + cos(deg2rad(lat_1)) * cos(deg2rad(lat_2)) * hav(dlong);
const double dlon = deg2rad(lon_2 - lon_1);
const double h = hav(dlat) + cos(deg2rad(lat_1)) * cos(deg2rad(lat_2)) * hav(dlon);

return 2 * r * asin(sqrt(std::clamp(h, 0.0, 1.0)));
}
Expand Down
26 changes: 13 additions & 13 deletions R/package/tests/testthat/test-gpx.r
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@

# In NYC, 20 blocks == 1 mile and the grid is diagonal. That makes it the
# perfect location for testing the haversine distance formula.
w59_coords <- list(lat=40.76684156255418, long=-73.97908243833855) # W 59th St / 7th Ave
w39_coords <- list(lat=40.75406905512651, long=-73.98830604245481) # W 39th St / 7th Ave
w59_coords <- list(lat=40.76684156255418, lon=-73.97908243833855) # W 59th St / 7th Ave
w39_coords <- list(lat=40.75406905512651, lon=-73.98830604245481) # W 39th St / 7th Ave

ave_7_distance <- get_haversine_distance(
w39_coords$lat, w39_coords$long, w59_coords$lat, w59_coords$long, "miles"
w39_coords$lat, w39_coords$lon, w59_coords$lat, w59_coords$lon, "miles"
)

park_ave_coords <- list(
list(lat=40.735337983655434, long=-73.98973648773142), # E 15 St / Park Ave
list(lat=40.74772623378332, long=-73.98066078090876), # E 35 St / Park Ave
list(lat=40.76026319186414, long=-73.97149360922498), # E 55 St / Park Ave
list(lat=40.77301604875587, long=-73.96217737679450) # E 75 St / Park Ave
list(lat=40.735337983655434, lon=-73.98973648773142), # E 15 St
list(lat=40.74772623378332, lon=-73.98066078090876), # E 35 St
list(lat=40.76026319186414, lon=-73.97149360922498), # E 55 St
list(lat=40.77301604875587, lon=-73.96217737679450) # E 75 St
)

park_ave_distance <- sum(
sapply(
seq_along(park_ave_coords)[-1],
\(i) get_haversine_distance(
park_ave_coords[[i]]$lat,
park_ave_coords[[i]]$long,
park_ave_coords[[i]]$lon,
park_ave_coords[[i - 1]]$lat,
park_ave_coords[[i - 1]]$long,
park_ave_coords[[i - 1]]$lon,
"miles"
)
)
Expand All @@ -34,18 +34,18 @@ context("Haversine distance formula")
test_that("one mile is one mile", {
d <- get_haversine_distance(
w39_coords$lat,
w39_coords$long,
w39_coords$lon,
w59_coords$lat,
w59_coords$long,
w59_coords$lon,
"miles"
)
expect_equal(d, 1., tolerance = 0.01)

d <- get_haversine_distance(
w39_coords$lat,
w39_coords$long,
w39_coords$lon,
w59_coords$lat,
w59_coords$long,
w59_coords$lon,
"kilometers"
)
expect_equal(d, 1.62, tolerance = 0.01)
Expand Down

0 comments on commit 4bbf8ce

Please sign in to comment.