I've been looking through all of the GRASS commands in the QGIS 2.10 processing toolbox and it seems like one of these must be able to do this but I haven't found one yet. There is 'v.sample' which can sample a DEM at a point location. Is there a way to do something similar to sample a DEM when calculating the length of a line segment?
5 Answers
You can also calculate the length of a line taking into account the topography the following way:
Use the "Profiles from line" (SAGA) tool, which adds points along the line, giving the length from the line start to each point ("DIST" as the length on a flat surface, "DIST_SURF" with heights included).
Select the point with the maximum length value with "extract by expression". If you have multiple lines, use this expression: "DIST_SURF" = maximum("DIST_SURF","LINE_ID")
, which will extract the max. point for each line.
Then join these values back to the original line layer, taking only "DIST_SURF" from the point layer.
Admittedly it's not in GRASS but it still works.
Yes and you can automate this process with python grass.script or bash script (bat script in Windows). I test it in my system and the individual commands are (for my line vector named route and raster dem named utah_demUTM2):
v.to.rast input=route value=1 output=route_raster
r.thin input=route_raster output=route_raster_thin
r.mapcalc route_raster_dem="if(route_raster_thin, utah_demUTM2)" #in GRASS console
to produce route_raster_dem with the raster values (see next image where I used the plugin Value Tool).
Afterward, you can use the command r.to.vect.points to create points (distance between points equal to raster resolution) along input line route_raster_dem for calculating the 3D length of the line segment by using the adequate algorithm (with code or in a spreadsheet).
At the next image you can see some selected features at the start of route_vector_dem (obtained by using r.to.vect.points) and its attributes table.
3D distance is the sum of the length of the hypotenuse given by the difference in height between two adjacent segments along the line (the individual steps are the same as the raster resolution).
-
dredging up the past here. Thank you @xunilk for the interesting answer, this does work, but a bit cumbersome to go to raster and then calc manually. I'm adding a 2021 qgis3 'almost' answer to this below.– jamierobFeb 24, 2021 at 15:05
I was facing the same problem and here was my approach:
I used "Drape (set Z value from raster)" to add z-value from DEM to vector nodes
checked in field calculator if it really generated those by using
z_min($geometry)
< just see if something shows up in bottom previewthen I used following formula to calculate in a new field 3D length for all segments
sqrt( $length ^ 2 + (z_max($geometry) - z_min($geometry)) ^ 2 )
You can use Show Statistical Summary and sum up your lengths, ideally they should differ :)
NB! I started from a 1m DEM and sampled it down to 10m resolution and combined multiple tiles into a virtual raster. Just bear this in mind, otherwise might have to wait for an eternity...
Using QGIS3, it's possible to use v.drape in the processing toolbox to attach z-values from a DEM to a vector layer of linestrings. The output layer will be MultiLinestringZ.
As far as I know there is still no way in QGIS to then calculate the 3d length of those features and add them as an attribute because the $length function only calculates 2d length.
If you output this MultilinestringZ file to .gpx, however, you can see that the z-values attached from the DEM during the v.drape are correct and attached to each track point.
I'm calculating 3D line lengths for my work right now and came across this thread. I just wanted to make the update that there is now a function available in the field calculator called "length3d" which calculates the 3D length of Z-enabled line geometries. Docs here: https://docs.qgis.org/3.28/en/docs/user_manual/expressions/functions_list.html#length3d