
Recently I had a requirement to get the great circle distance (GCD) between two points on earth. I needed to calculate ‘as the crow flies’ distance between a pair of latitude/ longitude provided. Since this was new to me, I did some research to figure out what my options are. It seems there has been a lot of research that went into this and there are quite a number formulas that can be used.
Calculating geodesic distance, as it is called, is required for navigation applications. We use GCD (great circle distance) to estimate flight time between two locations. It is also used for celestial distance measurement. We can use various available mathematical formulas to calculate this distance. For this blog, I decided to provide the python implementation for three such formulas. One thing to remember is that this assumes a flat earth surface. So you have to float over oceans and dig through mountains to match this distance.
Law of Cosines
I will start with the easiest formula for this problem known as ‘law of cosines’. This is a mathematical formula that accurately provides the length of the chord that joins the two points. This formula converts over to Pythagorean formula when angle if 90 degrees.Given that we want to travel between two points,
![]()
![]()
![]()
* All angles are in radians
: Latitudes (1 and 2)
: Longitudes
: Angle formed at center by these points d: Distance between the points R: Mean radius of Earth
The primary issue with this approach is that it assumes that earth is spherical. Also, based on what I have read online, for short distances it is not as accurate either.
Since we will use all angles as Radians, we will convert them to radians as soon as class initializes.
def __init__(self, point_a: tuple, point_b: tuple): self.point_A_lat = radians(point_a[0]) self.point_A_lon = radians(point_a[1]) self.point_B_lat = radians(point_b[0]) self.point_B_lon = radians(point_b[1])
def calc_distance(self): ang_A = sin(self.point_A_lat) * sin(self.point_B_lat) ang_B = cos(self.point_A_lat) * cos(self.point_B_lat) * cos(self.point_B_lon - self.point_A_lon) ang_C = acos(ang_A + ang_B) dist = MEAN_RADIUS * ang_C print('Distance by Law of Cosines: %.2f m or %.2f miles' % (dist, dist * 0.0006213712)) return dist
Above code is self explanatory. We are following the exact steps that I have provided above.
Haversine
Haversine, or half versed sine, is one more formula that is used to calculate the straight line distance between two coordinates on earth. This also assumes that earth surface is a round as the basketball.
which gives us:
![]()
That is not the easiest formula, but it does give better results apparently than law of cosines. We provide below the implementation in Python.
def calc_distance(self): delta_lat = self.point_B_lat - self.point_A_lat delta_lon = self.point_B_lon - self.point_A_lon haversine_val = (sin(delta_lat * 0.5) ** 2) + (sin(delta_lon * 0.5) ** 2) * \ cos(self.point_A_lat) * cos(self.point_B_lat) dist = 2 * MEAN_RADIUS * asin(sqrt(haversine_val)) print('Distance by Haversine: %.2f m or %.2f miles' % (dist, dist * 0.0006213712)) return dist
Here we calculate the delta for latitude and longitude first. Next we calculate the value for d/2R sine squared. Finally, we calculate the distance. In this case we also take mean earth radius for calculation.
Vincenty’s formula
Vincenty’s formula was first derived by Thaddeus Vincenty. This formula will give the most accurate results of all as it considers the flatness of the earth. We calculate the polar radius of the earth assuming a flatness correction factor of 1/298.25722. This means that earth is flatter towards the pole and bulges towards the equator.
There are two different formulae provided by Vincenty, Direct and Inverse. We need direct when we know one point and the distance. In this case we will find out the second point on earth. However, for our problem, we are interested in Inverse formula. We use the inverse formula when we need to calculate the distance between two given points.
Please refer to Wikipedia for Vincenty’s formula here. I am using a screenshot from Wikipedia here for reference. I have no intent to write all these equations in tex :).

This is the longest code that we need to calculate geodesic distance.
def calc_distance(self): val_l = self.point_B_lon - self.point_A_lon val_u1 = atan((1 - FLAT_CORRECT) * tan(self.point_A_lat)) val_u2 = atan((1 - FLAT_CORRECT) * tan(self.point_B_lat)) val_sin_u1 = sin(val_u1) val_cos_u1 = cos(val_u1) val_sin_u2 = sin(val_u2) val_cos_u2 = cos(val_u2) val_lambda = val_l cos_sq_alpha = None val_sigma = None sin_sigma = None cos_sigma = None cos2_sigma_m = None for i in range(0, Vincenty.max_iters): i += 1 sin_lambda = sin(val_lambda) cos_lambda = cos(val_lambda) sin_sigma = sqrt((val_cos_u2 * sin(val_lambda)) ** 2 + (val_cos_u1 * val_sin_u2 - val_sin_u1 * val_cos_u2 * cos_lambda) ** 2) cos_sigma = val_sin_u1 * val_sin_u2 + val_cos_u1 * val_cos_u2 * cos_lambda val_sigma = atan2(sin_sigma, cos_sigma) sin_alpha = (val_cos_u1 * val_cos_u2 * sin_lambda) / sin_sigma cos_sq_alpha = 1 - sin_alpha ** 2 cos2_sigma_m = cos_sigma - ((2 * val_sin_u1 * val_sin_u2) / cos_sq_alpha) val_c = (FLAT_CORRECT / 16) * cos_sq_alpha * (4 + FLAT_CORRECT * (4 - 3 * cos_sq_alpha)) val_lambda_prv = val_lambda val_lambda = val_l + (1 - val_c) * FLAT_CORRECT * sin_alpha * \ (val_sigma + val_c * sin_sigma * (cos2_sigma_m + val_c * cos_sigma * (-1 + 2 * cos2_sigma_m ** 2))) val_diff = abs(val_lambda_prv - val_lambda) if val_diff <= Vincenty.tolerance: break val_u_sq = cos_sq_alpha * ((EQTR_RADIUS ** 2 - POLR_RADIUS ** 2) / POLR_RADIUS ** 2) val_a = 1 + (val_u_sq / 16384) * (4096 + val_u_sq * (-768 + val_u_sq * (320 - 175 * val_u_sq))) val_b = (val_u_sq / 1024) * (256 + val_u_sq * (-128 + val_u_sq * (74 - 47 * val_u_sq))) delta_sig = val_b * sin_sigma * (cos2_sigma_m + 0.25 * val_b * ( cos_sigma * (-1 + 2 * cos2_sigma_m ** 2) - (1 / 6) * val_b * cos2_sigma_m * ( -3 + 4 * sin_sigma ** 2) * (-3 + 4 * cos2_sigma_m ** 2))) dist = POLR_RADIUS * val_a * (val_sigma - delta_sig) print('Distance by Vincenty: %.2f m or %.2f miles' % (dist, dist * 0.0006213712)) return dist
As I said before, this will provide the most accurate result. However, we have to perform a lot more calculation here. So, if you do not need very accurate results and lean towards performance, you can use the other equations.
Comparison
We will run a few comparison and see what value we get between each of them (in miles).
Destination | Law of Cosines | Haversine | Vincenty |
Milan to Paris | 397.3939 | 397.3939 | 398.1266 |
New York to new Delhi | 7304.0584 | 7304.0584 | 7317.9312 |
BC to Abu Dhabi | 7033.6936 | 7033.6936 | 7046.7748 |
Kolkata to Berlin | 2478.0766 | 2478.0766 | 2485.7594 |
Kenya to Auckland | 8633.2939 | 8633.2939 | 3795.4240 |
Everything seems to be aligning nicely. However, we see a drastic difference in the calculation between Kenya and Auckland. On investigation, it looks like the numbers returned by Haversine/ Law of Cosines is much closer to the actual. If I calculate it on distance calculator website,

However, the Vincenty’s answer also matches when I test it on WGS-84 website.

I do not know why there is a mismatch. I will try to find out and if I can, I will update the blog.
For completeness, here is the output from code.
Calculating distance between Milan & Paris [(48.85341, 2.3488) -> (45.46427, 9.18951)]:
Distance by Law of Cosines: 639543.4029 m or 397.3939 miles
Distance by Haversine: 639543.4029 m or 397.3939 miles
Distance by Vincenty: 640722.6394 m or 398.1266 miles
Calculating distance between NY & New Delhi [(40.712776, -74.005974) -> (28.613939, 77.209023)]:
Distance by Law of Cosines: 11754742.3641 m or 7304.0584 miles
Distance by Haversine: 11754742.3641 m or 7304.0584 miles
Distance by Vincenty: 11777068.5849 m or 7317.9312 miles
Calculating distance between BC & Abu Dhabi [(53.726669, -127.647621) -> (24.453884, 54.377342)]:
Distance by Law of Cosines: 11319632.4995 m or 7033.6936 miles
Distance by Haversine: 11319632.4995 m or 7033.6936 miles
Distance by Vincenty: 11340684.6690 m or 7046.7748 miles
Calculating distance between Kolkata & Berlin [(88.363895, 22.572646) -> (52.520008, 13.404954)]:
Distance by Law of Cosines: 3988077.6989 m or 2478.0766 miles
Distance by Haversine: 3988077.6989 m or 2478.0766 miles
Distance by Vincenty: 4000441.9305 m or 2485.7594 miles
Calculating distance between Kenya & Auckland [(37.906193, -0.023559) -> (174.763331, -36.84846)]:
Distance by Law of Cosines: 13893939.4862 m or 8633.2939 miles
Distance by Haversine: 13893939.4862 m or 8633.2939 miles
Distance by Vincenty: 6108142.8142 m or 3795.4240 miles
Process finished with exit code 0
As always you can find the source codes at github/chakrab. Ciao for now!