Been quite a while since any updates, but here’s a short one!
As a part of a contract I’m working on, I found myself having to plot the major arc of great circle paths on a map. But if you google “how to plot great circle path in [insert python library here]” all the solutions are for plotting minor arcs. Turns out in the end, there’s a really simple trick to plotting the major arc (and I felt pretty dumb when I realized it after wasting a ton of time), but I figured I’d write it up here in case it saves anyone else a bit of time. The short answer: given two points that you want the major arc for, just add the antipodes for each point to the list of points in your path.
First off, in case you need a review of great circles, here’s a globe:
Given two points on the surface of a sphere, there is a single circle that that contains both points (unless you’re at a pole, in which case there are infinite great circles). The short way round is the minor arc (red curve), the long way round is the major arc (green curve). And I needed to plot both of them.
The reason I got into plotting this in the first place is that in seismology, surface waves are described by major and minor arcs. When an earthquake generates seismic waves and is measured at a seismometer somewhere else, the raypath between the epicenter and seismic station falls on a great circle path. And surface waves are referred to in terms of the minor and major arcs: the R1 wave travels the minor arc and the R2 travels the major arc. These waves will actually keep going around the earth’s surface before dissipating: R3 is the R1 after it goes around again, R4 is the R2 after it goes around again, and on and on. So I needed to be able to plot all these.
Ok, so back to plotting…
I was using the plotly library in Python for this plot, so I’ll stick with that for examples here, but there should be similar functions in whatever mapping library you’re using. The full script is on my github page here.
So the important bit is just defining the list of latitude and longitude points. Here, the minor arc points are put into a dictionary:
paths={} paths['minor_arc']={'lon':[ start_lon, end_lon ], 'lat':[start_lat,end_lat], 'clr':'red','dash':None}
When we give this to plotly, we’ll tell it to connect the two points, which will give us the shortest path between the two, the minor arc.
To plot the major arc, we just need to add some points between the start and end so that it takes the long way around. But how to choose the points? Well, turns out that there are tons of confusing pages out there on the trig used for calculating great circle paths, and I almost started to code up some of it… until I realized only needed a couple points. And the antipodes (the point that is exactly opposite a given point on the surface) are both real easy to calculate and guaranteed to lie on the great circle path. Just add 180 to the longitude and flip the sign of the latitude:
ant1lon=start_lon+180 if ant1lon>360: ant1lon= ant1lon - 360 ant1lat=-start_lat
Same for the antipode of the second, end point. The >360 bit is just to make sure longitude remains between 0 and 360 degrees.
And now, we can put the antipodes in a list for the major arc:
paths['major_arc']={'lon':[ start_lon,ant2lon,ant1lon, end_lon ], 'lat':[start_lat,ant2lat,ant1lat,end_lat], 'clr':'green','dash':None}
In the script, these paths are then added as a data dictionary used in creating the plotly figure:
DataDict=list() for path in ['minor_arc','major_arc']: DataDict.append( dict( type = 'scattergeo', lon = paths[path]['lon'], lat = paths[path]['lat'], name= path, mode = 'lines', line = dict( width = 2.5, color = paths[path]['clr'], dash=paths[path]['dash'], ), opacity = 1.0, ) ) figdata={} figdata['data']=DataDict
The full script has a bit more where it actually plots the data (to give the image above), but plotly has some really nice tutorials for that already so I won’t bother explaining all that.
So that’s that! Hope it saves someone else some time.