Dynamic elevation profile lines as QGIS geometry generator

Note: You need the current master build of QGIS or wait for QGIS 3.10. I’m a cool kid.

Load a raster layer in QGIS.

Add a new Scratch Layer of Polygon type (in any CRS). Set its Symbology to Inverted Polygons. Use a Geometry Generator as symbol layer type. Set it to LineString/MultiLineString. Enter the expression below and adjust the layer ID (best enter the expression editor and find it in the “layers” tree). Then adjust the scaling factor at the very bottom.

-- UPPER CASE comments below are where you can change things

	'long_and_complicated_layer_id',  -- RASTER LAYER to sample from
	-- this collects all the linestrings generated below into one multilinestring
		-- a loop for each y value of the grid
			-- array_foreach loops over all elements of the series generated below
			-- which is a range of numbers from the bottom to the top of y values
			-- of the map canvas extent coordinates.
			-- the result will be an array of linestrings
				y(@map_extent_center)-(@map_extent_height/2), -- bottom y
				y(@map_extent_center)+(@map_extent_height/2),  -- top y
				@map_extent_height/50  -- stepsize -> HOW MANY LINES
			-- we want to enter another loop so we assign the name 'y' to
			-- the current element of the array_foreach loop
				-- now we are ready to generate the line for this y value
					-- another loop, this time for the x values. same logic as before
					-- the result will be an array of points
							x(@map_extent_center)-(@map_extent_width/2), -- left x
							x(@map_extent_center)+(@map_extent_width/2),  -- right x
							@map_extent_width/50  -- stepsize -> HOW MANY POINTS PER LINE
						-- and here we create each point of the line
							@element,  -- the current value from the loop over the x value range
							@y  -- the y value from the outer loop
							+   -- will get an additional offset to generate the effect
							-- we look for values at _this point_ in the raster, and since
							-- the raster might not have any value here, we must use coalesce
							-- to use a replacement value in those cases
							coalesce(  -- coalesce to catch raster null values
									1,  -- band 1, *snore*
									-- to look up the raster value we need to look in the right position
									-- so we make a sampling point in the same CRS as the raster layer
										make_point(@element, @y),
								0  -- coalesce 0 if raster_value gave null
							-- here is where we set the scaling factor for the raster -> y values
							-- if things are weird, set it to 0 and try small multiplications or divisions
							-- to see what happens.
							-- for metric systems you will want to multiply
							-- for geographic coordinates you will want to divide
							)*10  -- user-defined factor for VERTICAL EXAGGERATION
)  -- wee

If you don’t have your raster data on a SSD this can be a bit slow.

Yes, this works if you change your CRS!

4 thoughts on “Dynamic elevation profile lines as QGIS geometry generator

  1. Pingback: Dynamic elevation profile lines as @QGIS geometry generator – GeoNe.ws

  2. Toni

    Amazing work!
    I would like to hear more explanation since for some reason, the code does not work for me, and input “collect_geometries” does not exist in qgis 3.4.4

    1. Hannes

      See the note at the very top. This only works in the current development version until the next version is released.


Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.