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 ,
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)