Great Circle Algorithms
OpenLayers is a wonderful JavaScript framework for map making, but its functions assume a FlatLand view of the Earth. This is fine for simply displaying maps, but if you're trying to interact with your map by measuring distances or angles over large areas you're not likely to get accurate results.
The Earth is essentially a sphere, and so it's more appropriate to measure distances and angles using spherical trigonometry. First, note that the shortest distance between two points on a sphere is the route traced out by a plane passing through the center of the sphere and the two points where it intersects the sphere's surface. The arc described by the intersection of any plane that passes through the center of a sphere and the surface of the sphere is known as a great circle. All the meridians (lines of longitude) are great circles as is the Equator. For detailed discussion of great circles and their application see the Great Circle page at WikiPedia.
The OpenLayers.Geometry.Point class can easily be extended to provide great circle functionality for calculating distances and angles between points as well as computing waypoints along a great circle route (i.e. finding the coordinates of a point that is a specified distance and bearing from an origin point.) The mathematics for the following functions comes from Ed Williams' excellent Aviation Formulary site.
If you want to download some working JavaScript code that implements these algorithms in OpenLayers it's available at Point.js. This is used in an OpenLayers demonstration of animating a line.
Great Circle Distance
In this discussion (and in the actual functions), we assume that coordinates are Latitude and Longitude as signed decimal degrees with negative longitude in the western hemisphere and negative latitude in the southern hemisphere. Coordinates are also converted to radians to do the calculations as this simplifies the spherical trigonometry a great deal.
Constants: Radius of the Earth in miles EARTH_RADIUS = 3958.75 Ratio of a circle's circumference to its diameter PI = 3.1415926535897932384626433832795 Factor to convert decimal degrees to radians DEG2RAD = 0.01745329252 Factor to convert decimal degrees to radians RAD2DEG = 57.29577951308 Great Circle Distance: Inputs are 2 coordinates x1,y1 and x2,y2 Convert to radians x1 = x1 * DEG2RAD y1 = y1 * DEG2RAD x2 = x2 * DEG2RAD y2 = y2 * DEG2RAD a = sin(( y2-y1 ) / 2.0 )^2 b = sin(( x2-x1 ) / 2.0 )^2 c = sqrt( a + cos( y2 ) * cos( y1 ) * b ) distance = 2 * asin( c ) * EARTH_RADIUS
Great Circle Bearing
This algorithm calculates the angle that point 2 bears to point 1 along a great circle route. Note that as you move along that route from point 1 to point 2 the bearing is always changing.
Inputs are 2 coordinates x1,y1 and x2,y2
Convert to radians
x1 = x1 * DEG2RAD
y1 = y1 * DEG2RAD
x2 = x2 * DEG2RAD
y2 = y2 * DEG2RAD
a = cos(y2) * sin(x2 - x1)
b = cos(y1) * sin(y2) - sin(y1) * cos(y2) * cos(x2 - x1)
adjust = 0
if((a == 0) && (b == 0)) {
bearing = 0
} else if( b == 0) {
if( a < 0)
bearing = 3 * PI / 2
else
bearing = PI / 2
} else if( b < 0)
adjust = PI
else {
if( a < 0)
adjust = 2 * PI
else
adjust = 0
}
bearing = (atan(a/b) + adjust) * RAD2DEG
Great Circle Waypoints
This algorithm returns a point that is a specified distance and bearing from the input point. Inputs are 2 coordinates x1,y1, bearing (an angle) and distance (units match EARTH_RADIUS). It returns coordinates x2, y2.
Convert to radians
x1 = x1 * DEG2RAD
y1 = y1 * DEG2RAD
bearing = bearing * DEG2RAD
// Convert arc distance to radians
c = distance / EARTH_RADIUS
y2 = asin( sin(y1) * cos(c) + cos(y1) * sin(c) * cos(bearing)) * RAD2DEG
a = sin(c) * sin(bearing)
b = cos(y1) * cos(c) - sin(y1) * sin(c) * cos(bearing)
if( b == 0 )
x2 = x1
else
x2 = x1 + atan(a/b) * RAD2DEG
return x2,y2
