Almost 10 years later it is probably worth adding an update to @vinayan's answer:
By storing the features geometries inside the QgsSpatialIndex()
using QgsSpatialIndex.FlagStoreFeatureGeometries
flag, you can get the real closest features, not just the approximate ones by their bounding box. This adresses the comment by Håvard Tveite. Also, nowadays it is much more efficient to bulkload the index at once; this is much faster than adding features one by one after the creation of the index in a loop. Additionally you can get the nearest geometries directly from the index, which is much faster than getting the whole feature via a QgsFeatureRequest()
. If you still want to get the whole feature, you can now also use directly .getFeature(id)
, which is shorter. Apart from that, the syntax is now for PyQGIS 3. The code:
layer = iface.activeLayer()
# Bulkloading the index is much faster than adding features one by one
# Storing the geometry in the index allows finding the exact nearest neighbor, also for not single-point-features
index = QgsSpatialIndex(layer.getFeatures(), flags=QgsSpatialIndex.FlagStoreFeatureGeometries)
# QgsSpatialIndex.nearestNeighbor(QgsPointXY(), int neighbors)
pt = QgsPointXY(-0.00062201,0.00001746)
nearestIds = index.nearestNeighbor(pt,1) # we need only one neighbour
# Or, not stated in the docs, if you store the geometry in the index as done here, you can also: QgsSpatialIndex.nearestNeighbor(QgsGeometry(), int neighbors)
geom = QgsGeometry.fromPointXY(QgsPointXY(-0.00062201,0.00001746))
nearestIds = index.nearestNeighbor(geom,1)
# note that in reality, if both layers are the same, the nearest feature will always be itself
# in that case you should request 2 nearest neighbors and remove the one with the same id as your current source feature
print(nearestIds)
for nearestId in nearestIds:
# get the geometry of nearest feature efficiently directly from the index without a slow feature request
nearestGeom = index.geometry(nearestId)
print(nearestGeom)
# or get the whole feature via a short getFeature() request
nearestFeat = layer.getFeature(nearestId)
print(nearestFeat)