# flightpathr

Tools to analyze aircraft and flight path data.

```commit d11aebdb6b1aa186d7e4e5c5c275389d788815c3
parent 654b56bdc2c306b81f1a9689063fcb2c9ef5477f
Date:   Mon, 18 Apr 2016 13:52:05 -0400

Working (and passing tests) for the simplest case.

Diffstat:
MR/distanceFromPath.R | 24+++++++++++++-----------
Atests/testthat/test_distanceFromPath.R | 17+++++++++++++++++
```
```2 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/R/distanceFromPath.R b/R/distanceFromPath.R
@@ -18,8 +18,10 @@ distanceFromPath <- function(trajectory, path) {
numLegs <- nrow(pathCoords)-1

# Given n points and m legs, store horizontal and vertical distance in an
-  # n x m x 2 array
-  distanceToLeg <- array(NA, dim = c(nrow(trajectory), 2, numLegs))
+  # n x m arrays
+  hDistanceToLeg <- array(NA, dim = c(nrow(trajectoryCoords), numLegs))
+  vDistanceToLeg <- array(NA, dim = c(nrow(trajectoryCoords), numLegs))
+
# And the squared "slant range" (euclidean distance) in an n x m array
slantToLeg <- array(NA, dim = c(nrow(trajectoryCoords), numLegs))

@@ -27,21 +29,21 @@ distanceFromPath <- function(trajectory, path) {
# For each pair of adjascent waypoints, calculate the horizontal distance
# from the great circle defined by the pair and all points in the
# trajectory.
-    distanceToLeg[, i, 1] <- geosphere::dist2gc(path[i, c(1,2)],
-                                                path[i+1, c(1,2)],
-                                                trajectory[, c(1,2)],
-                                                r = 2.0904e+7)
+    hDistanceToLeg[, legIdx] <- geosphere::dist2gc(pathCoords[legIdx, c(1,2)],
+                                              pathCoords[legIdx+1, c(1,2)],
+                                              trajectoryCoords[, c(1,2)],
+                                              r = 2.0904e+7)

# If the waypoints are at the same altitude, just calculate the deviation
# from this altitude. Easy.
# XXX - Not actually handling the case where they don't match.
-    if (!isTRUE(all.equal(altitudes(path[i]), altitudes(path[i+1])))) {
+    if (!isTRUE(all.equal(pathCoords[legIdx, 3], pathCoords[legIdx+1, 3]))) {
warning("Pretending that waypoint altitudes match when they don't")
}
-    distanceToLeg[, i, 2] <- trajectory[, 3] - path[i, 3]
+    vDistanceToLeg[, legIdx] <- trajectoryCoords[, 3] - pathCoords[legIdx, 3]

# Squared euclidean distance
-    slantToLeg[, i] <- distanceToLeg[, i, 1]^2 + distanceToLeg[, i, 2]^2
+    slantToLeg[, legIdx] <- hDistanceToLeg[, legIdx]^2 + vDistanceToLeg[, legIdx]^2
}

# Figure out which leg is closer to each point in the trajectory.
@@ -51,7 +53,7 @@ distanceFromPath <- function(trajectory, path) {

# Return the horizontal and vertical distance to the flight path (distance to
# the closest leg) as a data.frame.
-  distanceToPath <- as.data.frame(drop(distanceToLeg[, closestLeg, ]))
-  colnames(distanceToPath) <- c("horizontal", "vertical")
+  distanceToPath <- data.frame(horizontal = hDistanceToLeg[cbind(1:nrow(trajectoryCoords), closestLeg)],
+                               vertical = vDistanceToLeg[cbind(1:nrow(trajectoryCoords), closestLeg)])
return(distanceToPath)
}
diff --git a/tests/testthat/test_distanceFromPath.R b/tests/testthat/test_distanceFromPath.R
@@ -0,0 +1,17 @@
+library(flightpathr)
+context("distanceFromPath")
+
+# Flying from 17N to KACY with a stop over N81. Flying VFR at 3500 msl
+
+path <- matrix(c(-75.0268, 39.7065,
+                 -74.7577, 39.6675,
+                 -74.5722, 39.4513),
+               nrow = 3, byrow = TRUE,
+               dimnames = list(c("17N", "N81", "KACY"),
+                               c("lon", "lat")))
+trajectory <- rbind(geosphere::gcIntermediate(path[1, ], path[2, ], 5),
+                    geosphere::gcIntermediate(path[2, ], path[3, ], 6))
+
+test_that("non-deviating paths have small distances", {
+  expect_true(all(distanceFromPath(trajectory, path) < 1))
+})
```