Tôi muốn nói đây là bài tập hình học.
MÃ PSEUDO:
- Đối với mọi điểm (điểm đen), tìm đường gần nhất và tìm điểm chiếu trên đường này (điểm đỏ).
- Vẽ đường ngắn (nét đứt) theo hướng ngược lại bắt đầu từ điểm đen
- Tìm nếu có giao điểm giữa đường ngắn và đường cùng tên, ngôi sao màu xanh. Nếu có một, điểm đen là điểm chúng ta theo sau.
Như người ta có thể thấy có những trường hợp đặc biệt - những điểm đen được khoanh tròn:
- Rất ngoằn ngoèo 1 đường. Điều này có thể được loại bỏ bằng cách a) chỉ làm việc với 2 đường hoặc b) đảm bảo FID của các đường giao nhau giữa chấm đỏ và sao khác nhau. Tuy nhiên, nếu đường uốn cong có giao lộ với đường 1 khác, điều này có thể không hoạt động.
- Điểm đen đang ngồi trên phần mở rộng của đường 1 vuông góc chính xác. Trong trường hợp này, có khả năng 1 làn đường có thể được chọn làm hàng xóm gần nhất.
- Điểm đen nằm trên đường.
Tất cả các trường hợp trên đều rất khó xảy ra, tuy nhiên có vẻ như tùy chọn an toàn nhất là chỉ hoạt động với 2 đường, tức là xuất chúng sang một lớp tính năng riêng biệt. Trường hợp 3 là một trường hợp buồn cười, chúng ta sẽ để nó có cơ hội, bởi vì khoảng cách ngắn nhất đến đường thẳng không bao giờ đúng bằng 0, do đó có thể tìm thấy hướng ngược lại của tia nối 2 điểm.
Triển khai 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()
Có một giải pháp khả thi khác có lẽ thanh lịch hơn. Nó liên quan đến tam giác. Hãy cho tôi biết nếu đó là mối quan tâm và tôi sẽ cập nhật câu trả lời của mình