Kevin Mess
2006-11-02 14:55:12 UTC
For you mathematicians out there :)
I have a class whose primary attributes are two doubles representing a
geographic point, expressed as a latitude and longitude.
One of the methods in the class calculates the distance between two
Points using the Haversine Formula.
For the most part, it works, but in some instances, I get NaN (Not a
Number) where I realistically should expect a distance.
Here is the method that implements the Haversine formula:
public double distanceTo(Point p2) {
/*
Haversine Formula (from R.W. Sinnott, "Virtues of the Haversine",
Sky and Telescope, vol. 68, no. 2, 1984, p. 159):
http://www.movable-type.co.uk/scripts/GIS-FAQ-5.1.html
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin^2(dlat/2) + cos(lat1) * cos(lat2) * sin^2(dlon/2)
c = 2 * arcsin(min(1,sqrt(a)))
d = R * c
The Haversine Formula can be expressed in terms of a two-argument
inverse tangent function instead of an inverse sine. No bulletproofing is
needed for an inverse tangent (theoretically at least).
*/
final double RADIUS = 6371.005076123; // Earth's mean radius in km
// delta (difference) in latitudes
double dLat = radians(p2.latitude) - radians(this.latitude);
// delta (difference) in longitudes
double dLon = radians(p2.longitude) - radians(this.longitude);
double a = sin(dLat / 2) * sin(dLat / 2) +
cos(this.latitude) * cos(p2.latitude) * sin(dLon / 2) *
sin(dLon / 2);
double c = 2 * atan2(sqrt(a), sqrt(1 - a)); // great circle
distance in radians
return RADIUS * c;
// great circle distance in km
}
I won't provide you with the entire output for brevity. Notice the
first few lines - they return expected results. The last few show the
problem:
Distance from Las Vegas (N36°10'59" W115°13'00") to:
// these work
offshore Northern California (N40°18'29" W124°22'49") = 401.5591308690782 km.
Nias region, Indonesia (N00°47'03" E097°19'49") = 4667.779825988913 km.
offshore Northern California (N40°18'35" W124°23'04") = 401.64873756773324 km.
Gulf of Alaska (N58°20'18" W148°17'06") = 2430.6375616198306 km.
// these don't work
Oklahoma (N34°27'52" W097°47'44") = NaN km.
eastern Turkey (N39°30'18" E040°42'10") = NaN km.
Central California (N35°51'19" W120°24'25") = NaN km.
Caspian Sea, offshore Turkmenistan (N40°25'44" E052°01'29") = NaN km.
...
Any thoughts on where/why this formula is failing?
Thanks,
Kevin
I have a class whose primary attributes are two doubles representing a
geographic point, expressed as a latitude and longitude.
One of the methods in the class calculates the distance between two
Points using the Haversine Formula.
For the most part, it works, but in some instances, I get NaN (Not a
Number) where I realistically should expect a distance.
Here is the method that implements the Haversine formula:
public double distanceTo(Point p2) {
/*
Haversine Formula (from R.W. Sinnott, "Virtues of the Haversine",
Sky and Telescope, vol. 68, no. 2, 1984, p. 159):
http://www.movable-type.co.uk/scripts/GIS-FAQ-5.1.html
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin^2(dlat/2) + cos(lat1) * cos(lat2) * sin^2(dlon/2)
c = 2 * arcsin(min(1,sqrt(a)))
d = R * c
The Haversine Formula can be expressed in terms of a two-argument
inverse tangent function instead of an inverse sine. No bulletproofing is
needed for an inverse tangent (theoretically at least).
*/
final double RADIUS = 6371.005076123; // Earth's mean radius in km
// delta (difference) in latitudes
double dLat = radians(p2.latitude) - radians(this.latitude);
// delta (difference) in longitudes
double dLon = radians(p2.longitude) - radians(this.longitude);
double a = sin(dLat / 2) * sin(dLat / 2) +
cos(this.latitude) * cos(p2.latitude) * sin(dLon / 2) *
sin(dLon / 2);
double c = 2 * atan2(sqrt(a), sqrt(1 - a)); // great circle
distance in radians
return RADIUS * c;
// great circle distance in km
}
I won't provide you with the entire output for brevity. Notice the
first few lines - they return expected results. The last few show the
problem:
Distance from Las Vegas (N36°10'59" W115°13'00") to:
// these work
offshore Northern California (N40°18'29" W124°22'49") = 401.5591308690782 km.
Nias region, Indonesia (N00°47'03" E097°19'49") = 4667.779825988913 km.
offshore Northern California (N40°18'35" W124°23'04") = 401.64873756773324 km.
Gulf of Alaska (N58°20'18" W148°17'06") = 2430.6375616198306 km.
// these don't work
Oklahoma (N34°27'52" W097°47'44") = NaN km.
eastern Turkey (N39°30'18" E040°42'10") = NaN km.
Central California (N35°51'19" W120°24'25") = NaN km.
Caspian Sea, offshore Turkmenistan (N40°25'44" E052°01'29") = NaN km.
...
Any thoughts on where/why this formula is failing?
Thanks,
Kevin