TL;DR - By making a few geometric assumptions, the Haversine formula provies an exceptionally simple way of calculating distance between two latitude/longitude pairs. This tutorial will show you how to implement your own version in Python.

A lot of my posts recently have focused on the analysis of spacial data coming from either the GPS on my phone (collected through Strava) or geo-tagged tweets. Because of this I ended up writing my own Python module for calculating the distance between two latitude/longitude pairs. This is accomplished using the Haversine formula. While more accurate methods exist for calculating the distance between two points on earths surface, the Haversine formula and Python implementation couldn’t be any simpler. Below is a breakdown of the Haversine formula.

Haversine:

$$ a=\sin^2\left(\frac{\Delta\phi}{2}\right) +\cos(\phi_1)\cdot\cos(\phi_2)\cdot\sin^2\left(\frac{\Delta\lambda}{2}\right)$$

With:

$$ c=2\cdot arctan2\left(\sqrt{a},\sqrt{1-a}\right) $$

and:

$$ d=R\cdot c $$

Where:

\( \phi \) = latitude
\( \lambda \) = longitude
\( R \) = 6371 (Earth’s mean radius in km)

Much of Haverines’ simplicity comes from the underlying assumption that Earth is a perfect sphere (which it isn’t…). Because of this, it can lead to errors of up to 0.5%. More accurate methods exist but at the expense of computational complexity. Below is the Python implementation:

#------------------------------------------------------------------------------+
#
#   Nathan A. Rooy
#   Haversine Formula
#   June, 2016
#
#------------------------------------------------------------------------------+

import math

class Haversine:
    '''
    use the haversine class to calculate the distance between
    two lon/lat coordnate pairs.
    output distance available in kilometers, meters, miles, and feet.
    example usage: Haversine([lon1,lat1],[lon2,lat2]).feet
    
    '''
    def __init__(self,coord1,coord2):
        lon1,lat1=coord1
        lon2,lat2=coord2
        
        R=6371000                               # radius of Earth in meters
        phi_1=math.radians(lat1)
        phi_2=math.radians(lat2)

        delta_phi=math.radians(lat2-lat1)
        delta_lambda=math.radians(lon2-lon1)

        a=math.sin(delta_phi/2.0)**2+\
           math.cos(phi_1)*math.cos(phi_2)*\
           math.sin(delta_lambda/2.0)**2
        c=2*math.atan2(math.sqrt(a),math.sqrt(1-a))
        
        self.meters=R*c                         # output distance in meters
        self.km=self.meters/1000.0              # output distance in kilometers
        self.miles=self.meters*0.000621371      # output distance in miles
        self.feet=self.miles*5280               # output distance in feet

if __name__ == "__Haversine__":
    main()

Example usage:

>>> import haversine
>>> Haversine([-84.412977,39.152501],[-84.412946,39.152505]).feet 
8.890493621837097

>>> Haversine((-84.412977,39.152501),(-84.412946,39.152505)).feet 
8.890493621837097

>>> Haversine((-84.412977,39.152501),(-84.412946,39.152505)).km 
0.0027098232942902385

>>> Haversine((-84.412977,39.152501),(-84.412946,39.152505)).miles 
0.00168380561019642

Note haversine script accepts the coordinates in both tuple “()” and list “[]” form. Additionally, the script can be downloaded from my GitHub located (here).