邱建平 徐玉玲 劉文軍
(1.江西省自然資源測(cè)繪與監(jiān)測(cè)院 江西南昌 330002;2.江西省自然資源政策調(diào)查評(píng)估中心 江西南昌 330025)
地理數(shù)據(jù)處理是GIS 軟件功能的一個(gè)重要組成部分。作為測(cè)繪地理空間數(shù)據(jù)處理人員,經(jīng)常會(huì)遇到各類地理數(shù)據(jù)處理任務(wù),如數(shù)據(jù)格式轉(zhuǎn)換、矢量數(shù)據(jù)合并、影像裁剪、投影變換等,當(dāng)某個(gè)數(shù)據(jù)處理任務(wù)面臨數(shù)據(jù)量大、重復(fù)性操作時(shí),批處理方法的實(shí)現(xiàn)就顯得尤為重要。ArcGIS 軟件平臺(tái)中ArcTooLBox工具箱自帶有批處理方法[1],即右鍵ArcTooLBox 工具箱中的各工具,選擇“批處理”即可實(shí)現(xiàn)批處理操作,ArcTooLBox 工具箱批處理如圖1 所示。本文案例有兩個(gè)數(shù)據(jù)圖層,分別是點(diǎn)圖層和線圖層,當(dāng)比例尺很小的時(shí)候看起來(lái)點(diǎn)落在線上,即點(diǎn)和線相交(如圖2 所示),實(shí)際上將比例尺放大到一定程度時(shí),會(huì)發(fā)現(xiàn)點(diǎn)沒(méi)有落在線上,即點(diǎn)和線不相交(如圖3 所示)。現(xiàn)在的任務(wù)是將不在線上的點(diǎn)移動(dòng)到線上。傳統(tǒng)的方法是在ArcMap 桌面軟件中,加載點(diǎn)圖層和線圖層,進(jìn)行要素編輯,將顯示比例尺放大到最大程度,然后將點(diǎn)一個(gè)一個(gè)移動(dòng)到線上。然而當(dāng)數(shù)據(jù)量很大時(shí),需要移動(dòng)成千上萬(wàn)個(gè)點(diǎn),該方法是不明智的。能否找到一種快速而有效的方法來(lái)完成以上任務(wù),ArcGIS Python 腳本提供了解決方案。為此本文基于ArcGIS 鄰近分析思想,利用ArcGIS Python 腳本語(yǔ)言編程制作工具,批處理點(diǎn)線拓?fù)潢P(guān)系的檢查與修正,提高了工作效率,滿足了生產(chǎn)應(yīng)用需求。
圖1 ArcTooLBox工具箱批處理
圖2 點(diǎn)在線上(小比例尺顯示)
圖3 點(diǎn)未在線上(大比例尺顯示)
Python 是一種不受局限、可跨平臺(tái)的開(kāi)源編程語(yǔ)言[2-3]。Python 腳本因功能強(qiáng)大且易于上手、處理速度快的優(yōu)點(diǎn)被廣泛應(yīng)用,深受用戶認(rèn)可和支持[4-7]。Python 腳本語(yǔ)言可在腳本環(huán)境中獨(dú)立運(yùn)行,也可將其添加到工具箱中通過(guò)對(duì)話框或加入到模型中運(yùn)行[3]。為此,ESRI 將它作為腳本語(yǔ)言嵌入到ArcGIS中[8-12],從而使得ArcGIS軟件中所有能在ArcTooLBox工具箱或Model Builder模型構(gòu)建器中使用的工具都可以通過(guò)Python腳本進(jìn)行調(diào)用,表現(xiàn)出了強(qiáng)大的生命力。
本文的實(shí)例數(shù)據(jù)一個(gè)點(diǎn)圖層(公交站點(diǎn)數(shù)據(jù)),一個(gè)線圖層(公交路線數(shù)據(jù)),點(diǎn)數(shù)據(jù)量有420 個(gè),線數(shù)據(jù)量有30 條。在ArcMap 軟件中,加載以上點(diǎn)線數(shù)據(jù),將比例尺放大到最大程度,有些點(diǎn)落在線上,即點(diǎn)線相交,而有些點(diǎn)未落在線上,即點(diǎn)線未相交。
為進(jìn)一步挖掘數(shù)據(jù)的利用價(jià)值,要求點(diǎn)數(shù)據(jù)全部落在線上,即滿足點(diǎn)在線上的拓?fù)潢P(guān)系。最直接的方法是在ArcMap 桌面軟件中,加載點(diǎn)圖層和線圖層,進(jìn)行要素編輯,將圖形顯示比例尺放大到最大,然后將點(diǎn)一個(gè)一個(gè)移動(dòng)到線上;也可以利用ArcGIS中的鄰近分析工具,快速找出不滿足點(diǎn)在線上拓?fù)潢P(guān)系的數(shù)據(jù),再將點(diǎn)一個(gè)一個(gè)移動(dòng)到線上;然而完成點(diǎn)在線上的數(shù)據(jù)修正,需要大量的人工操作。
基于ArcGIS 鄰近分析思想[13],本文利用ArcGIS Python腳本語(yǔ)言編程制作工具[14],批處理自動(dòng)找出不在線上的點(diǎn),并將其移動(dòng)到最鄰近的線上,以滿足拓?fù)湟蟆?/p>
在Python 中分別獲取點(diǎn)、線兩個(gè)要素圖層數(shù)據(jù),通過(guò)鄰近分析,獲得點(diǎn)到線上的最近距離以及對(duì)應(yīng)的線上的點(diǎn)X、Y坐標(biāo),并寫入到點(diǎn)的屬性表中。再判斷是否滿足點(diǎn)在線上的拓?fù)湟?guī)則,若滿足則輸出結(jié)果;若不滿足則通過(guò)游標(biāo)獲得最近點(diǎn)的坐標(biāo)并根據(jù)該坐標(biāo)構(gòu)建一個(gè)新的點(diǎn),最后把對(duì)應(yīng)不相交點(diǎn)的屬性賦值給新點(diǎn),同時(shí)刪除原有點(diǎn)。具體技術(shù)路線圖如圖4所示。
圖4 技術(shù)路線圖
在ArcGIS 中建立Python 腳本主要有兩種方法[15]:一是在ArcGIS 軟件平臺(tái)中打開(kāi)Python 窗口編寫并執(zhí)行Python 代碼;二是在txt 文本編輯器中編寫Python 代碼,然后將其后綴改為“.py”,即可在ArcTooLBox 工具箱中進(jìn)行調(diào)用。由于Python窗口能夠支持代碼的自由編寫,具有代碼提示功能,因此本文選擇第一種方法建立腳本。打開(kāi)Python 窗口(如圖5 所示),將所有代碼編輯完成后,保存為Python腳本文件(*.py),然后在ArcTooLBox 工具箱中新建工具集,右鍵選擇添加腳本,按照向?qū)砑颖4婧玫哪_本文件即可,如圖6所示。
圖5 Python窗口
圖6 添加Python腳本
(1)添加路徑識(shí)別代碼
主要解決因數(shù)據(jù)存儲(chǔ)路徑中存在中文導(dǎo)致Python腳本無(wú)法識(shí)別數(shù)據(jù)的問(wèn)題,代碼如下:
import arcpy,sys,os,string
reload(sys)
sys.setdefaultencoding(“utf8”)
(2)獲得點(diǎn)線圖層數(shù)據(jù)
infc=r“D:Arcpy2dian.shp”#點(diǎn)數(shù)據(jù)
line=r“D:Arcpy2xian.shp”#線數(shù)據(jù)
(3)進(jìn)行鄰近分析
arcpy.Near_analysis(infc,line,“”,“true”)
(4)判斷是否滿足拓?fù)湟?guī)則,創(chuàng)建一個(gè)新點(diǎn)并輸出結(jié)果
#查詢游標(biāo)
rows=arcpy.UpdateCursor(infc)
for row in rows:
#距離大于零,表示不相交
if row.NEAR_DIST>0:
#插入游標(biāo)
cur=arcpy.InsertCursor(infc)
#創(chuàng)建一個(gè)空的新行
new_row=cur.newRow()
#創(chuàng)建一個(gè)新的點(diǎn)幾何
newpnt=arcpy.Point()
#把線上對(duì)應(yīng)點(diǎn)的坐標(biāo)賦值給新點(diǎn)
newpnt.X=row.NEAR_X
newpnt.Y=row.NEAR_Y pointGeometry=arcpy.PointGeometry(newpnt)
new_row.shape=pointGeometry
#把不相交點(diǎn)的屬性賦值給新點(diǎn) new_row.NEAR_DIST=row.NEAR_DIST
new_row.NEAR_X=row.NEAR_X
new_row.NEAR_Y=row.NEAR_Y
new_row.ID=row.ID
#插入新點(diǎn)
cur.insertRow(new_row)
#刪除不相交的點(diǎn)
#rows.deleteRow(row)
對(duì)建好的腳本,設(shè)置好各項(xiàng)腳本參數(shù),經(jīng)過(guò)測(cè)試運(yùn)行后,得到的結(jié)果是:滿足點(diǎn)在線上拓?fù)湟?guī)則那些點(diǎn)的位置不變,不滿足點(diǎn)在線上拓?fù)湟?guī)則點(diǎn)的位置發(fā)生了移動(dòng),即點(diǎn)落在線上了(如圖7 所示)。從運(yùn)行后點(diǎn)的屬性表中(如圖8 所示)可以看到,點(diǎn)圖層屬性表中增加了三個(gè)NEAR_DIST,NEAR_X,NEAR_Y 字段,分別表示點(diǎn)到線上的距離、線上點(diǎn)的X坐標(biāo)、線上點(diǎn)的Y坐標(biāo)。NEAR_DIST 值為0 表示點(diǎn)線已經(jīng)相交,即滿足點(diǎn)在線上的拓?fù)湟?guī)則,直接輸出結(jié)果;NEAR_DIST 值不為0則不滿足點(diǎn)在線上的拓?fù)湟?guī)則,要插入新點(diǎn)后輸出結(jié)果。屬性表中選中的部分即為新插入的點(diǎn),可以看到新插入點(diǎn)的屬性與對(duì)應(yīng)舊點(diǎn)的屬性一致(FID 除外)。
圖7 運(yùn)行后點(diǎn)落在線上
圖8 運(yùn)行后點(diǎn)的屬性截圖
最后,本文通過(guò)腳本代碼批處理執(zhí)行和人工操作實(shí)現(xiàn)點(diǎn)在線上的拓?fù)湟?guī)則檢查及將不在線上的點(diǎn)移動(dòng)到線上。將這兩種方法所耗時(shí)間和優(yōu)缺點(diǎn)進(jìn)行了對(duì)比分析,見(jiàn)表1所示。
表1 兩種方法及優(yōu)缺點(diǎn)對(duì)比匯總表
本文基于ArcGIS 鄰近分析思想,利用ArcGIS Python 腳本語(yǔ)言編程制作工具,批處理實(shí)現(xiàn)了對(duì)點(diǎn)線拓?fù)潢P(guān)系的檢查與修正,解決了實(shí)際生產(chǎn)中的問(wèn)題,具有高效、省時(shí)之優(yōu)勢(shì),為地理信息數(shù)據(jù)相關(guān)自動(dòng)化處理提供了解決方案。