Reputation: 5270
Which is better for calculating the distance between two latitude/longitude points, The Haversine Formula or The Vincenty's Formula? Why?
The distance is obviously being calculated on Earth. Does WGS84 vs GCJ02 coordinates impact the calculation or distance (The Vincenty's formula takes the WGS84 axis into consideration)?
For example, in Android, the Haversine Formula is used in Google Map Utils, but the Vincenty Formula is used by the android.Location
object (Location.distanceBetween()
).
Upvotes: 40
Views: 35408
Reputation: 7253
Lets compare Haversine vs Karney (a faster, more stable reformulation of Vincenty) distance calculations. If we assume the ellipsoid model of the Earth is accurate, and also ignore GPS elevation in distances, Karney's calculation will be exact. Haversine distances will have errors, because they assume a spherical rather than ellipsoid Earth.
For minimum error, the Haversine calculation should use a spherical Earth radius that matches the radial distance on the ellipsoid near your GPS points of interest. For GPS points that are randomly distributed on the Earth, a radius that is halfway between the polar and equatorial radii lengths will minimize error. For the WGS84 reference ellipsoid, this is 6367444.65712259
meters.
Using this radius, we can measure Haversine distances for random GPS points and compare to Karney. The maximum relative absolute error is a constant ~0.5052%. For a 1km distance, that means Haversine distances will be off by at most 5.052 meters.
The Haversine calculation is much simpler and faster to calculate, so it should be preferred if 0.5052% relative error is acceptable for your application.
Here is some Python code you can play with to measure errors for different Haversine radii, or for different distances:
""" Compare haversine vs karney distances """
import math
from random import random
from geographiclib_cython import Geodesic
from geographiclib.constants import Constants
# distance in meters
karney_distance = 100000
def lerp(t, a, b):
if t < 0.5:
return a+(b-a)*t
return b-(b-a)*(1-t)
equatorial_radius = Constants.WGS84_a
polar_radius = Constants.WGS84_a*(1-Constants.WGS84_f)
radius = lerp(0.5, equatorial_radius, polar_radius)
print(f"Haversine radius: {radius}")
def haversine(A, B):
A = tuple(map(math.radians, A))
B = tuple(map(math.radians, B))
dlat = A[0] - B[0]
dlon = A[1] - B[1]
a = math.sin(dlat/2)**2 + math.cos(A[0]) * math.cos(B[0]) * math.sin(dlon/2)**2
c = 2 * math.asin(math.sqrt(a))
return c * radius
max_error = 0
for sample in range(100000):
A = (
lerp(random(), -90.0, 90.0),
lerp(random(), -180.0, 180.0)
)
azimuth = lerp(random(), 0.0, 360.0)
res = Geodesic.WGS84.Direct(*A, azimuth, karney_distance)
B = (
res["lat2"],
res["lon2"]
)
haversine_distance = haversine(A, B)
err = abs(haversine_distance - karney_distance)
if err > max_error:
max_error = err
# haversine formula error in meters
print(f"Maximum relative absolute error: {max_error/karney_distance*100:.04f}%")
Upvotes: 1
Reputation: 1929
Haversine and Vincenty are two algorithms for solving different problems. Haversine computes the great circle distance on a sphere while Vincenty computes the shortest (geodesic) distance on the surface of an ellipsoid of revolution. So the answer to your question can be broken into 2 parts:
For terrestrial applications, an ellipsoid of revolution is a reasonable approximation to "mean sea level"; the error is ± 100 m. The flattening of this ellipsoid is small, about 1/300, and so can be approximated by a sphere (of equal volume, for example).
Great circle distances differ from geodesic distances by up to 0.5%. In some applications, e.g., what's the distance from the Cape to Cairo?, this error can be neglected. In other applications, e.g., determining maritime boundaries, it is far too large (it's 5 m over a distance of 1 km). In general, you're safer using the geodesic distance.
If you're interested is distance traveled (by car, boat, or plane), there are lots of constraints on the path taken and neither the great circle or geodesic distance, which measure the length of shortest paths on an ideal surface, would be appropriate.
On the question of whether the algorithms are accurate:
Haversine is accurate to round-off unless the points are nearly antipodal. Better formulas are given in the Wikipedia article on great-circle distances.
Vincenty is usually accurate to about 0.1 mm. However if the points are nearly antipodal, the algorithm fails to converge and the error is much larger. I give a better algorithm for solving the geodesic problem in Algorithms for geodesics. See also the Wikipedia article on geodesics on an ellipsoid.
Solving the geodesic problem is slower than solving for the great-circle. But it's still very fast (about 1 μs per calculation), so this shouldn't be a reason to prefer great circle distances.
ADENDUM
Here is the Java package which implements my algorithm for finding geodesic distances. Unlike Vincenty's method, this is accurate to round-off and converges everywhere.
Upvotes: 70
Reputation: 17487
Haversine is a simpler computation but it does not provide the high accuracy Vincenty offers.
Vincenty is more accurate but is also more computationally intensive and will therefore perform slower and increase battery usage.
As with anything "better" is a matter of your particular application. For your application, Vincenty may be a "better" choice than Haversine, but for a different application, Haversine may be a better choice. You will have to look at the particulars of your use cases and make a determination based upon what you find there.
Upvotes: 26