# Selecting features within certain buffer distance of selected feature using PyQGIS?

I have a shapefile of thousands of polylines. I have select one feature, I want to select all other features that is within say 100m of the selected feature.

How do I achieve it by pyqgis?

• Is the one feature selected using a mouseclick or from code? – weiji14 Jan 6 '17 at 2:05
• it is from code, say select where fid = 1 – chenghopan Jan 6 '17 at 2:06
• Do you want the 100m tolerance to be set from the selected feature's centre, bounding box rectangle, or as an actual 100m buffer from the line (note increasing order of complexity). – weiji14 Jan 6 '17 at 2:16
• i want it to be the buffer – chenghopan Jan 6 '17 at 2:17
• Welcome to gis.stackexchange! Please note that a good question on this site is expected to show some degree of research on your part, i.e. what you have tried and - if applicable - code so far. For more info, you can check our faq. – underdark Jan 8 '17 at 20:08

If you want to select all features that are within 100 m of the selected "buffer" feature you can use next code:

layer = iface.activeLayer()

feats = [ feat for feat in layer.getFeatures() ]

#selected feature fid = 0
geom_buffer = feats[0].geometry().buffer(100, -1)

#erasing selected feature in original list
del feats[0]

new_feats = [feat for feat in feats
if feat.geometry().intersects(geom_buffer) ]

epsg = layer.crs().postgisSrid()

uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
'line',
'memory')

prov = mem_layer.dataProvider()

for i, feat in enumerate(new_feats):
feat.setAttributes([i])



It produces a memory layer with features that match this condition.

I tried out above code with next line layer; where selected feature (id=0) was previously visualized as buffer by using its WKT format into QuickWKT plugin of QGIS.

After running the code, memory layer (red layer in next image) was obtained as expected:

This should give you some ideas.

lyr = qgis.utils.iface.activeLayer()
featDict = {feature.id(): feature for (feature) in lyr.getFeatures()}  #stores features in a dictionary for fast access
featIdx = QgsSpatialIndex(lyr.getFeatures())   #spatial index for faster spatial queries
bufDist = 100                                  #sets distance

for line in lyr.selectedFeatures():
xyList = line.geometry().asPolyline()
minx = min([xy[0] for xy in xyList])   #minimum x-coordinate
maxx = max([xy[0] for xy in xyList])   #maximum x-coordinate
miny = min([xy[1] for xy in xyList])   #minimum y-coordinate
maxy = max([xy[1] for xy in xyList])   #maximum y-coordinate
ids = featIdx.intersects(QgsRectangle(minx - bufDist, miny - bufDist, maxx + bufDist, maxy + bufDist))

#lyr.selectByIds(ids)  #use this if you don't need total accuracy, much faster!!

#For QGIS versions below 2.16
for id in ids:
if featDict[id].geometry().distance(line.geometry()) < bufDist:
lyr.select(id)

#For QGIS 2.16 or above
tids = []  #true ids of nearby features that we want to select
for id in ids:
if featDict[id].geometry().distance(line.geometry()) < bufDist:
tids.append(id)
lyr.selectByIds(tids, 1)   #AddToSelection, see https://qgis.org/api/classQgsVectorLayer.html#a2dbfa880644f08f8b9f77b6c28036c74 for SelectBehaviour

• it says QgsVectorLayer' object has no attribute 'selectByIds', any ideas? – chenghopan Jan 6 '17 at 2:52
• Ah, you're probably using a version older than 2.16 (see qgis.org/api/…). Hold on, I'll edit the code :). – weiji14 Jan 6 '17 at 2:54
• what is the caution comment about ? Is it exceed the extent? – chenghopan Jan 6 '17 at 3:08
• Yeah, I need to fix that actually. It's not exactly the minimum y-coordinate, the code just uses the y-coordinate from the node with the minimum x-coordinate. So if you have a complex zig-zagging line, that won't quite work. – weiji14 Jan 6 '17 at 3:13
• yeah... I just added a pic of my data – chenghopan Jan 6 '17 at 3:20