李乃強(qiáng)
(江蘇省測(cè)繪工程院,江蘇 南京 210013)
Python作為一種高級(jí)程序設(shè)計(jì)語言,憑借其簡潔、易讀及可擴(kuò)展性日漸成為程序設(shè)計(jì)領(lǐng)域備受青睞的語言之一。使用Python作為ArcGIS的腳本語言將大大提升ArcGIS數(shù)據(jù)處理的效率,更好地實(shí)現(xiàn)ArcGIS內(nèi)部的任務(wù)自動(dòng)化[1]。
ArcPy 封裝了ArcGIS大部分功能進(jìn)而構(gòu)建而成的站點(diǎn)包,目的是以實(shí)用高效的方式通過 Python 執(zhí)行地理數(shù)據(jù)分析、數(shù)據(jù)轉(zhuǎn)換、數(shù)據(jù)管理和地圖自動(dòng)化創(chuàng)建基礎(chǔ)。
基于菜單界面的ArcGIS for Desktop能夠支持許多復(fù)雜的操作和空間分析,但用戶還需要更多的功能來解決遇到的難題。那么,通過Python腳本調(diào)用ArcPy可以自動(dòng)執(zhí)行在ArcGIS中需要通過菜單建模才能實(shí)現(xiàn)的繁瑣操作。例如,將1 000個(gè)shapefile文件轉(zhuǎn)成地理數(shù)據(jù)庫中的要素類,雖然可以運(yùn)行1 000次相應(yīng)的工具,但是在ArcGIS中肯定還有其他更高效和更簡捷的方法。這時(shí),只需要使用Python編寫一小段代碼就能解決這個(gè)問題。
地理空間數(shù)據(jù)在入庫之前,需要進(jìn)行屬性檢查、邏輯一致性等一系列檢查,空間數(shù)據(jù)包含屬性特征、幾何特征和拓?fù)涮卣?,通過Arcpy提供的方法,可以減少除拓?fù)溴e(cuò)誤編輯之外的重復(fù)性工作,實(shí)現(xiàn)數(shù)據(jù)檢查入庫流程的自動(dòng)化[2]。
在公開文獻(xiàn)中,基于Arcpy的腳本工具雖然已在地理國情監(jiān)測(cè)數(shù)據(jù)接邊檢查、長江河道水下空間數(shù)據(jù)提取批處理、建設(shè)用地?cái)?shù)據(jù)裁切、數(shù)據(jù)轉(zhuǎn)換等方面被廣泛應(yīng)用[3-5],主要通過ArcGIS基礎(chǔ)功能的組合應(yīng)用,但是對(duì)要素變化檢測(cè)、空間參考信息、拓?fù)錂z查等方面的高級(jí)功能描述較少。為此,本文結(jié)合最新版本的ArcPy站點(diǎn)包新擴(kuò)展功能,以土地利用更新數(shù)據(jù)檢查為例,介紹了相關(guān)技術(shù)原理和關(guān)鍵功能代碼。
Python的諸多特點(diǎn)使它可以作為ArcGIS的腳本語言,這些特點(diǎn)包括以下幾個(gè)方面:
1)簡單易學(xué)。相對(duì)于其他高度結(jié)構(gòu)化的編程語言(如C++或Visual Basic)而言,Python更容易被掌握。它的語法簡單,編程者將有更多的時(shí)間來解決實(shí)際問題,而不需要在學(xué)習(xí)Python語言上耗費(fèi)太多精力。
2)免費(fèi)且開源。Python是一款免費(fèi)并且開源的軟件,用戶可以自由地分發(fā)該軟件的副本,查看并修改源代碼,或者將其中一部分代碼用在其他免費(fèi)的程序里。Python語言如此好用的一個(gè)重要原因在于它有一個(gè)十分活躍的用戶社區(qū),社區(qū)里的成員都積極地參與Python的開發(fā)和維護(hù)。
3)跨平臺(tái)。Python支持包括Windows、Mac、Linux在內(nèi)的各種平臺(tái)。不同平臺(tái)上的Python程序只需要作極小的改動(dòng)甚至不改動(dòng),就能在其他平臺(tái)上正常運(yùn)行。由于ArcGIS for Desktop只能在Windows上運(yùn)行,所以Python的這種特性在ArcGIS中似乎沒有得到明顯的體現(xiàn),但是需要了解的是,Python的用戶之所以如此龐大,其中一個(gè)重要原因就是它跨平臺(tái)的特性。
4)解釋性。許多程序語言(如C++或Visual Basic)需要將程序源文件轉(zhuǎn)換成計(jì)算機(jī)可以理解的二進(jìn)制代碼。這就需要有適用于各種程序語言的編譯器。而Python是一種解釋性語言,它不需要編譯就可以直接運(yùn)行。這一特點(diǎn)使Python使用起來更加簡單,并具有更強(qiáng)的移植性。
5)面向?qū)ο?。Python是一門面向?qū)ο蟮木幊陶Z言。面向?qū)ο蟮某绦虿辉偈枪δ艿亩哑?,而是由一系列相互作用的?duì)象構(gòu)建起來的,很多現(xiàn)代編程語言都支持面向?qū)ο缶幊獭?/p>
與其他語言比較,Python也有不足之處:
1)Python大部分?jǐn)U展軟件包是由許多企業(yè)或個(gè)人開發(fā)和維護(hù),并沒有直接集成在Python軟件中,用戶如要用到這些軟件包,需要收集和安裝。
2)Python是解釋型語言,不是以本地機(jī)器碼運(yùn)行,所以運(yùn)行速度比編譯型語言慢。
ArcPy 封裝了ArcGIS大部分功能進(jìn)而構(gòu)建而成的站點(diǎn)包(見圖1)。目的是以實(shí)用高效的方式通過 Python 執(zhí)行地理數(shù)據(jù)分析、數(shù)據(jù)管理、數(shù)據(jù)轉(zhuǎn)換和地圖自動(dòng)化創(chuàng)建基礎(chǔ)[6-8]。
圖1 ArcPy體系結(jié)構(gòu)Fig.1 Arcpy architecture
地理空間數(shù)據(jù)質(zhì)檢內(nèi)容主要包括:要素幾何類型、空間參考系統(tǒng)、數(shù)據(jù)空間范圍等基礎(chǔ)檢查;字段類型、字段值域、關(guān)系類等要素類檢查;自相交、偽節(jié)點(diǎn)、懸掛點(diǎn)、壓蓋相交等拓?fù)錂z查[9]。
應(yīng)用arcpy.Describe函數(shù)不僅可以獲取FeatureClass、GDB FeatureClass、Table、Dataset的文件路徑、數(shù)據(jù)類型等通用屬性,還能獲取空間數(shù)據(jù)的幾何類型、要素類型、空間參考、是否具有空間索引等屬性信息。實(shí)現(xiàn)代碼如下:
def checkDataTypeAndSpatialRef(logger,landUseFeatureClass):
desc=arcpy.Describe(landUseFeatureClass)
#【要素類型獲取】
#要素的幾何類型
shapeType=desc.shapeType
#要素類型
featureType=desc.featureType
#【要素空間參考獲取】
#projectionName投影坐標(biāo)系名稱GCSName地理坐標(biāo)系名稱
spatial_ref=desc.spatialReference
要素類屬性結(jié)構(gòu)檢查主要針對(duì)要素類的入庫管理、變化監(jiān)測(cè)等應(yīng)用需求。
ArcPy提供了DetectFeatureChanges_management方法,可以實(shí)現(xiàn)對(duì)線狀地物的變化監(jiān)測(cè),查找更新線要素與基本線要素在空間上匹配的位置,并檢測(cè)空間更改、屬性更改或同時(shí)檢測(cè)這兩種更改以及無更改的情況,并創(chuàng)建一個(gè)包含匹配的更新要素及其更改信息、不匹配的更新要素和不匹配的基礎(chǔ)要素的輸出要素類[10],返回如圖2所示變化前后的線狀地物變化類型對(duì)照表。
圖2 線狀地物變化類型對(duì)照表Fig.2 Comparison of types for linear feature changes
圖2中變化檢測(cè)類型:
1)S代表空間,表示空間發(fā)生更改的匹配更新要素。
2)A代表屬性,表示屬性發(fā)生更改的匹配更新要素。
3)SA代表空間和屬性,表示空間和屬性均發(fā)生更改的匹配更新要素。
4)S_LD代表空間更改以及線的反方向。
5)SA_LD代表空間和屬性的更改以及線的反方向。
6)NC代表無更改,表示未發(fā)生任何更改的匹配更新要素。
7)N代表新要素,表示新加入基礎(chǔ)數(shù)據(jù)的不匹配更新要素。
8)D代表刪除,表示可能需要從基礎(chǔ)數(shù)據(jù)中刪除的不匹配基礎(chǔ)要素。
對(duì)于其他類型的要素,ArcPy提供了FeatureCompare_management方法,能夠得到整體的狀態(tài)信息,通過將需要入庫的要素類與目標(biāo)數(shù)據(jù)庫中的要素類進(jìn)行比較,如果幾何定義和字段屬性都相同,就可以進(jìn)行數(shù)據(jù)的增量追加了。代碼如下:
def checkAttrSchema(targetLandUseFeatureClass,landUseFeatureClass):
#【要素幾何定義和字段屬性檢查】
#得到總體描述
out_compare_file="D:/developdemo/dev2018dataschemaresult.txt"
compare_result=arcpy.FeatureCompare_management(targetLandUseFeatureClass,landUseFeatureClass,"OBJECTID","SCHEMA_ONLY","",".000000008983 Unknown",".001",".001","","","CONTINUE_COMPARE",out_compare_file)
#result.getOutput(1) 獲取此工具的狀態(tài)未檢測(cè)到差異時(shí)將顯示′true′值;檢測(cè)到差異時(shí)將顯示′false′值。
要素拓?fù)錂z查包括7個(gè)步驟:①創(chuàng)建數(shù)據(jù)集;②導(dǎo)入需要拓?fù)錂z查數(shù)據(jù);③創(chuàng)建拓?fù)洌虎芟蛲負(fù)渲刑砑右仡?;⑤添加拓?fù)湟?guī)則;⑥驗(yàn)證拓?fù)?;⑦?dǎo)出拓?fù)溴e(cuò)誤。本文主要介紹土地利用數(shù)據(jù)庫拓?fù)錂z查,創(chuàng)建拓?fù)錂z查的數(shù)據(jù)集,針對(duì)同一個(gè)圖層內(nèi)要素壓蓋、縫隙,不同圖層要素空間包含關(guān)系等圖形拓?fù)鋯栴}自動(dòng)化檢查。具體實(shí)現(xiàn)代碼如下:
def checkDataTopology(landUseFeatureClass,buildingFeatureClass,topoGdbPath):
#【拓?fù)錂z查】
#數(shù)據(jù)集中需要導(dǎo)入進(jìn)行拓?fù)錂z查的數(shù)據(jù)
landUseTopoFeature=topologyFeatureDataset+"/"+landUseFileNameNoExt
#根據(jù)土地利用類型抽取水田
expression="CLASS='水田'"
out_Layer="selectlayer"
arcpy.MakeFeatureLayer_management(landUseFeatureClass,out_Layer,expression,"","")
if int(arcpy.GetCount_management(out_Layer).getOutput(0)) > 0:
arcpy.CopyFeatures_management(out_Layer,landUseTopoFeature)
buildingTopoFeature=topologyFeatureDataset+"/"+buildingFileNameNoExt
arcpy.CopyFeatures_management(buildingFeatureClass,buildingTopoFeature)
#創(chuàng)建拓?fù)湟?guī)則
arcpy.CreateTopology_management(topologyFeatureDataset,topologyName,"")
#添加拓?fù)湟?guī)則適用的空間數(shù)據(jù)
arcpy.AddFeatureClassToTopology_management(in_topology,landUseTopoFeature,1,1)
arcpy.AddFeatureClassToTopology_management(in_topology,buildingTopoFeature,1,1)
#針對(duì)土地利用數(shù)據(jù)進(jìn)行單項(xiàng)檢查
#arcpy.AddRuleToTopology_management(in_topology,"Must Not Have Gaps (Area)",landUseTopoFeature,"","#","")
arcpy.AddRuleToTopology_management(in_topology,"Must Not Overlap (Area)",landUseTopoFeature,"","#","")
#針對(duì)建設(shè)用地?cái)?shù)據(jù)進(jìn)行壓蓋檢查
arcpy.AddRuleToTopology_management(in_topology,"Must Not Overlap With (Area-Area)",landUseTopoFeature,"",buildingTopoFeature,"")
拓?fù)錂z查錯(cuò)誤導(dǎo)出會(huì)按照數(shù)據(jù)集中的要素類型生成對(duì)應(yīng)的錯(cuò)誤要素。
采用Append的方法將質(zhì)檢通過的數(shù)據(jù)追加到數(shù)據(jù)庫中,并更新追加數(shù)據(jù)的相關(guān)屬性。實(shí)現(xiàn)代碼如下:
def data2TargetGDB(targetLandUseFeatureClass,landUseFeatureClass):
#【入庫更新】
arcpy.Append_management(landUseFeature-Class,targetLandUseFeatureClass,"NO_TEST",","")
queryfilter="timeVersion=""
fields=[′timeVersion′]
with arcpy.da.UpdateCursor(targetLandUseFeatureClass,fields,queryfilter) as cursor:
for row in cursor:
row[0]=datetime.datetime.now().strftime(′%Y-%m-%d %H:%M:%S′)
cursor.updateRow(row)
arcpy.AddMessage("地理空間數(shù)據(jù)入庫完成!")
本文詳細(xì)介紹了地理空間數(shù)據(jù)檢查的主要內(nèi)容,并結(jié)合要素類型和空間參考檢查、要素類屬性結(jié)構(gòu)檢查、要素拓?fù)錂z查、數(shù)據(jù)入庫和屬性更新等功能需求,介紹了利用 Python調(diào)用ArcPy相關(guān)功能函數(shù)的技術(shù)原理和實(shí)現(xiàn)代碼,可供同類項(xiàng)目借鑒。