これは幾何学的な運動だと思います。
疑似コード:
- すべてのポイント(黒いポイント)について、最も近い道路を見つけ、この道路(赤いポイント)上のポイントの投影を見つけます。
- 黒い点から反対方向に短い線(破線)を描画します
- 短い線と同じ名前の道路、青い星の間に交差点があるかどうかを確認します。1つある場合は、黒い点が後のものです。
ご覧のとおり、特殊なケースがあります–丸で囲まれた黒い点:
- 非常にツイスティな1ラインの道路。これは、a)2線の道路のみで作業するか、b)赤い点と星と交差する道路のFIDが異なることを確認することで解消できます。ただし、曲がりくねった道路に別の単線道路との交差点がある場合、これは機能しない可能性があります。
- ブラックポイントは、正確に垂直な1線道路の延長上にあります。この場合、1車線の道路が最も近い隣人として選択される可能性があります。
- 黒い点が線上にあります。
上記のすべてのケースが発生する可能性は非常に低いですが、それでも、最も安全なオプションは2線の道路のみを処理すること、つまり別のフィーチャクラスにエクスポートすることです。ケース3は面白いものです。ラインまでの最短距離が真のゼロになることはないため、偶然に任せます。したがって、2点を結ぶ光線の「反対」方向が見つかります。
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()
おそらくもっとエレガントな別の解決策があります。三角測量が含まれます。興味がある場合はお知らせください。回答を更新します