I’d say this is geometric exercise.
- For every point (black point) find nearest road and find point’s
projection on this road (red point).
- Draw short line (dashed) in opposite direction starting at black
- Find if there is intersection between short line and same name road,
blue star. If there is one, black point is the one we are after.
As one can see there are special cases – circled black points:
- Very twisty 1 line road. This can be eliminated by a) working with 2
line roads only or b) making sure FIDs of roads that intersect red
dot and star are different. However if bendy road has a junction
with another 1 line road, this might not work.
- Black point is sitting on extension of exactly perpendicular 1 line
road. In this case there is a chance that 1 lane road can be picked
as a nearest neighbour.
- Black point sits on the line.
All of above cases are very unlikely, nevertheless it seems that the safest option is to work with 2 line roads only, i.e. export them to a separate feature class.
Case 3 is a funny one, we’ll leave it to chance, because shortest distance to line is never true zero, thus ‘opposite’ direction of ray connecting 2 points can be found.
import arcpy, traceback, os, sys
from arcpy import env
# things to change ---------
mxd = arcpy.mapping.MapDocument("CURRENT")
pointLR = arcpy.mapping.ListLayers(mxd,"NODES")
lineLR = arcpy.mapping.ListLayers(mxd,"LINKS")
arcpy.AddMessage(str(time.ctime()) + " - " + message)
g = arcpy.Geometry()
for fid in range(n):
query='"TARGET_FID" = %s' %str(fid)
fidLines=[int(row) for row in nearTable]
query='"FID" in %s' %str(tuple(fidLines))
with arcpy.da.SearchCursor(lineLR,("FID", "Shape@","STREET"),query) as rows:
for row in rows:
for n in listOfLines:
query='"FID" in %s' %str(initFidList)
arcpy.SelectLayerByAttribute_management(pointLR, "NEW_SELECTION", query)
arcpy.AddMessage ('\n %i point(s) found' %(len(initFidList)-1))
message = "\n*** PYTHON ERRORS *** "; showPyMessage()
message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()); showPyMessage()
message = "Python Error Info: " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()
There is another possible solution perhaps more elegant. It involves triangulation. Let me know if it is of interest and I'll update my answer