2

In QGIS (3.34 at the time of writing), the "Drape (set Z value from raster)" algorithm (native:setzfromraster) allows the user to assign a Z value to a given vector geometry using a raster layer:

Drape (set Z value from raster)
This algorithm sets the z value of every vertex in the feature geometry to a value sampled from a band within a raster layer.
The raster values can optionally be scaled by a preset amount and an offset can be algebraically added.

This is based on a value-sampling under each vertex, so it's a nice tool when working with points. But it's not well suited for other geometry types. For example, if a line having only "start" and "end" vertices crosses a valley, the 3D line generated with this algorithm will be a line floating in space over the valley:

enter image description here

Instead of something similar to:

enter image description here

This would of course yield to add additional vertices to the geometry.

So my question is: is there a tool in QGIS to achieve this result?
If not, do you know any other tool that can achieve that?

1
  • 4
    Densify the geometry by using the pixel size as an interval before running drape. As a result there may be two vertices within the same pixel here and there but that does not feel too bad for me.
    – user30184
    Commented Mar 25 at 12:23

1 Answer 1

2

You can:

  1. Buffer the line with a small distance, like the pixel size*2
  2. Clip the raster with the buffer
  3. Raster pixel to points
  4. Shortest line between features, points as source, input line layer as destination, max distance your pixel size. To create lines from each point (pixel center) to the input line
  5. Extend lines by a short distance so the lines cross the input line layer.

Steps 1 to 5 is just to create the yellow lines to split the input line layer with: enter image description here

  1. Split the input line layer with the extended lines to split the line at the nearest pixel centroid
  2. Drape the output on the raster
  3. Dissolve (keep disjoint features separate)

This will create a vertex at the nearest point on the line to the nearest raster pixel and give it the Z value of that pixel.

enter image description here

The lines become linestringz with z values:

input_line_layer = QgsProject.instance().mapLayersByName("path")[0]
for f in input_line_layer.getFeatures():
    g = f.geometry()
print(g)
#There are no Z values:
#<QgsGeometry: LineString (583796.50100680498871952 7459416.78863538522273302, 584407.45742262701969594 7459954.17438333388417959, 584346.68165351380594075 7460379.60476712603121996, 585018.41383844905067235 7460430.78436216898262501, 585155.95900012622587383 7459902.99478829093277454)>

model_output_layer = QgsProject.instance().mapLayersByName("Dissolved")[0]
for f in model_output_layer.getFeatures():
    g = f.geometry()
print(g)
#Now there are more vertices and each has a Z:
#<QgsGeometry: MultiLineStringZ ((583796.50100680498871952 7459416.78863538522273302 1175.6644287109375, ...

enter image description here

1
  • Thank you for your very nice proposal! But I'm not always 100% sure if you are speaking about 3D or 2D. E.g. at point 3: "Raster pixel to points". Is it 2D or 3D points here? So, could you maybe precise if you're using 3D or 2D geometry at each stage where this can be confusing? Commented Mar 30 at 12:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.