2

I am trying to select (point) features within an envelope (buffer) of the start point of a line feature.

I have

line_layer = QgsProject.instance().mapLayersByName('DSC_Roads')[0]
chainage_layer= QgsProject.instance().mapLayersByName('DSC_Roads_10m_Chainage')[0]
for feature in line_layer.getFeatures(): # for each road select line and point features
    road = feature['RoadMntnc']
    if road == "Bamboo_Creek_Rd": #temporary for testing
        request = QgsFeatureRequest(QgsExpression('"RoadMntnc"= \'{0}\''.format(road)))
        l_sel = line_layer.getFeatures(request)
        c_sel = chainage_layer.getFeatures(request) #make sure points are on the same road
        for l in l_sel:
          geom = l.geometry().asPolyline()
          g = QgsGeometry.fromPointXY(geom[0])
          buffer = g.buffer(5,4) #10m buffer with 4 segments
          print (buffer) #test to see if the buffer works
          processing.run("qgis:selectbylocation",buffer,c_sel,['within'],0,0)
          chainage_selection=layer.selectedFeatures()
          print (chainage_selection) #test to see if selection worked

With this I am getting an error as there's probably something wrong with the selectbylocation that's based on https://gis.stackexchange.com/a/259441/2891

Traceback (most recent call last):
  File "C:\OSGEO4~1\apps\Python37\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "<string>", line 12, in <module>
  File "C:/OSGEO4~1/apps/qgis-dev/./python/plugins\processing\tools\general.py", line 106, in run
    return Processing.runAlgorithm(algOrName, parameters, onFinish, feedback, context)
  File "C:/OSGEO4~1/apps/qgis-dev/./python/plugins\processing\core\Processing.py", line 130, in runAlgorithm
    if context.feedback() is None:
AttributeError: 'int' object has no attribute 'feedback'

--- NEW CODE based on Joseph's answer

I tried the following but still get the same error

for l in l_sel:
    geom = l.geometry().asPolyline()
    g = QgsGeometry.fromPointXY(geom[0])
    buffer = g.buffer(5,4) #10m buffer with 4 segments
    buff_layer = QgsVectorLayer('Polygon', 'buffer' , 'memory')
    prov = buff_layer.dataProvider()
    feat = QgsFeature()
    feat.setGeometry(buffer)
    prov.addFeatures([feat])
    buff_layer.updateExtents()
    QgsProject.instance().addMapLayers([buff_layer])[0]
    processing.run("qgis:selectbylocation",buff_layer,c_sel,['within'],0,0)
    chainage_selection=layer.selectedFeatures()
    print (chainage_selection
GeorgeC
  • 8,228
  • 7
  • 52
  • 136

2 Answers2

4

I think the error is persisting because your c_sel argument is not a vector layer object either.

I would not worry about using the Select By Location processing algorithm and just work directly with the point feature geometries and their relationships to the buffers.

I created some test layers as a 'mock-up' and put together the script below which should do what you want. My point layer has a different name and chainage distance to yours, so my buffer is also larger. Just change the details to suit your data. I also assume you are wanting to do the buffer and selection for the start point of each line in your roads layer. If not, see the comments in my code- comment and uncomment the lines as indicated to use only the line features which match a feature name e.g. 'Bamboo_Creek_Rd' etc.

Here is the result I obtained on my test data after running the code:

enter image description here

line_layer = QgsProject().instance().mapLayersByName('DSC_Roads')[0]
chainage_layer = QgsProject().instance().mapLayersByName('Chainage_points')[0] #Change name to match your chainage layer
fids = []
feats = [f for f in line_layer.getFeatures()]
# comment above and uncomment below to run only on Bamboo Creek Road etc
#feats = [f for f in line_layer.getFeatures() if f['RoadMntnc'] == 'Bamboo_Creek_Rd']
for feat in feats:
    name = feat['RoadMntnc']
    c_sel = [p for p in chainage_layer.getFeatures() if p['RoadMntnc'] == name]
    geom = feat.geometry().asPolyline()
    start_point = QgsGeometry.fromPointXY(geom[0])
    buffer = start_point.buffer(5000, 4) #5000m buffer with 4 segments
    points_within_buffer = []
    for f in c_sel:
        if f.geometry().within(buffer):
            points_within_buffer.append(f.id())
    for x in points_within_buffer:
        fids.append(x)
chainage_layer.selectByIds(fids)
Ben W
  • 21,426
  • 3
  • 15
  • 39
2

The qgis:selectbylocation tool requires two input vector layers. The first input you used is buffer which is just a geometry feature.

Try storing your buffer features in a new memory layer and use this as the first input layer.

Joseph
  • 75,746
  • 7
  • 171
  • 282
  • Thanks - I tried but still get the same error. Can I do this without using processing? – GeorgeC Sep 27 '19 at 21:39
  • Ideally I would simply like to use request.setFilterRect(areaOfInterest) based on https://qgis-docs.readthedocs.io/en/latest/docs/pyqgis_developer_cookbook/vector.html . The areaOfInterest should just be the buffer. – GeorgeC Sep 27 '19 at 21:57