I've been trying to write an ArcPy script that gets the nearest point to the endpoint of a line feature and puts the value of a certain attribute into a field of the new layer and updates the row. Been trying to figure this out for weeks but nothing is working for me. I can't use Arcade, I've tried doing spatial join and that also didn't work. My path and everything works perfectly and the layer is being created just fine. but the problem is that the rows that I want updated in the new layer are not updating at all. Here is my code but please assume that all parameters and paths pertaining to things like MakeFeature and SelectByLocation are correct, because I believe that they are since the new layer is being created successfully. I believe there is a flaw with my logic for updating the cursor but I'm not sure where.
import arcpy
import numpy as np
arcpy.MakeFeatureLayer_management(parameter_drop, new_layer)
arcpy.SelectLayerByLocation_management(new_layer, "within", parameter_poly)
arcpy.AddMessage("Number of selected features: " + str(arcpy.GetCount_management(new_layer)[0]))
arcpy.CopyFeatures_management(new_layer, parameter_out)
arcpy.SelectLayerByLocation_management(parameter_SA, "WITHIN_A_DISTANCE", new_layer, "50 Feet")
with arcpy.da.UpdateCursor(new_layer, ["SHAPE@", "ADDRESS_TDS_LOCATION_ID"]) as cursor:
#get XY of endpoints on drop layer and loop through
for row in cursor:
#SHAPE@ method
drop = row[0]
end_x = drop.lastPoint.X
end_y = drop.lastPoint.Y
min_distance = float("inf")
#get XY of SA Layer and loop through features in SA layer
with arcpy.da.SearchCursor(parameter_SA, ["SHAPE@XY", "ADDRESS_UUID"]) as SA_cursor:
for SA_row in SA_cursor:
SA_x, SA_y = SA_row[0]
distance = np.sqrt((SA_x - end_x) ** 2 + (SA_y - end_y) ** 2)
if distance < min_distance:
row[1] = SA_row[1]
min_distance = distance
cursor.updateRow(row)
-
A quick review of your code it seems fine to me, but my question why always the lastpoint, what about the firstpoint? I think to improve this question you need to add some images of your data and a sketch of what YOU think should be correct?Hornbydd– Hornbydd2023年02月07日 15:48:29 +00:00Commented Feb 7, 2023 at 15:48
-
Numpy function might produce array not scalar value. Try [0] after it when computing distance. Much faster is using Near tool, selection and join field.FelixIP– FelixIP2023年02月08日 04:26:59 +00:00Commented Feb 8, 2023 at 4:26
1 Answer 1
I would approach the problem in a different way were I you.
You could pull out the point geometry and whatever attributes you want into a list with a search cursor - creating something like [id,attribute1,x,y,z]. Then during the update cursor just go through each line's end point and find the closest point with good old-fashioned math (if it's all numeric data then using numpy arrays can make it faster and easier to find the closest point. Once you do that you've got the attributes in list format, so it should be faster than having nested cursors (I don't recommend doing this)
Here's the pseudocode:
pointfeature = yourpointfeature
pt_fields = ["OBJECTID", "feature1", "Shape@X", "Shape@Y"]
pt_list = []
with arcpy.da.SearchCursor(pointfeature, fields) as cursor:
for row in cursor:
pt_list.append([row[0],row[1], row[2]])
#Then use this list during your main cursor loop:
with arcpy.da.SearchCursor(parameter_SA, ["SHAPE@XY", "ADDRESS_UUID"]) as SA_cursor:
for SA_row in SA_cursor:
SA_x, SA_y = SA_row[0]
min_dist = 1000.1
min_pt = "something"
for item in pt_list:
dist = sqrt( (SA_x - pt_list[1])**2 + (SA_y - pt_list[2])**2 )
if dist < min_dist:
min_dist = dist
min_pt = item
... and so on. (I'm too lazy to finish it out, but I think it would work - if it's only a slow implementation to solve the problem at hand)
-
Thank you. So far I did get it working but its fairly slow, depending how many rows it has to fill. What I do now is store the final value of row[1] in a list and then after I use an Update Cursor to put the contents of the list into the row of the new layer attribute table. I will try using numpy arrays for distance calculations and see if it runs faster. What exactly would I be storing in the numpy array? The data for calculating distance is all numeric.Live Strong– Live Strong2023年02月07日 20:35:52 +00:00Commented Feb 7, 2023 at 20:35
-
I think after writing your list - "pt_list" in the above code, pt_array = np.asarray(pt_list), and try the same routines with the array instead of the list. I suspect the impact won't be that great. Beyond that you can try putting in timestamps in around your code to see where it slows down. Or a more sophisticated method of timing your code. Just thought of something - were you only looking at the end points of each line? In that case using some sophistication to only pull the first and last vertex from each line for comparison will save you time. Also, for giggles ask OpenAI's chatGPTSmasher– Smasher2023年03月13日 17:48:52 +00:00Commented Mar 13, 2023 at 17:48