Get distance between two geo locations

Recently I was posed an interesting work hack to quickly calculate distance measured in miles or kilometers given a set of LatLngs (latitudes and longitudes).  The data points were in input files in csv format. File also had other other details.

# For quick visual check, I used vim and separated tabulate it with
:%column -t -s ,

 

www-gifcreator-me_wgsrhd

Following Python code generated the output between two consecutive LatLngs.


import math
import re
import sys
import csv
import json
import googlemaps
import ConfigParser
from datetime import datetime
import LatLon

def get_orders_zip(file):
    csv_rows = []
    with open(file) as csvfile:
        reader = csv.DictReader(csvfile)
        title = reader.fieldnames
        for row in reader:
            csv_rows.extend([{title[i]:row[title[i]] for i in range(len(title))}])

    # print csv_rows[0]
    for order in csv_rows[0:1]:
        lat, lng = (order['stop_latitude'], order['stop_longitude'])
        place = gmap.reverse_geocode((lat, lng))
        # print json.dumps(place, indent=4, sort_keys=True)
        for idx, pl in enumerate(place):
            print json.dumps(pl['address_components'][0], indent=4, sort_keys=True)
            for ix, ac in enumerate(pl):
                print ac
                for ix, ty in enumerate(ac):
                    print ty
                # print json.dumps(ob, indent=4, sort_keys=True)
                # print ob['types']['types'][0]

# Get distance
def calc_dist(file):
    csv_rows = []
    with open(file) as csvfile:
        reader = csv.DictReader(csvfile)
        title = reader.fieldnames
        for row in reader:
            csv_rows.extend([{title[i]:row[title[i]] for i in range(len(title))}])

    # print csv_rows[0]
    nxt = tot_miles = 0
    for idx, cur in enumerate(csv_rows):
        if idx < len(csv_rows) - 1:
            nxt = csv_rows[idx+1]

            lng1, lat1 = (cur['stop_longitude'], cur['stop_latitude'])
            lng2, lat2 = (nxt['stop_longitude'], nxt['stop_latitude'])

            dist = conv_km_to_miles(lng1, lat1, lng2, lat2)
            tot_miles += dist
            print '{0:.3f} miles'.format(dist)

    print "Total distance coverd: {0:.4f} miles".format(tot_miles)
    return True

def conv_km_to_miles (lng1, lat1, lng2, lat2):
    # Convert degrees to radians
    lng1 = conv_deg_to_rad(lng1)
    lat1 = conv_deg_to_rad(lat1)
    lng2 = conv_deg_to_rad(lng2)
    lat2 = conv_deg_to_rad(lat2)

    km_to_miles = 0.621371

    return (conv_lng_lat_to_dist(lng1, lat1, lng2, lat2)*km_to_miles)

def conv_lng_lat_to_dist (lng1, lat1, lng2, lat2):
    R   = 6371 # Earth mean radius [km]
    lng = (lng2 - lng1)
    lat = (lat2 - lat1)
    a   = math.sin(lat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(lng/2)**2
    c   = 2 * math.asin(min(1,math.sqrt(a)))
    d   = R * c
    return (d) # Distance in km

def conv_deg_to_rad(deg):
    return float(deg)*math.pi/180

# Set up and return gmap
def initialize():
    cfg = ConfigParser.ConfigParser()
    cfg.readfp(open('./ge.cfg'))
    key = cfg.get('main', 'key')
    return googlemaps.Client(key)

# Get zipcodes for orders
if __name__ == '__main__':
    gmap = initialize()
    calc_dist_2('./sample_one_route.csv')  # Replace above with LatLng module

The output generated.


0.257 miles
0.629 miles
0.644 miles
0.711 miles
1.019 miles
0.429 miles
0.245 miles
1.793 miles
1.200 miles
2.775 miles
0.179 miles
0.153 miles
0.312 miles
Total distance coverd: 10.3458 miles

There are also other packages or APIs available that will simplify this further. For example, you can make google API call to distance matrix or use Python LatLng module.

# Get distance
def calc_dist_2(file):
    csv_rows = []
    with open(file) as csvfile:
        reader = csv.DictReader(csvfile)
        title = reader.fieldnames
        for row in reader:
            csv_rows.extend([{title[i]:row[title[i]] for i in range(len(title))}])

    # print csv_rows[0]
    nxt = tot_miles = 0
    for idx, cur in enumerate(csv_rows):
        if idx < len(csv_rows) - 1:
            nxt = csv_rows[idx+1]

            loc1 = LatLon.LatLon(cur['stop_latitude'], cur['stop_longitude'])
            loc2 = LatLon.LatLon(nxt['stop_latitude'], nxt['stop_longitude'])

            dist = loc1.distance(loc2) * 0.621371 # Km to miles
            tot_miles += dist
            print '{0:.3f} miles'.format(dist)

    print "Total distance coverd: {0:.4f} miles".format(tot_miles)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s