Saya akan mengatakan ini adalah latihan geometris.
KODE PSEUDO:
- Untuk setiap titik (titik hitam) temukan jalan terdekat dan temukan proyeksi titik pada jalan ini (titik merah).
- Gambar garis pendek (putus-putus) dalam arah yang berlawanan mulai dari titik hitam
- Cari jika ada persimpangan antara garis pendek dan nama jalan yang sama, bintang biru. Jika ada satu, titik hitam adalah yang kita kejar.
Seperti yang dapat dilihat ada kasus khusus - titik hitam dilingkari:
- Jalan 1 baris sangat berkelok-kelok. Ini dapat dihilangkan dengan a) bekerja dengan 2 jalur jalan saja atau b) memastikan FID jalan yang memotong titik merah dan bintang berbeda. Namun jika jalan bendy memiliki persimpangan dengan jalan 1 jalur lainnya, ini mungkin tidak berfungsi.
- Titik hitam terletak pada perpanjangan jalan 1 garis persis tegak lurus. Dalam hal ini ada kemungkinan jalan 1 jalur dapat dipilih sebagai tetangga terdekat.
- Titik hitam berada di garis.
Semua kasus di atas sangat tidak mungkin, namun tampaknya opsi teraman adalah bekerja dengan 2 jalan saja, yaitu mengekspornya ke kelas fitur yang terpisah. Kasus 3 adalah yang lucu, kita akan membiarkannya kebetulan, karena jarak terpendek ke garis tidak pernah benar nol, dengan demikian arah sinar 'berlawanan' yang menghubungkan 2 titik dapat ditemukan.
Implementasi python:
import arcpy, traceback, os, sys
from arcpy import env
env.overwriteoutput=True
# things to change ---------
maxD=30
mxd = arcpy.mapping.MapDocument("CURRENT")
pointLR = arcpy.mapping.ListLayers(mxd,"NODES")[0]
lineLR = arcpy.mapping.ListLayers(mxd,"LINKS")[0]
sjOneToMany=r'D:\scratch\sj2.shp'
RDNAME='street'
# -------------------------
dDest=arcpy.Describe(lineLR)
SR=dDest.spatialReference
try:
def showPyMessage():
arcpy.AddMessage(str(time.ctime()) + " - " + message)
g = arcpy.Geometry()
geometryList=arcpy.CopyFeatures_management(pointLR,g)
n=len(geometryList)
endPoint=arcpy.Point()
arcpy.SpatialJoin_analysis(pointLR, lineLR,sjOneToMany,"JOIN_ONE_TO_MANY","KEEP_COMMON","","WITHIN_A_DISTANCE",maxD)
initFidList=(-1,)
for fid in range(n):
query='"TARGET_FID" = %s' %str(fid)
nearTable=arcpy.da.TableToNumPyArray(sjOneToMany,("TARGET_FID","JOIN_FID"),query)
if len(nearTable)<2:continue
fidLines=[int(row[1]) for row in nearTable]
query='"FID" in %s' %str(tuple(fidLines))
listOfLines={}
blackPoint=geometryList[fid]
with arcpy.da.SearchCursor(lineLR,("FID", "Shape@","STREET"),query) as rows:
dMin=100000
for row in rows:
shp=row[1];dCur=blackPoint.distanceTo(shp)
listOfLines[row[0]]=row[-2:]
if dCur<dMin:
fidNear,lineNear, roadNear=row
dMin=dCur
chainage=lineNear.measureOnLine(blackPoint)
redPoint=lineNear.positionAlongLine (chainage).firstPoint
smallD=blackPoint.distanceTo(redPoint)
fp=blackPoint.firstPoint
dX=(redPoint.X-fp.X)*(maxD-smallD)/smallD
dY=(redPoint.Y-fp.Y)*(maxD-smallD)/smallD
endPoint.X=fp.X-dX;endPoint.Y=fp.Y-dY
dashLine=arcpy.Polyline(arcpy.Array([fp,endPoint]),SR)
for n in listOfLines:
if n==fidNear:continue
line, road=listOfLines[n]
if road!=roadNear:continue
blueStars=dashLine.intersect(line,1)
if blueStars.partCount==0:continue
initFidList+=(fid,); break
query='"FID" in %s' %str(initFidList)
arcpy.SelectLayerByAttribute_management(pointLR, "NEW_SELECTION", query)
arcpy.AddMessage ('\n %i point(s) found' %(len(initFidList)-1))
except:
message = "\n*** PYTHON ERRORS *** "; showPyMessage()
message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
message = "Python Error Info: " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()
Ada solusi lain yang mungkin lebih elegan. Ini melibatkan triangulasi. Beri tahu saya jika ini menarik dan saya akan memperbarui jawaban saya