53

I would like to be able to swap the direction of a polyline/line in QGIS. I made a custom tool to do this in MapInfo, however I can't seem to find anything for QGIS.

Does anyone know of a tool to do this?

Taras
  • 32,823
  • 4
  • 66
  • 137
Nathan W
  • 34,706
  • 5
  • 97
  • 148
  • 4
    Would be great to have. I don't know of any such native QGIS function. – underdark May 04 '11 at 06:26
  • 4
    I have a good idea how I can do this pretty easily, I'll see if I can whip up something tonight. – Nathan W May 04 '11 at 08:51
  • 1
    Great! Maybe it can be added to ftools/vector tool box. – underdark May 04 '11 at 08:53
  • 2
    since you have already got the core taken care of, any chance you want to tackle this question, but for QGIS? http://gis.stackexchange.com/questions/9286/repository-of-arcview-3-x-avenue-commands-methods-general-information http://resources.arcgis.com/content/kbase?fa=articleShow&d=20961 – RyanKDalton May 04 '11 at 23:24
  • 2
    Here is the ticket: http://hub.qgis.org/issues/4936 – Mike T Mar 06 '12 at 20:58

8 Answers8

66

Ok here is the Python that I used to do it:

layer = qgis.utils.iface.mapCanvas().currentLayer()
for feature in layer.selectedFeatures():
   geom = feature.geometry()
   nodes = geom.asPolyline()
   nodes.reverse() 
   newgeom = QgsGeometry.fromPolyline(nodes)
   layer.changeGeometry(feature.id(),newgeom)

Before running the above code:

  1. Select the layer you want to edit;
  2. Toggle Editing on;
  3. Select the features in this layer you want to reverse.

Run the above python code by:

  1. Going to Plugins > Python Console;
  2. Copying and pasting the code into the window;
  3. Hit Enter 2x to run.

It should output "True" for each feature whose direction was swapped. If it outputs "False" then it didn't swap that feature's direction. This will happen if the layer doesn't have Editing toggled on.

Pretty easy!

I have wrapped it up in a plugin called Swap Line Direction and it's available in the QGIS plugin installer.

This plugin is no longer available (as of 11/16/2015) in the plugin installer but you can build your own pretty easily with the "Plugin Builder" plugin.

I'll have a look at how easy it is to intergrate with fTools.

mgri
  • 16,159
  • 6
  • 47
  • 80
Nathan W
  • 34,706
  • 5
  • 97
  • 148
  • 1
    so you created your own solution - well done - can it be added to ftools? – Mapperz May 04 '11 at 21:36
  • I'm sure it can, I'll just have to look at the way fTools is coded and write a patch. – Nathan W May 04 '11 at 22:02
  • Fantastic! Solutions like this are the reason I like using QGIS. Nice job Nathan - BTW I like your little catalogue type plugin aswell! – Ando May 04 '11 at 22:05
  • @Ando Thanks! I'm beta testing a few new ideas, just wish I had more time to work on it so I could get it out quicker. – Nathan W May 04 '11 at 22:17
  • 3
    That is really awesome that you worked up a solution so quickly and elegantly. The power of Open Source wins again! – RyanKDalton May 04 '11 at 22:20
  • When we apply this code is difficult to convert line to polyline. What is happening? thank you! – SadeckGEO Mar 06 '12 at 19:27
  • Please leave this as a comment as it is not an answer. Also that is not the intention of any of the code here. – Nathan W Mar 06 '12 at 21:16
  • Unfortunately, this doesn't work with my linestrings. I select one linestring, execute the code and get "False". Edit mode activated. QGis 2 (Dufour). – Marian Jan 13 '14 at 09:10
  • Can the direction of a line or a polyline be reversed from a menu or toolbar? – wannik Jun 16 '14 at 09:23
  • Did you use something like the PluginBuilder plugin mentioned on http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/plugins.html ? – Dave X Jul 22 '14 at 14:11
  • @Nathan: Curiosity: Is a polyline a sequence of points? or a sequence of line seqments? I ask because something about the swap has me wondering what's going on: Before the swap on the 1st segment, the 1st segment is P1-->P2: If you swap the ends of the 1st segment to become P2-->P1, on execution with the next feature/segment why isn't the beginning of the next segment (Initially P2-->P3) changed to P1-->P3, -before- its swap is executed (in which case the result becomes P3-->P1, instead of P3-->P2) ?? – John Nov 18 '14 at 00:50
  • worked like a charm in qgis 2.18. Thanks! And, tip to put arrows on your line so you can see the direction: layer>properties>style> change "symbol larger type" from "simple line" to "arrow". – Nikhil VJ Jul 06 '18 at 10:50
  • This doesn't seem to work in QGIS 3? – oskarlin Sep 03 '18 at 13:16
16

If you have the GRASS plugin use the v.flip option - http://grass.osgeo.org/wiki/GRASS_AddOns#v.flip

enter image description here

Mapperz
  • 49,701
  • 9
  • 73
  • 132
8

Following Nathan's answer, you can create a python action in the layer where you want to swap lines:

layer = QgsMapLayerRegistry.instance().mapLayer("_your_layer_id_")
r = QgsFeatureRequest([% $id %])
f = QgsFeature()
if layer.getFeatures(r).nextFeature(f):
  geom = f.geometry().asPolyline()
  geom.reverse()
  geom = QgsGeometry.fromPolyline(geom)
  if layer.changeGeometry([% $id %], geom):
    qgis.utils.iface.messageBar().pushMessage("Line swaped", QgsMessageBar.INFO, 2)
    qgis.utils.iface.mapCanvas().refresh()
  else:
    qgis.utils.iface.messageBar().pushMessage("Cannot swap line. Turn editing on.", QgsMessageBar.WARNING, 3)
else:
  qgis.utils.iface.messageBar().pushMessage("Cannot edit this feature.", QgsMessageBar.CRITICAL, 3)

You will be able to swap lines by one click on them. It is much user-friendly!

mgri
  • 16,159
  • 6
  • 47
  • 80
Denis Rouzaud
  • 1,618
  • 11
  • 16
6

This plugin reverses the line direction too:

https://hub.qgis.org/projects/swapvectordirection

You have to select a feature, and turn the layer into edit mode before clicking on the plugin icon.

AndreJ
  • 76,698
  • 5
  • 86
  • 162
6

Based on Nathan's post I've created a processing script to reverse the direction of features:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# define Interface
##QGIS tools (QGIS 2.x)=group
##Reverse vector direction=name
##Input_layer=vector
##Only_selected_features=boolean true

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import *

from qgis.core import *
from qgis.gui import *
from qgis.utils import *

# get input parameters from GUI
inlayer = processing.getObject(Input_layer)
selected = Only_selected_features

# check 'Only selected features' option
if selected is True and inlayer.selectedFeatureCount () == 0:
    raise RuntimeError('No features selected on Layer \'' + inlayer.name() + '\'.')

# check if input layer is editable
if not inlayer.isEditable():
    inlayer.startEditing()

# reverse vector direction
def reverse():
    geom = feature.geometry()
    nodes = geom.asPolyline()
    nodes.reverse()
    newgeom = QgsGeometry.fromPolyline(nodes)
    inlayer.changeGeometry(feature.id(),newgeom)

if selected is True:
    for feature in inlayer.selectedFeatures():
        reverse()
else:
    for feature in inlayer.getFeatures():
        reverse()

# refresh input layer
inlayer.dataProvider().forceReload()

enter image description here

eclipsed_by_the_moon
  • 1,855
  • 21
  • 44
4

This plugin will switch the direction of a polyline.

http://plugins.qgis.org/plugins/DigitizingTools/

GreyHippo
  • 2,180
  • 2
  • 17
  • 30
2

Since QGIS 2.14 (see the Changelog) there is the "Reverse line direction" (placed in Vector geometry) tool from the Processing Toolbox (Ctrl+Alt+T).

Let's assume there are two features in 'lines_test', see the image below.

input

Press Run and get the output:

output

Taras
  • 32,823
  • 4
  • 66
  • 137
0

Using QGIS 3.10

Following @Nathan W 's answer above, here's a solution if your line is a LineStringZ (i.e. a line with an x, y and Z value) - as are most Google Earth KML files (even if that Z value = 0, which is often the case.)

You might get this error when the nodes.reverse() call is made in the code below:

TypeError: index 0 has type QgsPointXY but QgsPoint is expected

1   layer = qgis.utils.iface.mapCanvas().currentLayer()
2   for feature in layer.selectedFeatures():
3      geom = feature.geometry()
4      nodes = geom.asPolyline()
5      nodes.reverse() 
6      newgeom = QgsGeometry.fromPolyline(nodes)
7      layer.changeGeometry(feature.id(), newgeom)

The solution to that is to use QgsGeometry.fromPolylineXY() instead in line 6:

1   vLayer = qgis.utils.iface.mapCanvas().currentLayer()
2   for feat in vLayer.selectedFeatures():
3       geom = feat.geometry()
4       pointXY_nodes = geom.asPolyline() # >>> returns list of QgsPointXY objects: [<QgsPointXY: POINT(-117.60560599 ..
5       pointXY_nodes.reverse() 
6       newgeom = QgsGeometry.fromPolylineXY(pointXY_nodes)
7       vLayer.changeGeometry(feat.id(), newgeom)
8       print("Geom reversed!")
Taras
  • 32,823
  • 4
  • 66
  • 137
grego
  • 1,043
  • 7
  • 18