# How to calculate distances in a point sequence?

I'm looking for help calculating the distance between a sequence of points that are in a single Shapefile in QGIS. Below is what my data look like and a blank distance column I've added to show how I'd like the distance to look. I want to know the distance between point 1 and 2, 2 and 3, etc. I'd like distance to be in meters or Km, but currently my Shapefile is in a projection whose units are decimal degrees.

``````ID  LAT         LON         TIME        DISTANCE
1   10.08527    124.59833   21:24:37    0
2   10.08523    124.59830   21:25:07    ?
3   10.08526    124.59832   21:25:37    ?
4   10.08526    124.59831   21:26:07    ?
``````

A number of people have asked similar questions, but none quite get at what I want to do. This post is close, but this is in PostGIS, not QGIS Calculate distances between series of points in postgis

This post got me part of the way there, but since I'm new to QGIS the answer doesn't provide enough detail for me. For example, once I've installed the GRASS plugin, I think I need to save/import the Shapefile with my series of GPS points into GRASS so I can use the v.distance module, but I don't know how to do that. QGIS calculate distance of point along a line

Is the GRASS v.distance module the only way to go? Or is there a more straight forward way? If v.distance is the only way would someone be able to point me to or explain more step-by-step how to do this?

-
@underdark How can we do that in excel ? – user2207232 Mar 26 '13 at 22:53

I return to this issue because it is very similar to How do I find vector line bearing in QGIS or GRASS? and it can be solved with Python in the same way:

1) Haversine distance

One can find lots of scripts by searching Haversine distance with Python on the Internet and I choose one of them in Haversine Formula in Python (Bearing and Distance between two GPS points)

``````def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(math.radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2
c = 2 * math.asin(math.sqrt(a))
km = 6367 * c
return km
``````

We have a series of lines (points) in the file that must be treated in pairs (point1 - point2) to calculate the distance. For this we will use a simple iterator from Most pythonic way to get the previous element

``````def offset(iterable):
prev = None
for elem in iterable:
yield prev, elem
prev = elem
``````

Now it is possible to read the file (example of Kerrie) in pairs of lines/points

``````import csv
with open('testhavers.csv', 'rb') as f:
print pair

(None, {'LAT': '10.08527', 'LON': '124.59833', 'ID': '1', 'TIME': '21:24:37'})
({'LAT': '10.08527', 'LON': '124.59833', 'ID': '1', 'TIME': '21:24:37'},
{'LAT':    '10.08523', 'LON': '124.59830', 'ID': '2', 'TIME': '21:25:07'})
({'LAT': '10.08523', 'LON': '124.59830', 'ID': '2', 'TIME': '21:25:07'},
{'LAT': '10.08526', 'LON': '124.59832', 'ID': '3', 'TIME': '21:25:37'})
({'LAT': '10.08526', 'LON': '124.59832', 'ID': '3', 'TIME': '21:25:37'},
{'LAT':    '10.08526', 'LON': '124.59831', 'ID': '4', 'TIME': '21:26:07'})
``````

Then create a shapefile containing the original fields of the csv file and a new field for the distance with the Python modules Shapely and Fiona of Sean Gillies:

``````import fiona
from shapely.geometry import Point, mapping
# creation of the schema of the shapefile (geometry and fields)
schema = { 'geometry': 'Point', 'properties':{'ID': 'int', 'LAT':'float', 'LON':'float', 'TIME':'str','distance' : 'float'}}
# creation of the shapefile:
with fiona.collection("result.shp", "w", "ESRI Shapefile", schema) as output:
with open('testhavers.csv', 'rb') as f:
# we need here to eliminate the first pair of point with None
if i == 0: (pair with None)
# writing of the point geometry and the attributes
point = Point(float(pair[1]['LON']), float(pair[1]['LAT']))
dist = 0 # None
output.write({'properties': {'ID':int(pair[1]['ID']),'LAT':float(pair[1]['LAT']),'LON':float(pair[1]['LON']), 'TIME':pair[1]['TIME'],'distance': dist},'geometry': mapping(point)})
else:
# writing of the point geometry and the attributes
point = Point(float(pair[1]['LON']), float(pair[1]['LAT']))
# Haversine distance between pairs of points
dist = haversine(float(pair[0]['LON']), float(pair[0]['LAT']), float(pair[1]['LON']),float(pair[1]['LAT']))
output.write({'properties': {'ID':int(pair[1]['ID']),'LAT':float(pair[1]['LAT']),'LON':float(pair[1]['LON']), 'TIME':pair[1]['TIME'],'distance': dist},'geometry': mapping(point)})
``````

and the result:

It is also possible to do it with PyQGIS but it is more complex than Fiona which uses simple dictionaries to create shapefiles.

You can use another function to calculate the Haversine distance (Why is law of cosines more preferable than haversine when calculating distance between two latitude-longitude points?) without any problem, only the distance calculation changes, not the process of creating the shapefile.

-

If you're familiar with r, try using a combination of the 'sp' and 'dismo' package.

For example like this (assuming to have points with x,y coordinates):

``````library(sp)
library(dismo)

coordinates(data) <- ~x+y # point them to your coordinates to make a spatialpoint layer
# Or like this:
Pointlayer <- SpatialPoints(cbind(data\$x,data\$y))

d <- pointDistance(pp,longlat=F)

# Looks for example like this:
[,1]     [,2]     [,3]     [,4]     [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
[1,]  0.000000       NA       NA       NA       NA   NA   NA   NA   NA    NA    NA    NA
[2,] 54.561891  0.00000       NA       NA       NA   NA   NA   NA   NA    NA    NA    NA
[3,] 25.000000 73.49830  0.00000       NA       NA   NA   NA   NA   NA    NA    NA    NA
[4,] 50.487622 43.93177 53.14132  0.00000       NA   NA   NA   NA   NA    NA    NA    NA
[5,]  4.123106 57.00877 26.30589 54.58938  0.00000   NA   NA   NA   NA    NA    NA    NA
[6,] 32.249031 37.21559 57.14018 60.30755 32.01562    0   NA   NA   NA    NA    NA    NA

``````
-

Perhaps the distance matrix tool might help? It's under the Vector menu. For each point this will calculate the distance to each of the other points and store the result in a CSV file.

If you want the distances in metres I think it would make sense to transform your points from lat/lon to a projected shapefile (possibly UTM51 in your case) before using the tool.

N.

-

Use v.to.db in GRASS (e.g. via Sextante plugin) with option=length (line length).

Example of uploading line lengths (in meters) of each vector line to attribute table (fill the corresponding fields in the GUI):

`v.to.db map=roads option=length type=line col=linelength units=me`

-

I find this problem is easiest to solve by working in a spreadsheet, don't use the gis. I found the work of Chris Veness to be very helpful -

http://www.movable-type.co.uk/scripts/latlong.html

If you scroll the the bottom paragraph, you will find links to two excel sheets, which are;

http://www.movable-type.co.uk/scripts/latlong-distance+bearing.xls

http://www.movable-type.co.uk/scripts/latlong-dest-point.xls