Game Development Reference

In-Depth Information

//Calculate angular distance

float C = 2 * atan(sqrt(a)/sqrt(1-a));

//Find arclength

float distance = 6371 * C; //6371 is radius of earth in km

return distance;

}

One limitation of the preceding method is that if the two locations are nearly
antipodal

—that is, on opposite sides of the earth—then the haversine formula may have round-

off issues that could results in errors on the order of 2 km. These, however, will be over

a distance of 20,000 km. If extreme accuracy is required for nearly antipodal coordinates,

you can fall back to the spherical law of cosines, which is best suited for large distances

such as the antipodal case.

Great-Circle Heading

As discussed before, to follow the shortest path between two points on a sphere you

must travel along a great circle. However, this requires that your heading be constantly

changing with time. The formula to calculate your initial heading, or
forward azi‐

muth
, is:

Θ
i
= atan2[sin(Δ
long
)cos(lat
2
), cos(lat
1
)sin(lat
2
) -

sin(lat
1
)cos(lat
2
)cos(Δ
long
)]

Recall that
atan2
is the two-argument variation of the
arctangent
function. It returns

a normalized angle in radians between −π and π (−180° and 180°). The code that cal‐

culates the value and returns the compass bearing is as follows:

float initialBearing (Coordinate2D startPoint, Coordinate2D endPoint){

//Convert location from degrees to radians

float lat1 = (M_PI/180.) * startPoint.lat;

float lon1 = (M_PI/180.) * startPoint.longi;

float lat2 = (M_PI/180.) * endPoint.lat;

float lon2 = (M_PI/180.) * endPoint.longi;

//Calculate deltas

float dLat = lat2 - lat1;

float dLon = lon2 - lon1;

// Calculate bearing in radians

float theta = atan2f( sin(dlon) * cos(lat2), cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)

*cos(dlon));

//Convert to compass bearing

Float bearing = theta * (180 / M_PI); //radians to degrees

bearing = ( bearing > 0 ? bearing : (360.0 + bearing)); //fix range

return bearing;

}