4

Based on the answer of @mgri here: https://gis.stackexchange.com/a/224954/164953 I tried to select the features of a multilines layer intersecting less or more than 2 features of a multipoints layer.

At first sight, I thought that the script did what I wanted but unfortunately, I realized that there were a significant number of features that were (not)/selected whereas they (should)/shouldn't

from qgis.core import *
from qgis.gui import *
from qgis.utils import *
 
layer1 = QgsProject.instance().mapLayersByName('lines')[0]
layer2 = QgsProject.instance().mapLayersByName('nodes')[0]

index = QgsSpatialIndex() # Spatial index
for ft in layer2.getFeatures():
    index.insertFeature(ft)

selection = [] # This list stores the features which contains at least one point
for feat in layer1.getFeatures():
    inGeom = feat.geometry().buffer(0.1,0.1)
    idsList = index.intersects(inGeom.boundingBox())
    if len(idsList) != 2:
        selection.append(feat)
        
layer1.selectByIds([k.id() for k in selection])

A small sample of the dataset: https://we.tl/t-caDtSeAe1z

1 Answer 1

4

The intersects() method of QgsSpatialIndex takes a QgsRectangle object so, initially, you are only testing for point features inside the bounding box of each line feature. You must then run a second test on these 'candidate' points to determine if they do in fact intersect the polygons formed by the very small buffering operation on your line features.

Try the modified version of your script below:

layer1 = QgsProject.instance().mapLayersByName('lines')[0]
layer2 = QgsProject.instance().mapLayersByName('nodes')[0]

index = QgsSpatialIndex() # Spatial index
for ft in layer2.getFeatures():
    index.insertFeature(ft)

selection = [] # This list stores the features which contains at least one point
for feat in layer1.getFeatures():
    inGeom = feat.geometry().buffer(0.1, 8)
    candidates = index.intersects(inGeom.boundingBox())
    req = QgsFeatureRequest().setFilterFids(candidates)
    points_on_lines = [f for f in layer2.getFeatures(req) if f.geometry().intersects(inGeom)]
    if len(points_on_lines) != 2:
        selection.append(feat)
        
layer1.selectByIds([k.id() for k in selection])

I obtained the following result with a couple of test layers:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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