# Detecting and making all connected lines in the same direction in QGIS

I have a list of straight roads segmented which has a unique `"ID"`. I would like to detect connected lines in the road network and make them in the same direction instead of reversing them one by one. So to simplify my question:

Each line has a beginning point(x1, y1) and an ending point(x2, y2). For instance: if line A's beginning point(x1, y1) or ending point(x2, y2) is equal to line B's beginning point(x3, y3) or ending point(x4, y4), detect those lines and make it in the same direction. It doesn't matter which direction it is as long as they align in the same direction. Since there are thousands of lines, I need a smart way to do this all at once.

I can use the "Reverse direction of geometry" tool in QGIS but it doesn't resolve my issue because I have to do it one by one.

Can you give me some insights please either via any QGIS tool or Python code samples?

• Does each line group have a unique ID? In your image the lines are colour coded, are these colours dictated by a certain attribute? Commented Apr 12, 2022 at 2:03
• Hi @Cushen, thank you for your reply. Yes, each line group has a unique ID which is segments. Example: RD009A, RD009B, RD009C. I categorized and colored by sections ID. In this case, section ID is: RD009. Commented Apr 12, 2022 at 2:15

Compare the azimuth of each line to the line group mean, and reverse the line in each group that deviate the most from the group mean:

Refactor fields (or use two field calculators) to calculate:

`groupid = left(id, 5)`

`degrees(azimuth(start_point(\$geometry), end_point(\$geometry)))`

Calculate a mean azimuth per group `mean(expression:="azimuth", group_by:="groupid")`

Calculate each lines deviation from mean `deviation_from_mean = abs("azimuth"-"meanAzimuth")`

Calculate a control field so we dont extract and reverse lines in the next step that shouldnt be reversed just because they deviate the most from the mean

`control = case when deviation_from_mean>45 then 1 else 0 end`

Extract the lines in each group that deviate the most from the mean `deviation_from_mean = maximum(expression:="deviation_from_mean", `group_by:="groupid") and control=1

Reverse the matching lines and merge with the none matching

• Hi @BERA. Thank you for your brilliant solution. However, I couldn't understand what 45 represents in your equation here: control = "case when deviation_from_mean>45 then 1 else 0 end". Can you clarify it, please? Also when I implemented your solution it worked in the majority of the network but I still couldn't achieve the 100 percent expected outcome. Some of the same groupid didn't align in the same direction. Here is the link to the images: imgur.com/a/XjqvxZN Commented Apr 20, 2022 at 3:04
• Hello. The 45 so you dont reverse the direction of one line segment in all groups. It has to be the line that deviates the most from the mean and where the deviation from the mean is more than 45 degrees. Try lowering it some and maybe get a better result
– Bera
Commented Apr 20, 2022 at 5:12

This is network task, so use networkx module. First compute connected components (groups) of undirected graph:

Select one dangling node per group and compute travel to them from other nodes:

Select lines where FROM node travel is less than TO node travel:

and flip selected:

Note: for true road network result will look controversial:

this is because from some point in the middle of 0 flow edges travel distance to destination is equal for 2 opposite directions at this point.

• Thank you for such a cool tip with this Python package! Commented Apr 13, 2022 at 6:41
• Can you show how you create the graph?
– Bera
Commented Apr 13, 2022 at 6:56
• @BERA this is separate big topic. Perhaps ask question and I post a GIS workflow. Commented Apr 13, 2022 at 9:33
• Thank you for your solution @FelixIP. Can you share the Python code for reference please? Commented Apr 20, 2022 at 3:21
• There are 4 or more scripts in play here. So, no. I cannot share. And I don't want too. Commented Apr 20, 2022 at 5:02