Sunday, 15 December 2019

Join / merge lines that touch and intersect in QGIS


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.



Answer



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


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...