0

I took this code from this source Select maximum number of points more than x meters apart

It seems to work for other users, but for me it's an endless loop. I do not understand why, though the code makes sense. The code itself gives me the result I want to get.

Can you help me out of this endless loop:

import arcpy, sys

feature = arcpy.GetParameterAsText(0)
distance = 500

arcpy.gp.overwriteOutput = True

#running NEAR analysis - every point gets attribute of a distance to the nearest point 
#in same feature class
arcpy.AddMessage("running first near analysis")
arcpy.Near_analysis(feature, feature)

arcpy.AddMessage("inserting cursor")
cur = arcpy.UpdateCursor(feature)
row = cur.next()

arcpy.AddMessage("starting loop")

i=0
while row:
    i+=1
    #fids list will store list of deleted points so if any other point will have 
    #deleted one as the nearest and distance < 150 will not get deleted as this
    #distance is no longer true
    fids = []
    while row:
        if row.NEAR_DIST < distance:
            try:
                #it seems I didn't know if .. in .. at the time ;) such a fun to dig
                #this script up! index throws an exception if element is not in the 
                #list
                fids.index(row.NEAR_FID)
                arcpy.AddMessage("OBJECTID = " + str(row.OBJECTID) + " is listed!")
            except:
                arcpy.AddMessage("deleting OBJECTID = " + str(row.OBJECTID))
                fids.append(row.FID)
                cur.deleteRow(row)
                d = 1
        row = cur.next()
    del cur, row, fids
    try:
        #this idiotic test is to break the loop when no points will have 
        #NEAR_DIST < 150, shameful - I know!
        if d == 1:
            pass
    except:
        sys.exit()
    d = 0
    arcpy.AddMessage("loop iteration " + str(i))

    #and again we go..
    arcpy.Near_analysis(feature, feature)
    cur = arcpy.UpdateCursor(feature)
    row = cur.next()

The functional CODE:

import arcpy, sys

feature = arcpy.GetParameterAsText(0)

def nearRoutine():
    #calculate the distances using the current dataset
    arcpy.Near_analysis(feature, feature)

    #iterate through any features which are within the distance
    cur = arcpy.UpdateCursor(feature, '"NEAR_DIST" < 500')
    row1 = cur.next()
    while row1:

        #this point is within the distance of its neighbor, so delete it
        cur.deleteRow(row1)

        #now re-run this routine on the new dataset
        del row1, cur
        cur = arcpy.UpdateCursor(feature, '"NEAR_DIST" < 500')
        row1 = cur.next()
        nearRoutine

#call the recursive routine. It will get progressively faster to run as it will loop through fewer points each time
nearRoutine()

Thanks @Stephen Lead

  • I really dislike how people use the while loop in arcpy and pyqgis to loop features. It is almost never needed and is error prone. Not your fault as you just copied it. Just a mini rant – Nathan W Aug 1 '13 at 13:43
  • I agree, @NathanW. It doesn't seem as intuitive to me what is going on. You don't need to use .next() in a for loop, and you have a built in counter with enumerate(). – Paul Aug 1 '13 at 14:56
0

Disclaimer - I haven't actually tried to run your code, and have only skimmed it briefly.

But it looks like you have two while row loops. Try using two unrelated cursors, eg row1, row2

EDIT: here is an approach which uses a recursive script to perform the NEAR. Each time you delete a point, the NEAR function is called again. (I don't have access to an ArcInfo license so I can't actually test it, so perhaps treat this as pseudo-code):

import arcpy, sys

feature = arcpy.GetParameterAsText(0)
distance = 500

def nearRoutine():
    #calculate the distances using the current dataset
    arcpy.Near_analysis(feature, feature)

    #iterate through any features which are within the distance
    cur = arcpy.UpdateCursor(feature, NEAR_DIST < distance)
    row = cur.next()
    while row:

        #this point is within the distance of its neighbor, so delete it
        cur.deleteRow(row)

        #now re-run this routine on the new dataset
        del row, cur
        nearRoutine

#call the recursive routine. It will get progressively faster to run as it will loop through fewer points each time
nearRoutine()
  • I was thinking that and because feature never gets redefined so it's doing the same thing over and over – Nathan W Aug 1 '13 at 13:53
  • 1
    Also, you're deleting the row during the Except clause. It's generally a bad idea to manipulate an array while you're traversing it, since it messes up the indexing (eg, cursor.next is no longer the "next" feature you're expecting) – Stephen Lead Aug 1 '13 at 13:55
  • I'm sorry I have a very low level programming so your possible solutions are real headache for me. However I believe that the entities that update because when I power the end of the program, it deleted all the fields exactly as I wanted – user19717 Aug 1 '13 at 15:23
0

Another approach is to use the Simplify Line command. This will remove all extraneous vertices within a given distance, aka "delete point in a distance of x meters"

Esri have already done the hard work of writing this function so you might as well use it...

0
import math
#calculate distance in 2 D
def distance(a,b) : 
    return math.sqrt(pow((a[0]-b[0]),2) + pow((a[1]-b[1]),2) )

#
def clean_array2d(array,limit) :
    result = array 
    i = 0 
    while(i < len(array))  : 
        j = 0 
        while(j < len(result)) :  
            if j != i    : 
                dist  = distance(array[i], result[j]) 
                if dist < limit : 
                    result.pop(j)
            j = j + 1 
        i = i + 1 

    return result
dist = 10  
arr = [(974, 34), (975, 34), (976, 34)]

print(clean(arr,dist)) #[(976, 34)]

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.