基於ArcGIS的python編程 5、Arcpy的一個簡單應用(近鄰分析工具進行點線拓撲)

前段時間在一個專業交流群里看到這樣的一個需求:有兩個圖層,一個線圖層,一個點圖層,比例尺小的時候看起來點是在線上的(相交),可是放大到一定程度的時候,點跟線是不相交的(如圖1,2),現在要做的就是要把不在線上的點移動在線上。按照一般的思路就是在桌面版軟體,進行要素編輯,放大到一定程度,然後一個一個點的移動在線上。但是數據量很大,幾萬個點,範圍很大,工作量很大,這個方法明顯是很不明智的。那時我在想,如果上頭給我這樣的一個任務,我怎麼辦??

圖1

圖2

群里也給出了很多解決方案,ARCMap里的近鄰分析工具,FME數據處理,CASS插件…………最好的方法還是是用編程來解決!

這裡我說說用Arcpy的解決方案:在python里分別獲得者兩個圖層(shape文件),通過近鄰分析,獲得點到線上的最近的距離以及對應的線上的點的x,y坐標,並寫入到點的屬性表中,然後通過游標獲得最近點的坐標並根據該坐標構建一個新的點,最後把對應不相交點的屬性賦值給新點。

因為我電腦安裝的Arcgis版本為10.0,所以只能用近鄰分析工具,該工具的Arcpy的語法如下圖3;如果是往後的版本會提供一個幾何對象的queryPointAndDistance(in_point,{as_percentage})方法,功能與近鄰分析工具差不多。建議要學Arcpy的盡量用10.1以後的版本。

圖3

過程如下:先進行 近鄰分析

#coding=utf-8nimport arcpynninfc=r"D:Arcpy2Export_Output.shp" #點數據nline=r"D:Arcpy2Export_Output_2.shp" #線數據nn#進行近鄰分析narcpy.Near_analysis(infc,line,"","true")n

運行這段代碼後,我們可以看到點圖層的屬性表中增加了三列NEAR_DIST,NEAR_X,NEAR_Y,分別表示點到線上的最短距離、線上點的X坐標、線上點的Y坐標如圖4,NEAR_DIST=0表示點線已經相交。

圖4

接下來通過查詢游標SearchCursor遍歷屬性表獲得線上點的X,Y坐標,利用該坐標構造新的點幾何;InsertCursor游標插入新的行。

rows=arcpy.SearchCursor(infc) #點的查詢游標nfor row in rows:n n if row.NEAR_DIST>0: #距離大於零,表示不相交nn cur=arcpy.InsertCursor(infc) #插入游標nn new_row = cur.newRow() #創建一個空的新行nn #創建一個新的點幾何n newpnt=arcpy.Point()n newpnt.X=row.NEAR_X #把線上對應點的信息賦值給新點n newpnt.Y=row.NEAR_Yn pointGeometry=arcpy.PointGeometry(newpnt)n new_row.shape = pointGeometrynn #把不相交點的屬性賦值給對應的新點n new_row.NEAR_DIST=row.NEAR_DISTn new_row.NEAR_X=row.NEAR_Xn new_row.NEAR_Y = row.NEAR_Yn new_row.ID=row.IDnn cur.insertRow(new_row) # 插入新點nn #rows.deleteRow(row) #刪除不相交的點n

運行後的結果如圖5,圖6所示,圖5選中部分(藍色)就是新插入的點。可以看到新點的屬性與對應的舊點的屬性是一致的(FID除外),如果要把不相交的點刪除,最後加上代碼:rows.deleteRow(row)即可。(刪除前要備份好源數據)

圖5

圖6

完整代碼如下:

#coding=utf-8nimport arcpynninfc=r"D:Arcpy2Export_Output.shp" #點數據nline=r"D:Arcpy2Export_Output_2.shp" #線數據nn#進行近鄰分析narcpy.Near_analysis(infc,line,"","true")nnrows=arcpy.SearchCursor(infc) #查詢游標nfor row in rows:n n if row.NEAR_DIST>0: #距離大於零,表示不相交nn cur=arcpy.InsertCursor(infc) #插入游標nn new_row = cur.newRow() #創建一個空的新行nn #創建一個新的點幾何n newpnt=arcpy.Point()nn newpnt.X=row.NEAR_X #把線上對應點的坐標賦值給新點n newpnt.Y=row.NEAR_Yn pointGeometry=arcpy.PointGeometry(newpnt)n new_row.shape = pointGeometrynn #把不相交點的屬性賦值給新點n new_row.NEAR_DIST=row.NEAR_DISTn new_row.NEAR_X=row.NEAR_Xn new_row.NEAR_Y = row.NEAR_Yn new_row.ID=row.IDnn cur.insertRow(new_row) # 插入新點nn #rows.deleteRow(row) #刪除不相交的點n

總結:

上面的代碼只是我的一個簡單的實驗,不到20行的代碼就可以為我們解決繁重的工作,可見編程對於我們的生活是多麼重要;始終都認為,不管什麼行業,編程的思維,能力都能夠帶給我們的生活,工作帶來便利。如果這要應用於實際項目的話還有很多地方需要完善;例如數據方面也是方便自己實驗而設計的,所以這裡只是提供一個解決問題思路而已,這個重新生成點,然後把新點的屬性賦值給新點的思路其實跟移動點到線上的需求的效果是一樣的。至於怎麼移動還沒琢磨出來,如果你有更好的解決方案,歡迎一起討論。

反思:

其實大三時就有接觸Arcpy了,可是為什麼在學校時就沒有好好學?那麼久了還沒什麼進步,這也是自己一直反思的地方,經過反覆的思考,可能是因為自己沒有深刻了解到某個東西的作用,所以就沒有動力去學,去堅持吧!一句話,沒有需求就沒有動力!所以建議在學校的同學,多點去了解自己的專業的工作都在幹什麼,看清差距,挖掘需求。這個實驗也是剛好在群里看到他們的需求,然後一直想如果是我,我該怎麼去便捷的完成,有了一個方向後,就認真去琢磨琢磨後還是弄出來了,過程儘管有點慢,可是還是學到東西了。

最近專欄的關注人數攀升了好多,有點「驚嚇」,感覺自己就是一個菜鳥在各位大神面前班門弄斧。不管怎樣,謝謝大家的關注,其實這也滿足了我小小的虛榮心。起初還擔心那麼多人關注,接下來我該怎麼辦?菜鳥一個,誤導了別人怎麼辦?後來想想,自己真的是多慮了,也太高估了自己能力了,哪有那麼容易誤導別人呢?另外,在這裡寫文章的一個好處就是可以儘早地把自己存在的問題拋出來,說不定哪路大神路過好心指導一下,那麼我就可以把這個問題解決了。這也是我當時決定在知乎寫東西的初衷吧。

最近實習的工作量開始加大了,有點吃力了,加上跟python沒什麼關係,一心很難二用,菜鳥表示很受傷;而且我暫時還沒什麼需求,所以接下來沒什麼時間更新專欄了,還是好好先搞好實習,掌握一樣東西再去學另一樣東西或許對於我來說會好的,貌似Arcgis engine裡面的方法對象原理跟Arcpy差不多。

如果你們有什麼好的需求,好的實驗,可以一起交流,一起學習,一起進步!


推薦閱讀:

利用 tesseract 解析簡單數字驗證碼圖片
[Python] 置換CPython 2.7.13的opcode
Tornado與flask的特點和區別有哪些?

TAG:GIS地理信息系统 | Python | ArcGIS |