Seemingly quite a simple problem, but I just can't get it. Essentially I am trying to plot a bunch of lines of different weights showing international trade flows, via leaflet in R. I tried using great circle approaches but it doesn't give the effect I want. Instead I am trying to plot the arrows as one side of an ellipse of which the center line is the rhumb line between two countries.
I don't want to cross the date line because then the chart looks horrible. However, the problem is that the implementation of rhumb line functions in geosphere
, (distRhumb
, bearingRhumb
etc.) seem to only allow you to calculate the shortest distance (i.e. crossing the dateline as required).
So my problem is given 2 points for which a connecting rhumb line would normally cross the dateline, let's say China and Canada, how do I accurately calculate the rhumb line distance and the rhumb line bearing without crossing the date line.
so far I've tried this extremely hacky approach...
library(geosphere)
rad2deg <- function(rad) {(rad * 180) / (pi)}
deg2rad <- function(deg) {(deg * pi) / (180)}
# China
p1 <- c("lon"=104, "lat"=36.6)
# Canada
p2 <- c("lon"=-102, "lat"=57.7)
# first get shortest distance rhumb bearing
rbearing <- (bearingRhumb(p1, p2) + 360) %% 360
# and shortest distance rhumb distance
shorter_dist <- distRhumb(p1, p2)
# reverse by flipping 180 degrees
rbearing <- rbearing - 180
rbearing <- (rbearing + 360) %% 360
# and take a first guess using original distance
p3 <- destPointRhumb(p1, rbearing, shorter_dist)
# now recalculate the distance and bearing
# so we have 2 sides of a triangle and an angle
dist2 <- distRhumb(p3, p2)
rbearing2 <- (bearingRhumb(p3, p2) + 360) %% 360
A <- 180 - abs(rbearing2 - rbearing)
# try to use trigonometry to solve for the opposite side
longer_dist <- sqrt(shorter_dist^2 + dist2^2 - 2*(shorter_dist *dist2)*cos(deg2rad(A)))
# and get a revised bearing
bear_offset <- rad2deg(asin(dist2*(sin(deg2rad(A))/longer_dist)))
if (rbearing2 > rbearing){
longer_rbearing <- rbearing + bear_offset
} else {
longer_rbearing <- rbearing - bear_offset
}
But that doesn't seem to work very well..
There must be an easier way...?