I am trying to create python code to iterate through points on 1 layer and find the closest point on another layer (Road Chainages) based on attribute values. I need to limit the search to < 20m maximum distance between both matching attribute values.

I utilised code from Find the closest segment to a point which contains the same attribute and amended to suit point layers but i get stuck at the nearestNeighbor code. I believe i need to try to implement something similar to whats on this website Finding nearest line to point in QGIS? and somehow include the QgsSpatialIndex.nearestNeighbor (QgsPoint point, int neighbors)

I am using QGIS 2.18, but will look to update code to 3+ once i improve my skills.

#Based on 

from qgis.core import *
from PyQt4.QtCore import QVariant

##in development=group
##points=vector point
##point_attribute_to_match=field points
##Chainages=vector point
##Chainage_attribute_to_match=field Chainages
##Chainage_attribute_to_transfer=field Chainages
##tolerance=number 50

#get source and target objects
sources = processing.getObject(points)
linksLayer = processing.getObject(Chainages)

#add new field
newField = QgsField('Chain', QVariant.Int)
sourceIndex = sources.fieldNameIndex('Chain')

#variables for progress bar
percentMax = sources.featureCount()
p = 1

for s in sources.getFeatures():   

    #get geometry 
    if s.geometry():
        sGeometry = s.geometry().asPoint()
        if sGeometry == [0,0]:
            sGeometry = s.geometry().asMultiPoint()[0]

        progress.setText("no geometry found")

    #get nearest feature and write source attribute out
    sDistMin = 1000
    sourceId = -1
    for c in linksLayer.getFeatures(QgsFeatureRequest().setFilterRect(s.geometry().buffer(tolerance,5).boundingBox())):

       # print c.attribute(Chainage_attribute_to_match)  -  Research why this is failing.

        # Tried sDist = c.QgsSpatialIndex.nearestNeighbor(sGeometry,1) 
        # Tried sDist = c.geometry().nearestNeighbor(sGeometry,1)  .
        # Tried sDist = c.nearestNeighbor(sGeometry,1)  
        sDist = p.nearestNeighbor(sGeometry.asPoint(),1)

       if sDist < sDistMin and s.attribute(point_attribute_to_match) == c.attribute(Chainage_attribute_to_match):
                    sDistMin = sDist
                    sourceId = p.attribute(Chainage_attribute_to_transfer)

    if sourceId != -1:    
        sources.changeAttributeValue(s.id(), sourceIndex, sourceId)
        sourceId = -1

        progress.setText("no matching source found for: " + point_attribute_to_match)

    #set progress
    p += 1   


In my log i get { 'QgsFeature' object has no attribute 'nearestNeighbor' See log for more details }. see below.

2019-01-18T08:47:13 2   Uncaught error while executing algorithm
            Traceback (most recent call last):
              File "C:/PROGRA~1/QGIS2~1.18/apps/qgis-ltr/./python/plugins\processing\core\GeoAlgorithm.py", line 203, in execute
              File "C:/PROGRA~1/QGIS2~1.18/apps/qgis-ltr/./python/plugins\processing\script\ScriptAlgorithm.py", line 381, in processAlgorithm
                exec((script), ns)
              File "<string>", line 50, in <module>
            AttributeError: 'QgsFeature' object has no attribute 'nearestNeighbor'

  • 1
    that specific error refers to a (pretty common) syntax error; Pythons whole code block definition is based on indentation. outdent sDist = ... to match the if sDist ... line. note that I have not checked your code for anything else! – geozelot Jan 17 '19 at 14:56

Your error message relates to the fact that you are trying to call the nearestNeighbor method of a QGSFeature object, which does not exist. Even if try to call the same method of the geometry object that also does not exist.

Instead, try calling the distance method of the geometry object. The check for sDist < sDistMin takes care of the 'nearest' part.

sDist = p.geometry().distance(sGeometry)

  • Also - your Chainage_attribute_to_match object in instance of QGSField. You need to pass a string to c.attribute(), so try c.attribute( Chainage_attribute_to_match.name() ) – firefly-orange Jan 18 '19 at 10:31
  • QGIS returns this error to me, File "<string>", line 50, in <module> TypeError: QgsGeometry.distance(QgsGeometry): argument 1 has unexpected type 'QgsPoint'. I am having troubles understanding this error. In the geometry section it checks that their is a point feature in the source file, in the sDist = p.geometry()... measures the distance between features. Am i missing something with this code? – Pat Jan 18 '19 at 13:06
  • 1
    my bad, try: sDist = p.geometry().distance( s.geometry() ) – firefly-orange Jan 18 '19 at 16:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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