3. Direction

Introduction

Point at distance and bearing

Function destPoint returns the location of point given a point of origin, and a distance and bearing. Its perhaps obvious use in georeferencing locations of distant sitings. It can also be used to make circular polygons (with a fixed radius, but in longitude/latitude coordinates)

destPoint(LA, b=65, d=100000)
## Error in inherits(p, "SpatialPoints"): object 'LA' not found
circle=destPoint(c(0,80), b=1:365, d=1000000)
circle2=destPoint(c(0,80), b=1:365, d=500000)
circle3=destPoint(c(0,80), b=1:365, d=100000)
plot(circle, type='l')
polygon(circle, col='blue', border='black', lwd=4)
polygon(circle2, col='red', lwd=4, border='orange')
polygon(circle3, col='white', lwd=4, border='black')

Triangulation

Below is triangulation example. We have three locations (NY, LA, MS) and three directions (281, 60, 195) towards a target. Because we are on a sphere, there are two (antipodal) results. We only show one here (by only using int[,1:2]). We compute the centroid from the polygon defined with the three points. To accurately draw a spherical polygon, we can use makePoly. This function inserts intermediate points along the paths between the vertices provided (default is one point every 10 km).

MS <- c(-93.26, 44.98)
gc1 <- greatCircleBearing(NY, 281)
## Error in inherits(p, "SpatialPoints"): object 'NY' not found
gc2 <- greatCircleBearing(MS, 195)
gc3 <- greatCircleBearing(LA, 55)
## Error in inherits(p, "SpatialPoints"): object 'LA' not found
plot(wrld, type='l', xlim=c(-125, -70), ylim=c(20, 60))
## Error in plot(wrld, type = "l", xlim = c(-125, -70), ylim = c(20, 60)): object 'wrld' not found
lines(gc1, col='green')
## Error in lines(gc1, col = "green"): object 'gc1' not found
lines(gc2, col='blue')
## Error in plot.xy(xy.coords(x, y), type = type, ...): plot.new has not been called yet
lines(gc3, col='red')
## Error in lines(gc3, col = "red"): object 'gc3' not found

int <- gcIntersectBearing(rbind(NY, NY, MS),
            c(281, 281, 195), rbind(MS, LA, LA), c(195, 55, 55))
## Error in rbind(NY, NY, MS): object 'NY' not found
int
## Error in eval(expr, envir, enclos): object 'int' not found
distm(rbind(int[,1:2], int[,3:4]))
## Error in rbind(int[, 1:2], int[, 3:4]): object 'int' not found
int <- int[,1:2]
## Error in eval(expr, envir, enclos): object 'int' not found
points(int)
## Error in points(int): object 'int' not found
poly <- rbind(int, int[1,])
## Error in rbind(int, int[1, ]): object 'int' not found
centr <- centroid(poly)
## Error in (function (classes, fdef, mtable) : unable to find an inherited method for function 'centroid' for signature '"function"'
poly2 <- makePoly(int)
## Error in inherits(p, "SpatialPolygons"): object 'int' not found
polygon(poly2, col='yellow')
## Error in xy.coords(x, y): object 'poly2' not found
points(centr, pch='*', col='dark red', cex=2)
## Error in points(centr, pch = "*", col = "dark red", cex = 2): object 'centr' not found

Bearing

Below we first compute the distance and bearing from Los Angeles (LA) to New York (NY). These are then used to compute the point from LA at that distance in that (initial) bearing (direction). Bearing changes continuously when traveling along a Great Circle. The final bearing, when approaching NY, is also given.

d <- distCosine(LA, NY)
## Error in inherits(p, "SpatialPoints"): object 'LA' not found
d
## Error in eval(expr, envir, enclos): object 'd' not found
b <- bearing(LA, NY)
## Error in inherits(p, "SpatialPoints"): object 'LA' not found
b
## Error in eval(expr, envir, enclos): object 'b' not found
destPoint(LA, b, d)
## Error in as.vector(b): object 'b' not found
NY
## Error in eval(expr, envir, enclos): object 'NY' not found
finalBearing(LA, NY)
## Error in inherits(p, "SpatialPoints"): object 'LA' not found

Getting off-track

What if we went off-course and were flying over Minneapolis (MS)? The closest point on the planned route (p) can be computed with the alongTrackDistance and destPoint functions. The distance from ‘p’ to MS can be computed with the dist2gc (distance to great circle, or cross-track distance) function. The light green line represents the along-track distance, and the dark green line represents the cross-track distance.

atd <- alongTrackDistance(LA, NY, MS)
## Error in inherits(p, "SpatialPoints"): object 'LA' not found
p <- destPoint(LA, b, atd)
## Error in as.vector(b): object 'b' not found
plot(wrld, type='l', xlim=c(-130,-60), ylim=c(22,52))
## Error in plot(wrld, type = "l", xlim = c(-130, -60), ylim = c(22, 52)): object 'wrld' not found
lines(gci, col='blue', lwd=2)
## Error in lines(gci, col = "blue", lwd = 2): object 'gci' not found
points(rbind(LA, NY), col='red', pch=20, cex=2)
## Error in rbind(LA, NY): object 'LA' not found
points(MS[1], MS[2], pch=20, col='blue', cex=2)
## Error in plot.xy(xy.coords(x, y), type = type, ...): plot.new has not been called yet
lines(gcIntermediate(LA, p), col='green', lwd=3)
## Error in inherits(p, "SpatialPoints"): object 'LA' not found
lines(gcIntermediate(MS, p), col='dark green', lwd=3)
## Error in inherits(p, "SpatialPoints"): object 'p' not found
points(p, pch=20, col='red', cex=2)
## Error in points(p, pch = 20, col = "red", cex = 2): object 'p' not found
dist2gc(LA, NY, MS)
## Error in inherits(p, "SpatialPoints"): object 'LA' not found
distCosine(p, MS)
## Error in inherits(p, "SpatialPoints"): object 'p' not found

Rhumb lines

Rhumb (from the Spanish word for course, ‘rumbo’) lines are straight lines on a Mercator projection map (and at most latitudes pretty straight on an equirectangular projection (=unprojected lon/lat) map). They were used in navigation because it is easier to follow a constant compass bearing than to continually adjust direction as is needed to follow a great circle, even though rhumb lines are normally longer than great-circle (orthodrome) routes. Most rhumb lines will gradually spiral towards one of the poles.

NP <- c(0, 85)
bearing(SF, NP)
## Error in inherits(p, "SpatialPoints"): object 'SF' not found
b <- bearingRhumb(SF, NP)
## Error in inherits(p, "SpatialPoints"): object 'SF' not found
b
## Error in eval(expr, envir, enclos): object 'b' not found
dc <- distCosine(SF, NP)
## Error in inherits(p, "SpatialPoints"): object 'SF' not found
dr <- distRhumb(SF, NP)
## Error in inherits(p, "SpatialPoints"): object 'SF' not found
dc / dr
## Error in eval(expr, envir, enclos): object 'dc' not found

pr <- destPointRhumb(SF, b, d=round(dr/100) * 1:100)
## Error in as.vector(b): object 'b' not found
pc <- rbind(SF, gcIntermediate(SF, NP), NP)
## Error in rbind(SF, gcIntermediate(SF, NP), NP): object 'SF' not found
par(mfrow=c(1,2))
data(wrld)
plot(wrld, type='l', xlim=c(-140,10), ylim=c(15,90), main='Equirectangular')
lines(pr, col='blue')
## Error in lines(pr, col = "blue"): object 'pr' not found
lines(pc, col='red')
## Warning in xy.coords(x, y): NAs introduced by coercion
data(merc)
plot(merc, type='l', xlim=c(-15584729, 1113195),
                     ylim=c(2500000, 22500000), main='Mercator')
lines(mercator(pr), col='blue')
## Error in inherits(p, "SpatialPoints"): object 'pr' not found
lines(mercator(pc), col='red')
## Error in .pointsToMatrix(p): Wrong length for a vector, should be 2