I have a shapefile of 200 lines (all connected) with the coordinates x and y and a DEM raster. I would like to give the z value to the lines by taking it from the raster.

I have read several discussion on how to do the same operation with a points shapefile but I was wondering if would be possible to have the same results with lines. Maybe applying the z-value to a line vertex, or calculating the average elevation of the line length? • Have you tried Drape (set z-value from raster) tool? Apr 13 '20 at 10:41
• Yes, but he does not add the extra column. Apr 13 '20 at 11:45
• What kind of 'extra column' do you expect? Apr 13 '20 at 11:47
• I am expecting an extra column with the altitude value: e.g.  line, altitude 57meters. Apr 13 '20 at 12:02

You can use the Field Calculator to create a new elevation field, using a way similar to the point layer. The operation will give you a punctual information extract from the raster.

In the line layer's Attribute Table use the Field Calculator to create a new field (numeric, real) with this expression

raster_value('DEM_NAME', 1, start_point(\$geometry))
+
raster_value('DEM_NAME', 1, end_point(\$geometry))/2

changing the value DEM_NAME with the name of your DEM.

This will create a new field with the average of the elevations calculated at the beginning and at the end of the line.

But if you want to calculate a more accurate average you can, still using the Field Calculator, use a more complex expression that calculates the elevation average recorded at n points along your line.

Considering that using the expression

collect_geometries(array_foreach(
generate_series(0, length(\$geometry)/10, 1),
line_interpolate_point(\$geometry,@element * 10)))

you can create a sequence of points along your line (as observable in the image below) starting from 0 to the end of the line, with 1 meter of distance you can extract from your raster the elevation of each of those points and calculate the average elevation of all them.

To do it, you can use the following expression:

array_sum(
array_to_string(
array_foreach(
array_foreach(
generate_series(0, length(\$geometry)//10, 1),
line_interpolate_point(\$geometry, @element * 10)),
expression:=raster_value('DEM_NAME', 1, collect_geometries(@element))
),
delimiter:=' ,'))
/
array_length(
array_foreach(
generate_series(0, length(\$geometry) // 10, 1),
line_interpolate_point(\$geometry, @element * 10)))

The resultant data will be the sum of calculation of all the elevations in all of the points (calculated by array_sum) divided by the number of points (calculated by array_length).

This is the result: ADDENDUM: If you want a rounded number for your elevation just add round( at the beginning of the expression and close all the adding a ) at the end of all.

I had a similar issue some time ago. If you want to split your lines into segments of a given lenght and then calculate the slope of the segments:

Calculate slope of line segments with QGIS