Move Points to Closest Line with Same Line Number

2260
3
08-01-2011 03:39 AM
MikeSmith7
New Contributor II
I am trying to move some point that I have that are not snaped to the edge of the line.  I want to make sure they are snapped to the right line given some are very close to an intersection. 

I keep getting the error:

Runtime error <class 'arcgisscripting.ExecuteError'>: ERROR 999999: Error executing function. Cannot acquire a lock. Cannot acquire a lock. [The table Points is being written by another process.] Failed to execute (Snap).

As you can see I have tried updatecursors, seachcursors and even just a plain old SelectLayerByAttribute_management.  I am stuck!!!

rows = arcpy.UpdateCursor("Points")
#rows = arcpy.SearchCursor("Points")
#rows = arcpy.SelectLayerByAttribute_management("Points","SUBSET_SELECTION","OBJECTID > 0")
mxd = arcpy.mapping.MapDocument("CURRENT")
print mxd.filePath
for row in rows:
    LINENO=row.getValue("Line_ID")
    print "LINENO " + LINENO
    for lyr in arcpy.mapping.ListLayers(mxd):
        #print "lyr.name " + lyr.name
        lyrname = lyr.name
        #for what ever reason, you can not use an = in the next statement
        if lyr.name in ["AllLines"]:
           print "LINENUMBER = '" + LINENO + "'"
           lyr.definitionQuery = "LINENUMBER = '" + LINENO + "'"
           snapEnv = [AllLines, "EDGE", "2 Meters"]
           arcpy.Snap_edit("Points", [snapEnv])
Tags (2)
0 Kudos
3 Replies
JakeSkinner
Esri Esteemed Contributor
Using the Update, Search, or Insert cursor function will place a lock on the feature class.  You will need to delete the 'row' and 'rows' variables.  You can do this by running 'del row, rows' at the end of your code.  Also, I noticed an error within your code.  You will need to change AllLines to "AllLines" within your snapEnv variable.  Ex:

import arcpy

rows = arcpy.UpdateCursor("Points")

mxd = arcpy.mapping.MapDocument("CURRENT")
print mxd.filePath

for row in rows:
    LINENO = row.getValue("Line_ID")
    print "LINENO " + str(LINENO)
    for lyr in arcpy.mapping.ListLayers(mxd):
        print "lyr.name " + lyr.name
        lyrname = lyr.name
        if lyr.name in ["AllLines"]:
            print "LINENUMBER = '" + str(LINENO) + "'"
            lyr.definitionQuery = "LINENUMBER = '" + str(LINENO) + "'"
            snapEnv = ["AllLines", "EDGE", "2 Meters"]
            arcpy.Snap_edit("Points", [snapEnv])

del row, rows, mxd 
0 Kudos
MikeSmith7
New Contributor II
The challenge with the del row, rows is that it is outside the loop and the layer is locked at that point.  I ended up creating a Line number array first, the performing the del row, rows and referencing the array during the loop.

rows = arcpy.SearchCursor("Points")
# Get a list of all the line numbers that we need to have transformers moved back onto the line
x=0
LineIDList = []
for row in rows:
    if row.getValue("line_id") not in LineIDList:
       x=x+1
       LineIDList.append(row.getValue("line_id"))
print str(x) + " Lines to have points that have been moved"    
try:
   del row
except:
   print arcpy.GetMessages(2)
try:
   del rows
except:
   print arcpy.GetMessages(2)
#now actually move those points
for count in range(0,x):
    for lyr in arcpy.mapping.ListLayers(mxd):
        lyrname = lyr.name
        #for what ever reason, you can not use an = in the next statement
        if lyr.name in ["AllLines"]:
           #print "LINENUMBER = '" + LineIDList[count] + "'"
           lyr.definitionQuery = "LINENUMBER = '" + LineIDList[count] + "'"
        if lyr.name in ["Points"]:
           lyr.definitionQuery = "line_id =  '" + LineIDList[count] + "'"
    try:
        snapEnv = ["AllLines", "EDGE", "2 Meters"]
        arcpy.Snap_edit("Points", [snapEnv])
        #print "Got Snapped"
    except:
print arcpy.GetMessages(2)
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Glad to see you got this working!  The lock will only remain while the feature class is being updated.  Once the points have been moved, the lock is released.  A lock will be placed on the feature class using the 'arcpy.Snap_Edit' funciton as well, the difference being is that it is automatically released afterwards.  Below is the code that I was able to get working:

mxd = arcpy.mapping.MapDocument("CURRENT")

rows = arcpy.UpdateCursor("Points")

for row in rows:
    POINTNO = row.getValue("Line_ID")
    for lyr in arcpy.mapping.ListLayers(mxd):
        if lyr.name in "AllLines":
            lyr.definitionQuery = "\"LINENO\" = " + str(POINTNO)
            arcpy.RefreshActiveView()
        if lyr.name in "Points":
            lyr.definitionQuery = "\"POINTNO\" = " + str(POINTNO)
            arcpy.RefreshActiveView()
    snapEnv = ["AllLines", "EDGE", "5"]
    arcpy.Snap_edit("Points", [snapEnv])
    print "Snapped point successfully"
del row, rows, mxd


Also, as a hint, after copying/pasting your code you can select it and click the '#' symbol to wrap CODE tags around it. This will preserve the indentation of your script.
0 Kudos