



[關鍵詞]主要河流;界樁埋設;Python;批量賦值
為了加強生態(tài)文明建設、適應自然資源部門管理需要,山西省第三次土地調查領導小組辦公室安排開展山西省主要河流土地資源調查項目建設,進行山西省域范圍內汾河、滹沱河等主要河流的土地資源調查工作。按照項目實施方案要求,需要對主要河流治導線與各級行政區(qū)域界線交界點處設置治導線埋設點標識,進而明確河道管理范圍,為河道劃界提供數據支撐。該項成果除了提交基礎矢量數據,還要形成圖件報表,方便后續(xù)成果統計分析,為推動我省河長制管理工作提供服務。
Python由荷蘭數學和計算機科學研究學會的Guidovan Rossum設計開發(fā),是一種解釋型、面向對象、動態(tài)數據類型的高級程序設計語言,不僅繼承了傳統編譯語言的強大性和通用性,而且借鑒了腳本語言和解釋語言的易用性[1]。Python結構簡單,語法明確,代碼清晰,易于閱讀,源代碼開放且容易維護,適合非編程人員快速上手[2]。本項目選擇Python語言通過批量賦值實現河流界樁矢量數據向圖表成果的轉換,將復雜的文檔轉化工作簡化,還可應對不同組織形式的Word文檔,規(guī)避了大量人工格式調整和文檔整合的工作[3]。
1. 工作流程
本項目主要在第三次國土調查的工作界線(市、縣、鄉(xiāng)鎮(zhèn)、村界)與主要河流治導線相交處設置治導線埋設點,基于0.5 m格網間距數字高程模型和1∶2000數字正射影像圖等項目已有成果,獲得不同行政級別的埋設點,其中市級和縣級埋設點要求實地埋設標識,若通過影像內業(yè)判斷或實地踏勘發(fā)現實地不具有設置埋設點標識的條件,此類型改為電子埋設點;鄉(xiāng)鎮(zhèn)級和村級埋設點利用已有成果資料建立電子埋設點。本文以如何批量生成電子埋設點圖表成果為例進行詳述,流程圖(圖1)如下:
2. 數據處理
埋設點屬性由BM、POINT_X、POINT_Y、POINT_Z、SZD 和BZ 組成,具體意義及格式見表1。BM格式中的埋設點序號依照河流上下游順序編號,類型碼依照與市級、縣級、鄉(xiāng)鎮(zhèn)級和村級三調工作界相交處分別標識為S、X、Y、C.POINT_Z基于0.5m格網間距的DEM提取獲得,SZD格式中“/”左側填寫所在地,右側填寫相鄰地,判斷標準依照河流上下游順序。BZ若為實地埋設點,填“Y”,否則為空。
以滹沱河村級埋設點為例,圖2左側為項目要求模板,需要將每個埋設點的屬性逐個填入模板對應位置,圖2右側為成果展示。模板表格中“編號”“所在地”、H由表1的“BM”“SZD”和“POINT_Z”得到;“所屬河流名稱”、B、L分別表示埋設點所屬的河流、埋設點的“緯度”“經度”,由矢量數據隱藏屬性得到;“點位三維模型示意圖”為三維模型上疊加電子埋設點標識的截圖,優(yōu)先選擇傾斜三維模型成果數據,由DasViewer加載顯示,若無該類成果,選擇DOM、DEM構成的地形級三維模型,由EasyEarth加載顯示;“整體位置”和“局部放大”為1∶2000 DOM上疊加電子埋設點點位的截圖,由ArcGIS加載顯示。滹沱河村級埋設點共有303個,若按照模板表格逐個輸入,不僅工作量大,還易出錯,因此引入Python語言實現批量賦值。鑒于模板表格不僅有數值輸入,還有圖片插入,在運用批量賦值前需對數據編輯整理,具體過程如下:
2.1 Excel 數據獲取
2.1.1新建字段
在ArcGIS 中新建點狀矢量圖層,投影坐標系為CGCS2000_3_Degree_GK_CM_114E。按表1要求新建字段,分別命名為BM、POINT_X、POINT_Y、SZD和BZ。為了方便后期表格賦值,新建過渡字段,分別命名為序號、市、縣、鄉(xiāng)鎮(zhèn)、所在村、相鄰村、經度、緯度、河流。
滹沱河范圍涉及忻州、陽泉地區(qū),埋設點位置由忻州、陽泉的三調村界與滹沱河治導線的交點得到,通過地理處理下的相交工具獲得并賦值到點狀矢量。以1:2000數字正射影像為底圖,以項目前期獲得的河流復核細化成果為依據,按照從上游到下游的順序逐個查看埋設點位,并填寫各項屬性。
2.1.2賦值字段
過渡字段“河流”為固定值,通過字段計算器統賦為滹沱河。過渡字段“序號”“市”“縣”“鄉(xiāng)鎮(zhèn)”“所在村”“相鄰村”通過逐個查看埋設點,參考河流復核細化成果得到。過渡字段“緯度”和“經度”需要將矢量數據投影轉換為大地坐標CGCS2000后通過計算幾何命令得到。
必填字段“BM”和“SZD”的值由過渡字段組合得到,運用字段計算器輸入公式分別為“HT00+序號+C”和“ 市+縣+鄉(xiāng)鎮(zhèn)+所在村+/+相鄰村”。必填字段“POINT_X”和“POINT_Y”由計算幾何命令得到。由于村級埋設點都是電子埋設,必填字段“BZ”為空。
2.1.3格式轉換
屬性編輯無誤后運用ArcToolbox 下的轉換工具將屬性表轉化成Excel 格式導出,命名為“村級埋設點.xlsx”(圖3),同時將原始矢量數據屬性表的過渡字段全部刪除,保存為最終矢量成果。
2.2 圖片數據獲取
模板表格中有三處需要插入圖片,其中“點位三維模型示意圖”是將三維成果旋轉一定角度進行截圖,以期展示最佳的立體效果,每個點位周邊地物高低起伏情況不同,選取的最佳角度也不同,該項工作需要人工判讀逐點截圖,根據表格大小確定截圖范圍7 cm×7 cm為,按BM命名存儲為JPG格式,保存在命名為三維視圖的文件夾中。
“整體位置”和“局部放大”圖是平面截圖,需在ArcGIS中實現,該軟件自9.0版本開始引入腳本處理技術并將Python作為其支持的腳本語言之一[4],通過Arcpy模塊功能實現批量截圖,具體過程如下:
(1)新建Arcmap工程文件,加載村級埋設點矢量數據和1∶2000數字正射影像圖,根據表格大小確定“整體位置”和“局部放大”圖的顯示比例尺分別以1∶3000和1∶800為佳。在頁面和打印設置中選擇自定義大小,寬度和高度分別為7 cm。
(2)切換到布局視圖,數據框和頁面大小不匹配,通過對數據框右鍵選擇分布,進一步選擇調整到頁邊距大小,使數據框和頁面大小重合,同時設置數據框邊框格式為無。
(3)以“整體位置”圖為例,將當前布局視圖的比例尺固定到1∶3000,打開村級埋設點矢量數據的屬性表,選擇第一行,右鍵選擇縮放至圖層,使矢量數據居中顯示,保證后續(xù)每個埋設點都自動居中顯示。
(4)打開頁面和打印設置,選擇數據驅動頁面[5],啟動后定義選項卡中索引圖層選擇為村級埋設點矢量圖層,范圍選項卡選擇居中并保持當前比例。
5.Arcpy作為ArcGIS自帶的封裝包,提供了很多用于處理和查詢GIS 數據的函數和類,通過調用Arcpy輸入以下代碼實現批量導出指定范圍的圖片。
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
mxd = arcpy.mapping.MapDocument(\"CURRENT\")
for pageNum in range(1,mxd.dataDrivenPages.page?Count+1):
mxd.dataDrivenPages.currentPageID=pageNum
fieldname=u\"BM\"#設置指定字段
a=mxd. dataDrivenPages. pageRow. getValue(field?name)
path=r\"D:\整體位置\"#設置文件保存路徑
path_2=os.path.join(path,str(a))
arcpy.mapping.ExportToJPEG(mxd,path_2+\".jpg\",resolution=400)#設置圖片命名的格式和分辨率
del mxd
D盤目錄下新建2個文件夾,分別命名為整體位置和局部放大,來存儲2種類型的截圖。運行上述代碼后,整體位置文件夾會生成以BM命名的303個圖片,將當前布局視圖的比例尺固定到1:800,并修改文件保存路徑后再次運行代碼,局部放大文件夾也會生成303個圖片。三個文件夾生成圖片成果如圖4所示:
3. 成果整理
根據Excel 數據、JPG 數據與模板表格的對應關系,本文基于Python設計實現兩類數據批量賦值表格的工具,具體實現過程如下:
3.1 環(huán)境配置
本項目運用Python3.5,將其安裝目錄加入環(huán)境變量,方便在任何目錄下均可執(zhí)行。右鍵點擊“計算機”,選擇“屬性”,再點擊“高級系統設置”,雙擊“系統變量”窗口下面的“Path”,添加python安裝路徑即可,設置成功以后,在cmd命令行輸入命令“python”,就可以有相關顯示。
3.2 核心代碼
運用VSCode編輯器編輯代碼,保存為cun.py,確保其與Word模板、Excel表、整體位置、局部放大和三維視圖均在同一文件路徑下。
3.2.1導入模塊
用Python 腳本操作Word ,需要用到第三方庫docx,它提供了對Word操作的良好封裝。Word對象模型中提供了數百個可以交互的對象,它們是按照層次順序排列的,包含創(chuàng)建Word對象、創(chuàng)建Document對象、使用對象操作Word文檔、保存并關閉Document對象等[6]。用Python腳本操作Excel,需要用到第三方庫openpyxl,幾乎可以實現所有的Excel操作,而且接口清晰。
#導入Word操作模塊
from docx import Document
from docx.shared import Pt
from docx.oxml.ns import qn
from docx. enum. text import WD_PARAGRAPH_ALIGNMENT
#導入copy模塊,深度復制Python對象
from copy import deepcopy
#導入Excel操作模塊
import openpyxl
from decimal import Decimal
import os
3.2.2 以文件創(chuàng)建文檔對象
#定義Word模板、Excel表、整體位置、局部放大、三維視圖和最終成果的路徑參數,并讀取Word模板和Excel表的值
def main():
wordpath = './滹沱河河流電子埋設點點之記模板.docx'
excelpath = './滹沱河村級埋設點.xlsx'
entirety = './整體位置/'
part = './局部放大/'
dimensional = './三維視圖/'
output = './滹沱河河流電子埋設點點之記.doc'
document = Document(wordpath)
wb=openpyxl.load_workbook(excelpath)
sheet=wb.worksheets[0]
#通過遍歷Excel表的行數,復制Word模板
for index,excelrow in enumerate(sheet.iter_rows()):if index == 0:
continue
if index == 1:
wordtable=document.tables[index-1]
p=document.paragraphs[0]
document.add_section()
continue
paragraph = document.add_paragraph()
paragraph._p.addnext(p._element)
new_table = deepcopy(wordtable)
paragraph._p.addnext(new_table._element)
document.add_section()
document.save('./tmp.docx')
document = Document('./tmp.docx')
3.2.3 設置字體格式
#定義setcell函數,方便設置模板表格中的字體樣式
def setcell(cell,iscenter,isbold,ptsize):
paragraphs=cell.paragraphs
if iscenter:
paragraphs[0].alignment=WD_PARAGRAPH_ALI?GNMENT.CENTER
for run in paragraphs[0] .runs:
font=run.font
font.size=Pt(ptsize)
if isbold:
run.bold=True
run.font.name=\"宋體\"
run._element.rPr.rFonts.set(qn('w:eastAsia'),'宋體')
3.2.4批量賦值
#該段代碼也包含在def main()函數中,旨在通過遍歷Excel 表的行列,將Excel 表格的值一一映射到Word表格中
for index,excelrow in enumerate(sheet.iter_rows()):
if index == 0:
continue
wordtable=document.tables[index-1]
#設置Word表格的標題為“滹沱河河流電子埋設點點之記”,并設置字體居中,加粗,宋體16
hdr_cell = wordtable.rows[0].cells[1]
hdr_cell.text = str('滹沱河河流電子埋設點點之記')
setcell(hdr_cell,True,True,16);
#設置Word表格中編號對應的值由Excel表中的BM列得到,并設置字體不居中,不加粗,宋體11
hdr_cell = wordtable.rows[2].cells[2]
hdr_cell.text = str(excelrow[1].value)
setcell(hdr_cell,False,False,11);
#設置Word表格中所屬河流名稱對應的值由Ex?cel表中的河流列得到,并設置字體不居中,不加粗,宋體11
hdr_cell = wordtable.rows[2].cells[4]
hdr_cell.text = str(excelrow[12].value)
setcell(hdr_cell,False,False,11);
#設置Word表格中所在地對應的值由Excel表中的SZD列得到,并設置字體不居中,不加粗,宋體11
hdr_cell = wordtable.rows[3].cells[2]
hdr_cell.text = str(excelrow[11].value)
setcell(hdr_cell,False,False,11);
#設置Word表格中B對應的值由Excel表中的緯度列得到,設置數字保留小數點后八位,并設置字體不居中,不加粗,宋體11
hdr_cell = wordtable.rows[4].cells[2]
hdr_cell.text=str(Decimal((excelrow[7].value)).quan?
tize(Decimal('0.00000000')))
setcell(hdr_cell,False,False,11);
#設置Word表格中L對應的值由Excel表中的經度列得到,設置數字保留小數點后八位,并設置字體不居中,不加粗,宋體11
hdr_cell = wordtable.rows[5].cells[2]
hdr_cell.text=str(Decimal((excelrow[6].value)).quan?
tize(Decimal('0.00000000')))
setcell(hdr_cell,False,False,11);
#設置Word 表格中H 對應的值由Excel 表中的POINT_Z列得到,設置數字保留小數點后三位,并設置字體不居中,不加粗,宋體11
hdr_cell = wordtable.rows[6].cells[2]
hdr_cell.text=str(Decimal((excelrow[4].value)).quan?tize(Decimal('0.000')))
setcell(hdr_cell,False,False,11);
#設置Word表格中點位三維模型示意截圖對應的圖片,根據Excel表中的BM列對應的值,由三維視圖文件夾下的指定圖片插入
hdr_cell = wordtable.rows[6].cells[4] hdr_cell.paragraphs[0].add_run().add_picture(dimensional+str(ex?celrow[1].value)+\".jpg\")
#設置Word表格中整體位置(影像截圖)對應的圖片,根據Excel表中的BM列對應的值,由整體位置文件夾下的指定圖片插入
hdr_cell = wordtable.rows[9].cells[1]
hdr_cell. paragraphs[0]. add_run(). add_picture(en?tirety+str(excelrow[1].value)+\".jpg\")
#設置Word表格中局部放大(影像截圖)對應的圖片,根據Excel表中的BM列對應的值,由局部放大文件夾下的指定圖片插入
hdr_cell = wordtable.rows[9].cells[3] hdr_cell.paragraphs[0]. add_run(). add_picture(part+str(excelrow[1].value)+\".jpg\")
document.save(output)
print('執(zhí)行完成')
os.remove(\"tmp.docx\")
通過運行代碼生成滹沱河河流電子埋設點點之記.docx,共303頁,按BM編號順序排列,賦值正確率100%,以圖2右側為例,圖名的××替換成滹沱河,B、L、H分別自動四舍五入保留了小數點后八位和后三位,并且字體都是統一格式。“點位三維模型示意圖”“整體位置(影像截圖)”和“局部放大(影像截圖)”對應位置都插入了圖片。
4. 小結
山西省主要河流土地資源調查項目需要開展山西省域范圍內汾河、桑干河、滹沱河、漳河、沁河、瀟河、御河、黃河山西段等主要河流的界樁埋設工作,每條河流均需按要求上交圖件報表,若僅靠人工操作不僅費時費力還易出錯,本文以舉例的形式介紹了python語言在河流界樁數據成果轉換中發(fā)揮的作用,按此方法可以運用到不同要求的表格,即使同一表格字體或者數據格式發(fā)生改變,只需簡單更改代碼參數即可實現統改,是一個有效提升項目作業(yè)效率的方法。本文通過Python直接編寫腳本進行處理獲得結果,降低了技術門檻,還可將代碼打包成exe直接分發(fā),即使脫離項目情景也能使用,說明Python語言形式靈活,非常適合輕量化編程,為后續(xù)項目開發(fā)處理提供了新的思路。