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– weiji142017年01月06日 02:05:17 +00:00Commented Jan 6, 2017 at 2:05
-
it is from code, say select where fid = 1benchenggis– benchenggis2017年01月06日 02:06:25 +00:00Commented Jan 6, 2017 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– weiji142017年01月06日 02:16:14 +00:00Commented Jan 6, 2017 at 2:16
-
i want it to be the bufferbenchenggis– benchenggis2017年01月06日 02:17:13 +00:00Commented Jan 6, 2017 at 2:17
-
2Welcome 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– underdark2017年01月08日 20:08:42 +00:00Commented Jan 8, 2017 at 20:08
2 Answers 2
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])
prov.addFeatures(new_feats)
QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
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
-
1it says QgsVectorLayer' object has no attribute 'selectByIds', any ideas?benchenggis– benchenggis2017年01月06日 02:52:27 +00:00Commented Jan 6, 2017 at 2:52
-
1Ah, you're probably using a version older than 2.16 (see qgis.org/api/…). Hold on, I'll edit the code :).weiji14– weiji142017年01月06日 02:54:19 +00:00Commented Jan 6, 2017 at 2:54
-
what is the caution comment about ? Is it exceed the extent?benchenggis– benchenggis2017年01月06日 03:08:28 +00:00Commented Jan 6, 2017 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– weiji142017年01月06日 03:13:41 +00:00Commented Jan 6, 2017 at 3:13
-
yeah... I just added a pic of my databenchenggis– benchenggis2017年01月06日 03:20:25 +00:00Commented Jan 6, 2017 at 3:20
Explore related questions
See similar questions with these tags.