7

I have a large dataset consisting of lines/polylines where I would like to join/merge the lines that touch / intersect. Each line has an individual ID and there are no common attributes I can use for a join operation. Is there a way to (spatially) join lines into segments of touching lines?

Screenshot of a selected line in a line segment (current situation): Screenshot of a selected line in a line segment.

It can be done in ArcGIS according to this post (link) among others.

FYI, the dataset is an extract from a pipeline network and I will examine which line segments that cross the most properties / parcels of land.

I'm using QGIS 2.14.0. I have no experience with python or GRASS yet.

  • I was facing the same issue (Screenshot: Errno 9) as mentioned Above but the process is working fine when i selected the Data (Poly-lines).Try select the data first :) – Shakil Sep 6 '16 at 11:26
8

In QGIS Plugins you'll find a 'merge lines' plugin, which at first sight seems to accomplish what you are after.

cited from description:

MergeLines

Simplifies the topology of a line network by merging adjacent lines

This plugin merges segments of a line network (e.g. river network) in order to simplify its topology. Two merging methods are currently available : length (a segment is merged with its longest neighbor) and alignment (a segment is merged with its best aligned neighbor).

UPDATE:

Below you find a geoprocessing script of which I hope that it does what you want. For testing purposes I created a shapefile with a bunch of irregularly intersecting lines and no attributes (network):

enter image description here

The standard dialog when executing the script looks like this (in this case the result is a memory layer):

enter image description here

Running the script produces a 'copy' of the input data with a field 'subnet' distinguishing to which subnet a feature belongs. With a categorized style the result looks like this:

enter image description here

This can be dissolved using the field 'subnet'.

Create a new geoprocessing script, copy the code in the editor, save it and things should work.

##Networking=group
##lIn=vector
##lOut=output vector

from qgis.core import *
from qgis.utils import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import QColor
#from processing.core.VectorWriter import VectorWriter

c=iface.mapCanvas()
rubberBand = []

v = processing.getObject(lIn)

#generate a list of all features in the layer
subNets = []
flist = []
for f in v.getFeatures():
    flist.append(f)


def makeSubnets(featureList):
    #print "making subnet ---------------------------------------------------"
    if len(featureList) > 1:
        print [featureList[0]]
        print featureList[1:]
        #print "start finding a subnet"
        fTest, fRest = findSubnet([featureList[0]], featureList[1:])
        #print "finished finding a subnet"
        subNets.append(fTest)
        makeSubnets(fRest)
    else:
        subNets.append(featureList)

def findSubnet(featTest, featRest):
    found = True
    while found:
        newTestList = []
        #print "candidates: ", len(featTest)
        #print "search in: ", len(featRest)
        #print "-------------"
        for fT in featTest:
            for fR in featRest:
                if not fT.geometry().disjoint(fR.geometry()):
                    #print "!"
                    newTestList.append(fR)
                    #addRubberBand(fR.geometry())

        featTest += newTestList

        if newTestList == []:
            found = False
        else:
            #print "Found (undis)joining segments"
            for fn in newTestList:
                if fn in featRest:
                    featRest.remove(fn)
                    #print "removed ", fn
                else:
                    pass
                    #print "allready removed ", fn

    return featTest, featRest

def addRubberBand(theGeom):
    rubberBand.append(QgsRubberBand(c, False))
    rubberBand[-1].setToGeometry(theGeom, None)
    rubberBand[-1].setColor(QColor(255,0,0))
    rubberBand[-1].setWidth(3)

makeSubnets(flist)

fields = QgsFields()
fields.append(QgsField('subnet', QVariant.Int))
writer = QgsVectorFileWriter(lOut, None, fields, QGis.WKBLineString,     v.crs())

net = 0
for sn in subNets:
    for f in sn:
        #print net, f
        feat = QgsFeature()
        feat.setFields(fields)
        feat.setGeometry(f.geometry())
        feat.setAttribute('subnet', net)
        writer.addFeature(feat)
    net += 1
del writer

UPDATE #2:

To create a geoprocessing script do the following (I've got the german gui, so I try to translate in en):

A: Menu 'Processing' -> 'Toolbox' (appears as a dock on the right)

B: Under 'Scripts [...]' -> 'Tools' doubleclick 'create new script'

enter image description here

An Editor with a little toolbar appears, in wich you copy the code above. Herein you can:

C: Save the script. It appears (in this case) in the group 'Networking' or in whatever group you write in the first line of the script ##MyGroup=group. Be aware not to write blanks in the ##-lines!!!

D: Start the script with the two little gears. A gui appears (cp. above) with the in- and output layers defined in the script line 2 and 3. When saved, alteratively start the script by doubleclicking its name under 'scripts' > 'mygroup' > 'myscriptname' (if saved under myscriptname.py)

enter image description here

  • Thanks for your comment @jochen-schwarze. I tried this plugin again now, and I get a Python error: File "C:/Users/imc/.qgis2/python/plugins\QGISMergeLines-master\merge_lines.py", line 216, in onStart self.joinLines( inputLayer, params ) File "C:/Users/imc/.qgis2/python/plugins\QGISMergeLines-master\merge_lines.py", line 312, in joinLines deletedFeaturesID += delFeaturesID UnboundLocalError: local variable 'delFeaturesID' referenced before assignment Sorry for long error log. I will delete it again if we find a solution. – Ilias Jun 14 '16 at 12:29
  • I'll test this with 2.14.3 and see what happens... – Jochen Schwarze Jun 14 '16 at 12:31
  • I get the same error with 2.14.3. Could you make yourself familiar with how QGIS geoprocessing scripts work in general? I think I can find a solution using some lines of python... – Jochen Schwarze Jun 14 '16 at 13:57
  • OK, I will try to look into some Python tutorials. Furthermore I'll notify the developer of the plugin. – Ilias Jun 15 '16 at 7:10
  • test the script above. it's bit of quick and dirty, and silent. If I get an answer to this gis.stackexchange.com/questions/198706/… i'll update it. perhaps it's worth writing a plugin? – Jochen Schwarze Jun 16 '16 at 13:38
0

Alternative solution (QGIS 3.8):

  1. Processing Toolbox> v.clean:

    • Use the tools "break", "snap", "rmdup", "rmline"
    • Set the threshold in 0.3,0,0 (replace 3 by the maximum distance for which the snapping must be done)
  2. Processing Toolbox> Regroup

  3. Processing Toolbox> Merge Lines

  4. Processing Toolbox> Cut with lines

    • For this step, just cut the layer with itself

If necessary a second v.clean treatment can be applied to ensure that the topology is good. Deleting duplicate / null geometry can also be useful.

NOTE: If someone could develop a small plugin for this purpose it would be great :), this feature is only available in the Advanced version of ArcGIS (the most expensive).

  • 1
    What did you mean by Regroup? Can't find it in the toolbox. In which part of the toolbox is it? Can you please post a screenshot? – Techie_Gus Oct 21 at 10:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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