I am working with a road network, where I extracted only the three main road types. In the next step, I would like to union all Linestrings based on their road type and connectivity. That means that I have a gdf of thousands of Linestrings right now but want to end up with only six Linestrings (see image below).
So, red, green and blue are the three road types and therefore cannot be unioned together. On top of that 3, 4, 5, and 6 are the same type but are not connected to each other but with another class.
I looked into dissolved but the problem here is that it ignores connectivity. On the other side, unary_union looks suitable but only returns shapely geometries which I would have to transform back into a gdf (as far as I'm concerned?). Any idea how to approach this problem?
I found this code for an QGIS Add-on ([https://gis.stackexchange.com/questions/228267/merging-adjacent-lines-in-qgis#][3]). I could make the first block running (see in the very bottom) but struggle with the second block since I get a bunch of AttributeErrors and don't know how to translate them into pandas.
##Lines=vector line
from qgis.core import *
def find_adjacent(selected_ids): # for finding adjacent features
outlist = []
outinds = []
outset = set()
for j, l in enumerate(selected_ids):
as_set = set(l)
inds = []
for k in outset.copy():
if outlist[k] & as_set:
outset.remove(k)
as_set |= outlist[k]
inds.extend(outinds[k])
outset.add(j)
outlist.append(as_set)
outinds.append(inds + [j])
outinds = [outinds[j] for j in outset]
del outset, outlist
result = [[selected_ids[j] for j in k] for k in outinds]
return result
layer = processing.getObject(Lines)
crs = layer.crs().toWkt()
# Create the output layer
outLayer = QgsVectorLayer('Linestring?crs='+ crs, 'snapped' , 'memory')
prov = outLayer.dataProvider()
fields = layer.pendingFields()
prov.addAttributes(fields)
outLayer.updateFields()
already_processed = []
for feat in layer.getFeatures():
attrs = feat.attributes()
geom = feat.geometry()
curr_id = feat["ID"]
if curr_id not in already_processed:
query = '"ID" = %s' % (curr_id)
selection = layer.getFeatures(QgsFeatureRequest().setFilterExpression(query))
selected_ids = [k.geometry().asPolyline() for k in selection]
adjacent_feats = find_adjacent(selected_ids)
for f in adjacent_feats:
first = True
for x in xrange(0, len(f)):
geom = (QgsGeometry.fromPolyline([QgsPoint(w) for w in f[x]]))
if first:
outFeat = QgsFeature()
outFeat.setGeometry(geom)
outGeom = outFeat.geometry()
first = False
else:
outGeom = outGeom.combine(geom)
outFeat.setAttributes(attrs)
outFeat.setGeometry(outGeom)
prov.addFeatures([outFeat])
already_processed.append(curr_id)
else:
continue
# Add the layer to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(outLayer)
First block using pandas:
def find_adjacent(line): # for finding adjacent features
outlist = []
outinds = []
outset = set()
for j, l in line.iteritems():
as_set = set(line.astype(str))
inds = []
for k in outset.copy():
if outlist[k] & as_set:
outset.remove(k)
as_set |= outlist[k]
inds.extend(outinds[k])
outset.add(j)
outlist.append(as_set)
outinds.append(inds + [j])
outinds = [outinds[j] for j in outset]
del outset, outlist
result = [[line[j] for j in k] for k in outinds]
return result
lines = find_adjacent(trunk.geometry)