邱世平,潘立仁,韋建飛
(1.崇左市林業(yè)勘測(cè)設(shè)計(jì)院,廣西 南寧 530001;2.廣西南寧林業(yè)勘測(cè)設(shè)計(jì)院,廣西 南寧 530001)
專題地圖作為一種突出反映多種自然要素、人文要素以及社會(huì)經(jīng)濟(jì)方面等的有效工具,在國土資源、環(huán)境規(guī)劃設(shè)計(jì)和林業(yè)勘測(cè)設(shè)計(jì)中得到廣泛應(yīng)用。然而,一些專題圖件的數(shù)量較多,需要通過批處理的方式生成,例如一些專題類的地質(zhì)圖、林業(yè)中的林班圖等[1]。
目前設(shè)計(jì)生產(chǎn)單位在批量出圖中大多通過計(jì)算機(jī)輔助制圖的方式進(jìn)行。繪圖類專業(yè)軟件有CorelDRAW、Adobe illustrator、CAD等。地理信息系統(tǒng)軟件有ArcGIS、MapGIS、QGIS等,擁有強(qiáng)大的符號(hào)庫、標(biāo)記庫以及豐富的色彩表現(xiàn)功能的繪圖類專業(yè)軟件,圖形要素不能很好地與地理信息關(guān)聯(lián),出圖效率以及自動(dòng)化出圖的能力無法與地理信息系統(tǒng)軟件相比。
ArcGIS功能非常強(qiáng)大,其根據(jù)不同的用戶需求提供多種應(yīng)用場(chǎng)景和服務(wù),是一套完整的、可伸縮的GIS軟件。ArcGIS軟件中的ArcMap自帶的數(shù)據(jù)驅(qū)動(dòng)頁面已基本能實(shí)現(xiàn)批處理功能,這種方式能批量生成PDF格式專題圖。然而在實(shí)際生產(chǎn)需要中大部分的專題圖的出圖格式需求多樣,如JPG、BMP等。另一些研究運(yùn)用Python腳本語言中Arcpy庫對(duì)專題圖制作方法進(jìn)行改進(jìn),基本實(shí)現(xiàn)了整個(gè)專題圖制圖流程的自動(dòng)化,但這種操作需要建立專題變量庫,當(dāng)制作不同專題圖時(shí),需要建立不同的專題變量庫,未充分利用ArcGIS中數(shù)據(jù)驅(qū)動(dòng)頁面功能[2-3]。
針對(duì)目前專題圖批處理存在的問題,本文主要?jiǎng)?chuàng)新點(diǎn)是基于ArcGIS Python語言,根據(jù)MXD文檔(ArcMap地圖文檔)模板結(jié)合數(shù)據(jù)驅(qū)動(dòng)頁面進(jìn)行批量出圖,提供JPG、PDF等多種格式的專題圖的導(dǎo)出,專題圖還自帶坐標(biāo)文件便于實(shí)際應(yīng)用的需要。
從ArcGIS 9.3開始ESRI已在ArcGIS中納入了Python,使得Python能夠用于GIS平臺(tái)數(shù)據(jù)分析、轉(zhuǎn)換與管理,也能夠快速實(shí)現(xiàn)地圖的自動(dòng)化,很大程度上提升了GIS的工作效率,特別是ArcGIS10中加入了ArcPy庫,使得其arcgisscripting模塊功能相較于先前版本得到更多的加強(qiáng)。ArcPy庫能夠?qū)崿F(xiàn)地理處理過程,運(yùn)用ArcPy站點(diǎn)功能調(diào)用其中的地理處理工具、函數(shù)以及模塊。
采用ArcPy在ArcGIS平臺(tái)上編寫應(yīng)用程序與腳本,能夠共享其他人員開發(fā)的大量Python模塊。ArcGIS10中引入了全新的Python窗口(圖1)來增強(qiáng)內(nèi)嵌于ArcGIS桌面的Python體驗(yàn),其作為Python的解釋器,替代了先前版本中的命令行窗口,但可便用ArcPy提供的Command函數(shù)來執(zhí)行以前的命令行語法。在ArcGIS平臺(tái)上的Python窗口,相關(guān)的開發(fā)人員能夠快速地在GIS軟件中應(yīng)用到Python。進(jìn)而便捷地實(shí)現(xiàn)了地理處理工具和功能的交互使用,也使Python模塊和庫得到充分利用。Python窗口提供了智能感知和代碼自動(dòng)完成功能。
圖1 Python窗口代碼輸入與執(zhí)行Fig.1 Code input and execution of Python window
基于MXD文檔(ArcMap地圖文檔)的Arcpy的專題圖批量出圖技術(shù)流程如下所述。首先遍歷文件目錄中的MXD文檔,然后將每個(gè)文件中所包含的圖層遍歷出來。獲取每個(gè)圖層后,需要先將圖層開啟顯示,然后調(diào)用ArcPy庫的方法將圖層輸出成JPG或PDF文件,完成后關(guān)閉該圖層,最后遍歷完畢地圖也輸出完畢(圖2)[6-8]。
圖2 批量出圖技術(shù)流程Fig.2 Technical process of batch mapping
ArcPy.mapping模塊里常用的類有MapDocument、DataFrame、Layer、DataDrivenPages和TextElement。MapDocument類是地圖文檔(.mxd文件)對(duì)應(yīng)的類。初始化參數(shù)是一個(gè)字符串,一般是.mxd文件的路徑:
mxd=arcpy.mapping.MapDocument(r"F:GeoDataChinaAreaChinaVector.mxd")
DataFrame類用于操作地圖內(nèi)的Data Frame(即下圖的Layers),能夠控制地圖的范圍、比例尺等。用ArcPy.mapping.ListDataFrames(map_document,{wildcard})函數(shù)獲取。
df= arcpy.mapping.ListDataFrames(mxd)[0]
Layer類用于操作具體的圖層。能夠控制圖斑的樣式、可見性等[8]??梢杂?lyr文件的路徑初始化,也可以通過arcpy.mapping.ListLayers(map_document_or_layer,{wildcard},{data_frame})函數(shù)獲取。
lyr1=arcpy.mapping.Layer(r" F:GeoDataChinaAreaProvince.lyr")
df.addLayer(lyr1)
lyr2=arcpy.mapping.ListLayer(mxd,"",df)[0]
DataDrivenPages類需要配合ArcMap中的Data Driven Pages工具使用。用于一個(gè)矢量文件內(nèi)的全部或部分圖斑每個(gè)出一張圖的情況[9-10]。TextElement類用于操作地圖上的文字,比如圖名、頁數(shù)。通過arcpy.mapping.ListLayoutElements(map_document,{element_type},{wildcard})函數(shù)獲取。
txtElm=arcpy.mapping.ListLayoutElements(mxd,"TEXT_ELEMENT")[0]
常見的出圖模式有2種:一個(gè)矢量文件里每個(gè)圖斑出一張圖,一個(gè)文件夾下每個(gè)矢量文件出一張圖。
2.3.1代碼實(shí)現(xiàn)
首先需要制作一個(gè)在數(shù)據(jù)驅(qū)動(dòng)頁下設(shè)置好索引圖層、字段以及比例的MXD文檔。借助ArcMap工具的ArcToolBox工具箱,新建一個(gè)工具箱。在新建工具箱中添加一個(gè)腳本,之后在腳本屬性中編寫驗(yàn)證代碼,腳本的代碼設(shè)計(jì)如下:
1)第一步:在腳本的屬性中“驗(yàn)證”欄下def updateParameters(self):函數(shù)中,編寫遍歷MXD文檔的核心代碼:
#以下代碼是遍歷MXD文檔中的圖層列表
qsplyrs=arcpy.mapping.ListLayers(qspmxd)//列出MXD文檔的LYR圖層
qsplayerList=[]
for qsplyr in qsplyrs://執(zhí)行循環(huán)
qsplayerList.append(qsplyr.name) //列出圖層名
uniqueLayerList=list(set(qsplayerList)) //將列出的圖層名顯示在下拉菜單中
uniqueLayerList.sort()
2)第二步:依次遍歷獲取索引圖層以及索引字段
#以下代碼是依次遍歷獲取索引圖層以及索引字段
qspseleLayer=self.params[1].value
qsplayerRef=arcpy.mapping.ListLayers(qspmxd,qspseleLayer)[0]//列出圖層
qspfields=arcpy.ListFields(qsplayerRef.dataSource)
qspfieldList=[]
for qspfield in qspfields://執(zhí)行循環(huán)
qspfieldList.append(qspfield.name) //列出字段名
uniqueFieldList=list(set(qspfieldList)) //將列出的圖層名顯示在下拉菜單中
uniqueFieldList.sort()
3)第三步:獲取索引字段后,將索引字段列表于“選擇索引字段內(nèi)容”中
qsprows=arcpy.SearchCursor(qsplayerRef.dataSource)//搜索圖層的數(shù)據(jù)源
qsprow=qsprows.next()//游標(biāo)移動(dòng)到下一條記錄
qsppageNameList=[]//驅(qū)動(dòng)頁名稱列表
while qsprow://執(zhí)行循環(huán)選擇字段列表的記錄
if qsprow.getValue(qspfieldName) not in qsppageNameList:
qsppageNameList.append(qsprow.getValue(qspfieldName))
qsprow=qsprows.next()
qsppageNameList.sort()
4)第四步:依次設(shè)置好余下的“選擇成果放置文件夾”、“設(shè)置照片像素”等參數(shù)內(nèi)容。進(jìn)入核心代碼批量另存為單個(gè)MXD文檔
for eachPage in pageList://執(zhí)行循環(huán)導(dǎo)出MXD文檔
arcpy.AddMessage(str(eachPage)+".mxd")
pageID=ddp.getPageIDFromName(str(eachPage.strip("'")))//逐頁名稱賦值給pageID
ddp.currentPageID=pageID//設(shè)置pageID為當(dāng)前MXD文檔
if tpgs == ‘pdfzh’:
ddp.printPages(printerzh,"CURRENT")
qspmxd.saveACopy(printer+str(eachPage)+".mxd")
elif not(tpgs == ‘pdfzh’):
qspmxd.saveACopy(printer+str(eachPage)+".mxd")//另存一個(gè)MXD文檔
5)第五步:批量將“選擇成果放置文件夾”下的MXD文檔導(dǎo)出為JPG或PDF圖件
for qspf in os.listdir(path)://遍歷文件夾下的MXD文檔
if qspf[-3:].lower() ==‘mxd’:
if tpgs ==‘jpg’://當(dāng)參數(shù)選擇為JPG時(shí)
arcpy.AddMessage(str(qspf)+".jpge")
qspmxd=arcpy.mapping.MapDocument(os.path.join(path,afile))
arcpy.mapping.ExportToJPEG(qspmxd,os.path.join(path,afile[:-3]+‘'jpg’),resolution= qspres)//導(dǎo)出JPG格式圖件
if tpgs == ‘pdf’://當(dāng)參數(shù)選擇為PDF時(shí)
arcpy.AddMessage(str(qspf)+".pdf")
qspmxd=arcpy.mapping.MapDocument(os.path.join(path,qspf))
arcpy.mapping.ExportToPDF(qspmxd,os.path.join(path,qspf[:-3]+‘pdf’),resolution=qspres)//導(dǎo)出PDF格式圖件
2.3.2操作流程
在ArcMap布局或數(shù)據(jù)視圖下設(shè)置:索引圖層和索引字段的數(shù)據(jù)驅(qū)動(dòng)頁設(shè)置—保存MXD文檔—使用本程序打開MXD文檔模板—選擇索引圖層—選擇索引圖層出圖字段—選擇索引字段內(nèi)容(在字段內(nèi)容列表中選擇批量成圖的記錄數(shù))—設(shè)置成果放置文件夾—設(shè)置導(dǎo)出圖片像素—設(shè)置出圖格式—執(zhí)行程序。制作的工具如圖3所示。
以崇左市群力林場(chǎng)為實(shí)例,進(jìn)行了林場(chǎng)森林分布圖專題圖的批處理工作(圖4)。本文MXD文檔結(jié)合數(shù)據(jù)驅(qū)動(dòng)頁面方法的優(yōu)勢(shì)主要表現(xiàn)在:1)充分利用了ArcGIS數(shù)據(jù)驅(qū)動(dòng)頁面的優(yōu)勢(shì),批量生成具有坐標(biāo)信息的專題圖;2)充分利用了ArcGIS自帶的符
圖3 批量出圖工具展示Fig.3 Display of batch mapping tools
號(hào)庫、變量庫等,不需要制作專門的變量庫;3)由圖5可見,導(dǎo)出專題圖的同時(shí),生成對(duì)應(yīng)的MXD文檔,便于個(gè)別圖幅的靈活修改??傮w而言,基于ArcGIS Python語言,根據(jù)MXD文檔(ArcMap地圖文檔)模板結(jié)合數(shù)據(jù)驅(qū)動(dòng)頁面進(jìn)行批量出圖,提供JPG、PDF等多種格式的專題圖的導(dǎo)出,專題圖還自帶坐標(biāo)信息便于實(shí)際應(yīng)用的需要。
由表1可以看到,ArcPy結(jié)合專題變量庫方式與MXD文檔結(jié)合數(shù)據(jù)驅(qū)動(dòng)頁面對(duì)比:1)前者操作相對(duì)復(fù)雜,需要進(jìn)行專門使用培訓(xùn),而后者只需要知道簡單的ArcGIS操作便可熟練使用;2)前者需要編寫較多的代碼,設(shè)定專門的符號(hào)庫、變量庫等,后者能充分利用ArcGIS自身功能,簡化復(fù)雜程度;3)在靈活設(shè)計(jì)方面,由于前者針對(duì)的是某一方面的專題圖,當(dāng)需要制作另外一種模式的專題圖時(shí),需要進(jìn)行代碼的大幅修改,而后者進(jìn)行簡單的修改就能適應(yīng)不同的專題圖的需求。
圖5 成圖目錄Fig.5 Mapping catalogue
表1 2種批處理方式的對(duì)比
本文主要?jiǎng)?chuàng)新點(diǎn)是基于ArcGIS Python語言,根據(jù)MXD文檔(ArcMap地圖文檔)模板結(jié)合數(shù)據(jù)驅(qū)動(dòng)頁面進(jìn)行批量出圖?;具^程是首先遍歷文件目錄中的MXD文檔,然后將每個(gè)文件中所包含的圖層遍歷出來。獲取每個(gè)圖層后,需要先將圖層開啟顯示,然后調(diào)用ArcPy庫的方法將圖層輸出成JPG或PDF文件,完成后關(guān)閉該圖層,最后遍歷完畢地圖也輸出完畢。批量出圖實(shí)現(xiàn)過程中有2種出圖模式,即一個(gè)矢量文件里每個(gè)圖斑出一張圖,一個(gè)文件夾下每個(gè)矢量文件出一張圖。使用中需要根據(jù)實(shí)際需要選擇合適的出圖模式。
本文提出的批量處理方式可以達(dá)到節(jié)省人力和作業(yè)時(shí)間的目的。專題地圖制作是個(gè)繁瑣的作業(yè)過程。雖然本文通過MXD文檔的方式解決原有批量出圖的部分問題,該方法的推廣將有助于專題制圖更靈活的設(shè)計(jì)和更加的智能化,但完全自動(dòng)化的批量出圖仍需要進(jìn)一步探索。