Calculating distance between consecutive points in same point layer in QGIS

I have a point layer with close to 60.000 points that depict a river course (pixel extracts from satellite image). CRS of the layer is Geographic (Lat, Long).

The pixels are ordered ascendingly from source to outlet with an `"ID"` and each pixel has latitude and longitude. I want to know the distance in meter between two consecutive points (e.g. between point `"ID"=35144` and `"ID"=35145`, between `"ID"=35145` and `"ID"=35146`, etc.). This sounds very simple but I tried in numerous ways but failed.

I have tried:

• to transform the point layer to a line layer to measure the line segments. However, using the Vector Geometry (points to path) or diverse plugins such as NNJoin or MMQGIS I loose the vertexes (individual pixels) and therefore the point to point distance
• to create a distance matrix but this gets messy too, because it is the same layer. Also, other "nearest neighbour"-tools do not work since it is the same layer.
• to use the field calculator and loop through the rows of my dataset --> but how?

You can use the following script in QGIS Python Editor. It returns the distance in meter for geographic crs.

Note: `ID` field should be integer/numeric. If it is string, you get wrong order like: `1, 10, 11, ..., 2, 20, 21, ..., 3, 30, 31, ...`

``````layer_name = 'POINT_LAYER_NAME'
id_field_name = 'ID'

# get layer by name
layer = QgsProject.instance().mapLayersByName(layer_name)[0]

# Add new field. DIST_TO_NXT: distance to the next feature
layer.updateFields()

# get the sorted feature list
feats = list(layer.getFeatures(request))

# find the field's index
field_index = layer.fields().indexFromName("DIST_TO_NXT")

da = QgsDistanceArea()
da.setEllipsoid(layer.crs().ellipsoidAcronym())
# or maybe
# da.setEllipsoid(QgsProject.instance().ellipsoid())

# skipped the last point, not to get IndexError.
for i in range(len(feats[:-1])):
p1 = feats[i].geometry().asPoint()
p2 = feats[i+1].geometry().asPoint()

distance = da.measureLine(p1, p2)

layer.dataProvider().changeAttributeValues(
{feats[i].id(): {field_index: distance}})
``````

PS: The last distance is always NULL.

• Nice solution, I will also appropriate the last distance with `NULL` (vice versa to @BERA), but maybe this `0` (zero). Commented Jan 26, 2022 at 7:38
• Hello. Can you help me with the calculation. I create a layer named POINT_LAYER_NAME by adding 4 points with an ID field. I enter the script and QGIS returns a message, Layer 'POINT_LAYER_NAME': Field -1 from object 2 doesnt exist. Why it happens that way ? Commented Feb 6, 2022 at 14:29
• @NikolayYordanov Did you specify a field name in `field_index = layer.fields().indexFromName("DIST_TO_NXT")`. You have to change `DIST_TO_NXT` to your field name. Commented Feb 6, 2022 at 21:23
• Thanks, it works fine but when the points are more than 10, something goes wrong. The distance between the points in my work file are approximately 130 meters away. When I add 10 points with an approximate distance of 130 meters the calculation looks like this: 1-1255, 2-139, 3-141, 4-134, 5-133, 6-132, 7-173, 8-158, 9-Null, 10-1126. Where am I wrong ? Commented Feb 7, 2022 at 16:01
• @NikolayYordanov You should also specify `id_field_name` (containing values 1, 2, ...10 ). In this example, it is `ID`. And `ID` field should be numeric, not string. Your id field is probably string so QGIS returns the order as 1, 10, 11, 2, 3, 4. ... Commented Feb 8, 2022 at 13:28

I'm sure there's some less complicated way, but you can use pyqgis like this:

``````lyr = QgsProject.instance().mapLayersByName('Vertices')[0] #Change Vertices to the name of your layer

orderfield = 'vertex_index' #Change to the name of you order field
distancefield = 'distance' #Field to store the distances in. Add before executing script

features = [[f.id(), f[orderfield], f.geometry()] for f in lyr.getFeatures()] #List all points id, orderfield value and geometry
features.sort(key=lambda x: x[1]) #Sort the list by orderfield
distancefieldindex = lyr.fields().indexFromName(distancefield) #Find index of distancefield

attrmap = {} #A dictionary to store each points id, distance field index and distance in
for e, (f1, f2) in enumerate(zip(features[::1], features[1::1])): #For each point pair, for example point 1 and point2, then point2 and point3
if e==0: #If first point set distance to 0
attrmap[f1[0]]={distancefieldindex:0}
else: #Else calculate the distance between the two points
attrmap[f1[0]]={distancefieldindex:f1[-1].distance(f2[-1])}

lyr.dataProvider().changeAttributeValues(attrmap) #Update the values
print('Done')
``````

I am not sure if this is the best / fastest way, but I think it should work for you:

``````length(
make_line(
\$geometry,
geometry(
get_feature_by_id('*NAME/ID_of_your_layer*', "*ID_field*"+1)
)
)
)
``````

For `"ID"` 1 you will get the length from 1 to 2, for 2 you will get 2 to 3 ... for your last point you won't get a length.

• @ Kadir : thanks for that proposition. The formula is correct and a distance is calculated. However, the results are in degrees and are subsequently rounded to 0 if the decimal number is not chosen with enough digits... (the distance between the points is small, between 10 and 20 meters) . In my properties I had set "meters" for area/distance calculations but this doesn't apply to the layer. How can I first transform the Lat Long of the dataset to something metric before doing the calculation you suggest ? Thanks! Commented Jan 25, 2022 at 15:44
• use the transform function to project from a geographic to a metric system: docs.qgis.org/3.22/en/docs/user_manual/expressions/… Commented Jan 26, 2022 at 8:12