NOTE I edited the code (and the explanation of how it works) because there were wrong results in some specific cases.
I propose a solution with PyQGIS: starting from a linestring layer and a polygon layer, it looks for the line features within each polygon feature and then creates a new polygon memory layer (called "catchments_new") which stores the same attributes of the starting polygon layer plus one additional field (called "PREDOMIN_ID"
) containing the ID of the predominant river within it.
This is the code:
##Rivers=vector line
##Catchments=vector polygon
from qgis.core import *
from qgis.PyQt.QtCore import QVariant
layer1 = processing.getObject(Rivers)
crs = layer1.crs().toWkt()
layer2 = processing.getObject(Catchments)
# Create the output layer
outLayer = QgsVectorLayer('Polygon?crs='+ crs, 'catchments_new' , 'memory')
prov = outLayer.dataProvider()
fields = layer2.pendingFields() # Fields from the input layer
fields.append(QgsField('PREDOMIN_ID', QVariant.String, '', 50, 0)) # Name for the new field in the output layer
prov.addAttributes(fields) # Add input layer fields to the outLayer
outLayer.updateFields()
index = QgsSpatialIndex() # Spatial index
for ft in layer1.getFeatures():
index.insertFeature(ft)
for feat in layer2.getFeatures():
attrs = feat.attributes()
inGeom = feat.geometry()
idsList = index.intersects(inGeom.boundingBox())
if len(idsList) > 0:
req = QgsFeatureRequest().setFilterFids(idsList)
temp_river_lengths = {} # Store the ids and lengths that are within the current polygon feature
for elem in layer1.getFeatures(req):
temp_geometry = elem.geometry()
if temp_geometry.intersects(inGeom):
itx = temp_geometry.intersection(inGeom)
if elem[0] not in temp_river_lengths.keys():
temp_river_lengths[elem[0]] = itx.length()
else:
temp_river_lengths[elem[0]] += itx.length()
k=list(temp_river_lengths.keys())
v=list(temp_river_lengths.values())
if len(k) > 0:
predom_id = k[v.index(max(v))]
attrs.append(predom_id)
outGeom = QgsFeature()
outGeom.setAttributes(attrs) # Output attributes
outGeom.setGeometry(inGeom) # Output geometry
prov.addFeatures([outGeom]) # Output feature
# Add the layer to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(outLayer)
"Shape_Leng"
field).