3

Question

I have a multipart line representing a river, downloaded from OSM. It includes minor branches as well (see screenshot). For cartographic purpose, I want to convert the line to a single part geometry, keeping just one single feature representing the river from source to mouth. I don't care which segments are kept as long as the main course of the river is represented more or less (I will generalize the line anyway).

How can I get rid of multiple branches (side lines) to get a single feature for the whole line?

Screenshot: downloaded river: multipart line with two side branches that I want to delete, keeping just one single line representing the river's general course. However, this section of the river consists of three parts (in different colors), so I can't simply delete one of the parts, just some segments. A valid solution here would be, if the river flows form left to right, deleting the end of the red line and the beginning of the blue line - or, alternatively, start and end of orange line, keeping just the middle section: enter image description here

Context

I downloaded the river line-layer from OpenStreetMap using QuickOSM plugin with waterway=river and name=[Name of the river]. For cartographic purpose, I now want to use a style to show the river with varying width from source to mouth (I additionally use Geometry Generator to generalize and smooth the river's course, but that does not matter here).

This is easy using Symbol layer type Interpolated Line with Start value 0 and End value length($geometry), then load the actual min/max values (0 to the total length of the river) and setting a width at the source and one at the mouth to get a line with steadily increasing width from source to mouth.

Generalized and smoothd line with interpolated line style with varying width - this is how the result should look like: enter image description here

What I tried

Interpolated line style creates the result I'm looking for using a single part line without branches. A workaround is using network tool Shortest path (point to point), selecting manually source and mouth of the river to get one single line (the shortest connection from source to mouth). This works well, but is cumbersome to do for each river separately and I want to automatize it with a model.

Due to the data downloaded from OSM, I can't use start-/end point of the line as the line layer contains several features so I get additional start points somewhere in the middle of the course of the river.

5
  • A starting point could be to use Snap geometries to layer on the river layer with itself, then Split with lines, with the snapped layer as both the inputs this time. This should result in individual segments for all parts of the river. Where there are 3 coincident intersecting vertices gives you the start/end of a branch. Then it's a case of deciding which segment is which. I wondered about buffering an end point and get the azimuth of each of the 3 vertices and the intersections with the buffer. The smallest difference will most likely be the 2 branches - one of these can be deleted.
    – Matt
    Nov 7, 2022 at 21:02
  • Thanks for the idea - not sure I correctly understood it, but it sounds like this has do be done manually... For manual work, I think the network tool works fine. So probably a good option would be if I would be able to manually identify the source and mouth of the river (like first/last vertex). Or maybe I didn't understand it correctly.
    – Babel
    Nov 7, 2022 at 21:06
  • I would hope it is automatable (real word? Not sure) with PyQGIS. Perhaps I am over-thinking it. But if you can determine which segments have a start- or end-point coincident with 2 others, then you know the location of a branch, but not which segments are the single channel, and which 2 are the branches. Maybe the Hausdorff distance between all 3 could be useful..
    – Matt
    Nov 7, 2022 at 21:14
  • 1
    @Matt you comments inspired me to the solution just posted
    – Babel
    Nov 7, 2022 at 21:50
  • So, I was indeed over-thinking it, but I'm glad you managed to filter something useful out of it.
    – Matt
    Nov 8, 2022 at 7:05

1 Answer 1

1

Use the network solution indicated in the "What I tried" section of the answer. The problem can then be reduced to automatically finding the first and last vertex: source and mouth of each river.

This can be automated by identifying those points (vertices) in the multiline that are dangles - they are connected to only one line. To do so, proceed as follows:

  1. Explode line to get a single feature for each segment

  2. Create the source for each river, identifying those start-points that do not touch any other than the current line using this expression with Geometry by Expression:

     if (
      disjoint( 
         start_point($geometry),
         difference (
             collect ($geometry),
             $geometry)
         ),
         start_point($geometry),
         ''
     )
    
  3. Do the same for the mouth of the river, changing start_point with end_point (lines 3 and 8).

  4. Run network tool Shortest path (point to point) from source layer (step 2) to mouth layer (step 3).

Creating source (red) and mouth (blue) point layer with the expression: enter image description here

Your Answer

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

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