commit 152321e10b81ebe610a9ba5e3c8aa907c3fc5938
parent 52ba6c6c844aff0316ffaf68a4a139b9afe6221a
Author: eamoncaddigan <eamon.caddigan@gmail.com>
Date:   Tue, 19 Apr 2016 10:14:31 -0400
maxDistanceFromPath() helper.
Diffstat:
4 files changed, 78 insertions(+), 21 deletions(-)
diff --git a/NAMESPACE b/NAMESPACE
@@ -1,3 +1,4 @@
 # Generated by roxygen2: do not edit by hand
 
 export(distanceFromPath)
+export(maxDistanceFromPath)
diff --git a/R/maxDistanceFromPath.R b/R/maxDistanceFromPath.R
@@ -0,0 +1,18 @@
+#' Find the maximum distance of a flight trajectory from a flight path.
+#'
+#' @param trajectory A matrix or SpatialPoints object indicating the trajectory
+#'   of an aircraft.
+#' @param path A matrix or SpatialPoints object indicating the ordered waypoints
+#'   a pre-defined flight path.
+#' @return A named vector indicating the horizontal and vertical distance from
+#'   the fligh path at which the aircraft reached the maximum slant (euclidean)
+#'   distance.
+#'
+#' @export
+maxDistanceFromPath <- function(trajectory, path) {
+  distanceFromPathVals <- distanceFromPath(trajectory, path)
+  slantDistanceFromPath <- distanceFromPathVals$horizontal^2 +
+    distanceFromPathVals$vertical^2
+  farthestPoint <- which.max(slantDistanceFromPath)
+  return(unlist(distanceFromPathVals[farthestPoint, ]))
+}
diff --git a/man/maxDistanceFromPath.Rd b/man/maxDistanceFromPath.Rd
@@ -0,0 +1,24 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/maxDistanceFromPath.R
+\name{maxDistanceFromPath}
+\alias{maxDistanceFromPath}
+\title{Find the maximum distance of a flight trajectory from a flight path.}
+\usage{
+maxDistanceFromPath(trajectory, path)
+}
+\arguments{
+\item{trajectory}{A matrix or SpatialPoints object indicating the trajectory
+of an aircraft.}
+
+\item{path}{A matrix or SpatialPoints object indicating the ordered waypoints
+a pre-defined flight path.}
+}
+\value{
+A named vector indicating the horizontal and vertical distance from
+  the fligh path at which the aircraft reached the maximum slant (euclidean)
+  distance.
+}
+\description{
+Find the maximum distance of a flight trajectory from a flight path.
+}
+
diff --git a/tests/testthat/test_distanceFromPath.R b/tests/testthat/test_distanceFromPath.R
@@ -1,15 +1,7 @@
 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")))
-
+distancePrecision <- 10
 numPoints <- 5
 
 fakeTrajectory <- function(waypoints, n = numPoints) {
@@ -23,13 +15,20 @@ fakeTrajectory <- function(waypoints, n = numPoints) {
   return(do.call(rbind, trajectoryList))
 }
 
+# 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 <- fakeTrajectory(path)
 
 test_that("non-deviating paths have small distances for all input types", {
-  expect_true(all(distanceFromPath(trajectory, path) < 1))
-  expect_true(all(distanceFromPath(cbind(trajectory, 3500), cbind(path, 3500)) < 1))
-  expect_true(all(distanceFromPath(sp::SpatialPoints(trajectory), sp::SpatialPoints(path)) < 1))
-  expect_true(all(distanceFromPath(as.data.frame(trajectory), as.data.frame(path)) < 1))
+  expect_true(all(distanceFromPath(trajectory, path) < distancePrecision))
+  expect_true(all(distanceFromPath(cbind(trajectory, 3500), cbind(path, 3500)) < distancePrecision))
+  expect_true(all(distanceFromPath(sp::SpatialPoints(trajectory), sp::SpatialPoints(path)) < distancePrecision))
+  expect_true(all(distanceFromPath(as.data.frame(trajectory), as.data.frame(path)) < distancePrecision))
 })
 
 test_that("small deviations look OK", {
@@ -41,8 +40,11 @@ test_that("small deviations look OK", {
   farthestPoint <- which.max(abs(trajectoryDistance))
 
   expect_equal(farthestPoint, numPoints*2+3)
-  # left of course
-  expect_lt(trajectoryDistance[farthestPoint], 0)
+
+  expect_lt(abs(maxDistanceFromPath(flownTrajectory, path)["horizontal"] - -42015.6),
+            distancePrecision)
+  expect_lt(abs(maxDistanceFromPath(flownTrajectory, flownPath)["horizontal"] - 0),
+            distancePrecision)
 })
 
 test_that("simple altitude deviation is handled", {
@@ -54,11 +56,23 @@ test_that("simple altitude deviation is handled", {
                                    seq(5500, 3500,
                                        length.out = nrow(trajectory)-(numPoints+2))))
 
+  expect_lt(abs(maxDistanceFromPath(flownTrajectory, flownPath1)["vertical"] - 2000),
+            distancePrecision)
+  expect_lt(abs(maxDistanceFromPath(flownTrajectory, flownPath2)["vertical"] - 1000),
+            distancePrecision)
+  expect_lt(abs(maxDistanceFromPath(flownTrajectory, flownPath3)["vertical"] - 0000),
+            distancePrecision)
+})
+
+test_that("reproducing geosphere vignette example", {
+  LA <- c(-118.40, 33.95)
+  NY <- c(-73.78, 40.63)
+  MS <- c(-93.26, 44.98)
+  plannedPath <- rbind(LA, NY)
+  flownTrajectory <- fakeTrajectory(rbind(LA, MS, NY), n = 1000)
+  feetToMeters <- 0.3048
 
-  expect_equal(max(distanceFromPath(flownTrajectory, flownPath1)$vertical),
-               2000.0)
-  expect_equal(max(distanceFromPath(flownTrajectory, flownPath2)$vertical),
-               1000.0)
-  expect_equal(max(distanceFromPath(flownTrajectory, flownPath3)$vertical),
-               0)
+  expect_lt(abs(maxDistanceFromPath(flownTrajectory, plannedPath)["horizontal"]*feetToMeters -
+                  -547448.8),
+            1)
 })