1

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..

enter image description here

There must be an easier way...?

tofd
  • 620
  • 4
  • 11

0 Answers0