標準圖廓自動生成與批量出圖)
簡介針對ArcGIS地圖打印中圖廓圖框整飾繁瑣、重復勞動多的問題這份資源提供了一款綠色免安裝的輔助工具。它支持按標準圖幅號新/舊圖幅號涵蓋1∶100萬至1∶5000等多種比例尺批量生成嚴格平行的梯形圖廓也可基于行政區(qū)劃文件生成矩形圖廓并自動繪制公里網(wǎng)、十字絲、經(jīng)緯網(wǎng)完成四角經(jīng)緯度標注和四周文字標注以及接合表內(nèi)容的自動填寫標題、比例尺、單位、密級等文字內(nèi)容與字體、顏色、對齊方式均可靈活定制真正實現(xiàn)智能化標注。資源包共155個文件大小僅1.03MB主要包含AtkTool.exe主程序、CHM幫助文檔、示例分幅圖與行政區(qū)劃Shapefile文件、mdb地理數(shù)據(jù)庫及其索引文件等目錄結(jié)構(gòu)清晰下載解壓即可使用。目前已有1686人學習下載適合ArcGIS制圖人員、測繪與規(guī)劃相關(guān)從業(yè)者用于批量出圖、標準分幅圖廓生成等場景可顯著減少重復排版工作量讓地圖打印的圖廓修飾變得規(guī)范高效。1. 為什么ArcGIS默認的打印功能滿足不了制圖交付做GIS的人基本都經(jīng)歷過這個場景圖做完了點擊打印出來的圖總覺得不夠正式。不是比例尺放得不夠大而是圖面外框缺了點東西——沒有圖廓線、沒有完整的接圖表、沒有規(guī)范的分幅信息圖面看起來就像一張半成品拿去給甲方或者評審專家看第一關(guān)就過不了。這里需要先厘清一個概念。制圖領(lǐng)域說的圖廓不是簡單地畫一個矩形框住地圖而是指地圖的邊界框架系統(tǒng)包含內(nèi)圖廓線、外圖廓線、經(jīng)緯網(wǎng)或方里網(wǎng)刻度、圖幅編號、接圖表、比例尺、圖例等整飾要素的統(tǒng)稱。在測繪出圖、國土規(guī)劃、地質(zhì)調(diào)查這些行業(yè)里圖廓是一張合格成果圖的基本配置。ArcGIS雖然自帶Layout視圖底圖、指北針、比例尺、圖例這些整飾元素都能放但打印圖廓這個動作卻一直做得不夠順手。默認的格網(wǎng)工具能生成經(jīng)緯網(wǎng)但控制不了線寬、字頭朝向、內(nèi)外圖廓間距數(shù)據(jù)驅(qū)動頁面Data Driven Pages能批量出圖但圖廓要素的自動生成和更新卻要手動處理。更麻煩的是很多項目要求的是特定行業(yè)標準的圖廓樣式比如地質(zhì)圖規(guī)范、土地利用現(xiàn)狀圖規(guī)范這類帶參數(shù)化圖廓的需求在ArcGIS原生界面里幾乎只能靠人工一點點畫。我當年第一次接到一個批量出圖的活兒要求輸出300多幅標準分幅圖每幅都要帶規(guī)范圖廓。如果純手工做一個人一周都未必能完成。后來我干脆用ArcPy寫了一套圖廓生成工具把整個出圖流程從半手工變成了全自動這一步省下來的時間足夠我重新做三個項目。這篇文章就把這套工具的完整實現(xiàn)思路、核心代碼邏輯和實際踩過的坑都寫出來。不追求代碼有多花哨重點是讓每個用ArcGIS做制圖輸出的同行都能照著思路做出自己的圖廓工具。2. 圖廓工具的需求拆解先搞清楚要畫的是什么動手寫代碼之前先得把圖廓到底包含哪些要素拆清楚。很多人覺得圖廓就是一條線但實際上一個可交付的標準圖廓至少包含以下組件內(nèi)圖廓界定地圖內(nèi)容范圍的四條邊線通常用細線或中等線寬表示。外圖廓內(nèi)圖廓外圍的裝飾邊框線寬明顯粗于內(nèi)圖廓形成視覺上的框架感。經(jīng)緯網(wǎng)刻度線沿內(nèi)圖廓向外延伸的短線用于標示經(jīng)緯度位置配合度數(shù)注記。分度注記經(jīng)緯度或方里網(wǎng)坐標數(shù)值沿圖廓邊緣排布。圖幅編號和接圖表標準分幅圖的左上角通常帶圖幅編號右上角或左下角帶接圖表九宮格或更復雜的圖幅接合關(guān)系表。比例尺、圖例、指北針、圖名這些屬于圖面整飾雖然不直接算圖廓但在正式出圖中通常與圖廓一體化布局。搞清楚要素還要搞清楚坐標系和投影的影響。很多新手在這里翻車內(nèi)圖廓在ArcGIS里如果直接用格網(wǎng)工具生成經(jīng)緯網(wǎng)是按經(jīng)緯度計算的如果地圖用的是投影坐標系方里網(wǎng)是按投影坐標計算的。兩種格網(wǎng)的長相完全不同混用或者參數(shù)設(shè)置錯誤輸出的圖廓就是錯的。我的工具設(shè)計核心思路是內(nèi)圖廓和經(jīng)緯網(wǎng)不依賴ArcGIS的Grid工具而是用ArcPy按給定范圍的坐標值直接構(gòu)建線要素。這樣做的好處是完全掌控要素的幾何形態(tài)、線寬、顏色、注記位置不再受制于ArcGIS默認樣式的各種限制。工具的工作流程分三層輸入層讀入地圖文檔MXD或APRX、目標比例尺、出圖范圍、圖廓樣式參數(shù)。處理層用ArcPy計算內(nèi)圖廓坐標構(gòu)建外圖廓線、經(jīng)緯網(wǎng)刻線和注記要素寫入臨時要素類。輸出層將要素類加載到布局視圖同步設(shè)置布局尺寸、出圖參數(shù)執(zhí)行打印或?qū)С觥_@三層對應(yīng)了三個模塊下面逐個展開。3. 核心實現(xiàn)思路坐標計算與要素構(gòu)建3.1 內(nèi)圖廓坐標的計算邏輯圖廓工具的基礎(chǔ)是內(nèi)圖廓的四角坐標。批量出圖時每個圖幅的范圍通常由標準分幅規(guī)則決定比如1:10000標準分幅是經(jīng)差3分45秒、緯差2分30秒或者由用戶指定的矢量面要素邊界決定。我的做法是先用ArcPy讀取分幅面的Extent對象拿到XYMin、XYMax四個值然后根據(jù)指定的出圖比例尺計算實際圖幅尺寸。這一步是工具成敗的關(guān)鍵因為比例尺和紙張尺寸必須匹配——同樣是1:10000如果選A4紙和選A3紙能容納的實地范圍完全不同。計算公式很簡單實地寬度 紙張寬度 × 比例尺分母 實地高度 紙張高度 × 比例尺分母比如A4紙縱向去掉邊距后打印區(qū)域大約是180mm × 270mm比例尺1:10000時對應(yīng)的實地范圍就是1800米 × 2700米。如果分幅面的實際范圍大于這個值就得調(diào)整比例尺或分幅方式否則圖就要被裁切。我的工具里把這一段做成了一個交互步驟輸入分幅范圍后自動計算匹配當前紙張的最佳比例尺彈出一組推薦值用戶可以手動覆蓋。實測中這個邏輯能省掉大量反復試打印的時間。3.2 外圖廓與內(nèi)外圖廓間距內(nèi)外圖廓的關(guān)系在制圖規(guī)范里有明確要求雖然不同行業(yè)標準的具體數(shù)值不同但基本原理一致外圖廓線位于內(nèi)圖廓外側(cè)一定距離處這個距離開辟出專門放置經(jīng)緯度注記的區(qū)域。我實現(xiàn)的默認參數(shù)是外圖廓線寬1.2mm內(nèi)圖廓線寬0.3mm內(nèi)外圖廓間距8mm刻度線長3mm。這些參數(shù)都做成用戶可配置的因為不同項目要求的地圖樣式確實差別很大。之前幫一個地質(zhì)調(diào)查項目做工具他們要求內(nèi)外圖廓間距必須精確到15mm刻度線采用長短線交替樣式這些都是硬性規(guī)范沒得商量。外圖廓的構(gòu)建不需要太復雜——內(nèi)圖廓四個角坐標分別向外偏移固定距離再生成一個矩形面要素線寬單獨設(shè)置即可。麻煩的是經(jīng)緯網(wǎng)刻度線和注記的排布。3.3 經(jīng)緯網(wǎng)刻度與注記的自動生成這是圖廓工具中最容易出問題的部分。ArcGIS自帶格網(wǎng)工具雖然能生成刻度線但放置位置、長度、樣式都很難精確控制到行業(yè)標準要求。我在工具里直接解析經(jīng)緯度范圍按指定間隔插值生成刻度線位置。核心邏輯是這樣的import arcpy import math def generate_tick_marks(extent, interval_deg, tick_length_mm, map_scale): 根據(jù)圖廓范圍生成經(jīng)緯度刻度線點位 extent: 內(nèi)圖廓范圍對象 interval_deg: 刻度間隔度 tick_length_mm: 刻度線長度毫米 map_scale: 比例尺分母 mm_to_map_units map_scale / 1000.0 # 1mm對應(yīng)的地圖單位假設(shè)單位為米 min_x, min_y extent.XMin, extent.YMin max_x, max_y extent.XMax, extent.YMax # 計算刻度線在圖上的實際長度地圖單位 tick_len tick_length_mm * mm_to_map_units lines [] # 沿X方向經(jīng)度生成刻度線 x min_x while x max_x: # 生成下邊線刻度向內(nèi)延伸為內(nèi)刻度向外為外刻度 lines.append(((x, min_y - tick_len), (x, min_y))) lines.append(((x, max_y), (x, max_y tick_len))) x interval_deg # 沿Y方向緯度生成刻度線 y min_y while y max_y: lines.append(((min_x - tick_len, y), (min_x, y))) lines.append(((max_x, y), (max_x tick_len, y))) y interval_deg return lines這段代碼有幾個容易忽略的細節(jié)實測過程中我踩過好幾次坑第一坐標單位和比例尺的換算。如果數(shù)據(jù)框坐標系是投影坐標系單位是米而經(jīng)緯網(wǎng)刻度需要按度來算就必須先把經(jīng)緯度網(wǎng)格轉(zhuǎn)換為投影坐標。我的做法是在數(shù)據(jù)框里額外掛一個地理坐標系轉(zhuǎn)換用arcpy的ProjectGeometry方法把每個經(jīng)緯度點位投影到當前坐標系再計算刻度線端點。第二刻度間隔的取整。自動生成的刻度線如果直接按范圍的六等分或八等分出來的數(shù)值往往很難看——比如37.365°這種注記很難讀。工具必須先把間隔取整到規(guī)范值如0.5°、1°、2°、5°再讓刻度線對齊到整數(shù)值上。第三圖廓四個角的刻度線要去重。四個角點同時屬于兩條邊線如果不做去重會出現(xiàn)重疊線。這個處理要在循環(huán)里加一個坐標容差判斷。3.4 注記的放置與圖幅信息要素刻度線生成之后還要在每條刻度線外側(cè)放置度數(shù)注記。注記的放置邏輯其實就是一個文字定位問題但ArcPy里沒有直接放置注記的接口需要創(chuàng)建注記要素類或者動態(tài)文本。我的方案是用ArcGIS的動態(tài)文本Dynamic Text結(jié)合XML格式的布局代碼來做。在標準的MXD布局里動態(tài)文本可以引用數(shù)據(jù)框的當前范圍坐標自動生成經(jīng)緯度值但默認樣式同樣不可控。后來我換了思路直接把刻度線注記作為獨立的地圖要素寫入Geodatabase然后加載為地圖圖層用標注Label方式渲染。這種方法的好處是注記與地圖數(shù)據(jù)在同一坐標系下不會因為數(shù)據(jù)框范圍變化而錯位。缺點是需要額外管理一個注記要素類出圖前必須確保標注引擎正確啟用。圖幅編號、接圖表、圖名這些要素我通常建議做成獨立的布局元素而不是放進地圖畫面。因為它們在打印時不需要隨地圖縮放直接在布局上定位更穩(wěn)定。工具提供一個配置界面讓用戶錄入圖幅號、圖名、日期等信息自動寫入布局的文本框。4. 批量出圖場景下的聯(lián)動設(shè)計4.1 從單幅圖到批量出圖的管線改造單幅圖工具寫好了批量出圖就是一個循環(huán)的問題——但實際改造時你會發(fā)現(xiàn)批量出圖遠比循環(huán)畫100次圖廓復雜得多因為每幅圖的圖廓參數(shù)、注記內(nèi)容、圖幅信息都要跟著分幅范圍變化。批量分幅的核心數(shù)據(jù)結(jié)構(gòu)是分幅索引表。我的做法是用一個矢量面文件或數(shù)據(jù)庫表存每一幅的圖幅號、起始經(jīng)緯度、范圍四至、比例尺然后ArcPy逐行讀取分別為每個分幅創(chuàng)建獨立的出圖環(huán)境def batch_map_series(frame_features, output_folder, template_mxd): 批量出圖主邏輯 frame_features: 分幅面要素圖層 output_folder: 輸出文件夾 template_mxd: 模板地圖文檔 arcpy.env.overwriteOutput True with arcpy.da.SearchCursor(frame_features, [SHAPE, 圖幅號, 比例尺]) as cursor: for row in cursor: geometry, sheet_code, scale row # 拷貝模板文檔避免修改原文件 temp_mxd arcpy.mapping.MapDocument(template_mxd) # 更新數(shù)據(jù)框范圍到當前分幅 df arcpy.mapping.ListDataFrames(temp_mxd)[0] df.extent geometry.extent # 更新圖幅信息 update_sheet_metadata(temp_mxd, sheet_code, scale) # 導出PDF out_pdf os.path.join(output_folder, f{sheet_code}.pdf) arcpy.mapping.ExportToPDF(temp_mxd, out_pdf) del temp_mxd這里有個性能問題值得說每次循環(huán)都要加載一個MXD模板數(shù)據(jù)量大時效率很低。我實測過300幅圖在普通辦公電腦上跑大概需要40分鐘瓶頸不是繪圖而是MXD的反復加載和釋放。優(yōu)化方案是先一次性把模板加載到內(nèi)存循環(huán)里只改數(shù)據(jù)框范圍和參數(shù)不重新打開文檔。這樣能把總時間壓縮到20分鐘以內(nèi)。4.2 圖廓要素類與地圖內(nèi)容的同步更新批量出圖中最折磨人的問題是圖廓線要素是動態(tài)的每幅圖的經(jīng)緯網(wǎng)間隔、刻度位置都不同而ArcGIS的格網(wǎng)工具又不能在腳本里動態(tài)重建。所以我的工具里專門設(shè)計了一個圖廓要素刷新模塊每次切到新的分幅范圍就刪除舊的圖廓要素重新生成新的內(nèi)圖廓、外圖廓和刻度線要素類。這個模塊必須處理一個事務(wù)性問題如果某一幅圖在生成圖廓時失敗了比如坐標系轉(zhuǎn)換報錯不能讓上一幅圖的圖廓殘留在地圖上給后面的出圖造成干擾。我采取的做法是先備份當前圖廓要素類生成失敗時自動回滾。圖層管理也踩過坑。ArcGIS的MXD里圖層順序很敏感圖廓要素必須放在所有數(shù)據(jù)圖層的最上層否則會被面狀要素壓蓋。而且注記圖層和數(shù)據(jù)圖層的渲染順序也有講究如果注記被數(shù)據(jù)壓住出圖結(jié)果就是缺字。我的工具里通過arcpy.mapping.ListLayers判斷圖層名稱前綴確保圖廓相關(guān)圖層始終排在Top。5. 實測中的典型故障排查坐標系、比例尺、樣式三座大山5.1 坐標系不一致導致圖廓錯位工具上線后我遇到最多的問題就是我的圖廓跑到地圖外面去了或者刻度線方向全錯了。排查到最后十有八九是坐標系問題的變種。典型案例分幅面的坐標系是CGCS2000投影坐標但圖廓工具內(nèi)部的經(jīng)緯度計算默認用的是WGS84地理坐標。兩者之間的轉(zhuǎn)換偏差在不同緯度區(qū)域差異很大雖然計算機會自動做投影但如果你直接用未轉(zhuǎn)換的經(jīng)緯度去計算刻度線偏移量到高緯度地區(qū)刻度線的位置誤差可以達到肉眼可見的程度。解決辦法是我把坐標轉(zhuǎn)換邏輯前置讀入分幅范圍后立刻統(tǒng)一到數(shù)據(jù)框的目標坐標系所有計算全在目標坐標系下完成。經(jīng)緯度注記值則在生成注記文本時從目標坐標系反算回地理坐標的一個專門字段來存。這里也給一個實用建議如果你要處理不同帶號的投影坐標系比如高斯克呂格3度帶和6度帶混用一定要在工具里加入帶號檢查邏輯。我之前就遇到過一個分幅面文件坐標值本身沒錯但因為帶號標注錯誤導致整個范圍偏移了幾百公里——這種Bug在圖上看著特別詭異像是圖層飛了其實只是帶號問題。5.2 比例尺與打印尺寸的匹配問題第二個高頻問題出在比例尺設(shè)置上。很多用戶直接在出圖界面拖拽地圖覺得能放下就行這種習慣帶到工具里就出問題——工具嚴格按照比例尺和紙張尺寸計算地圖范圍如果比例尺設(shè)得太大圖面內(nèi)容超出紙張工具會直接報錯而不是自動縮放。我的工具在收到比例尺參數(shù)后會先做一次預檢計算目標紙張的可打印面積除以比例尺得出能容納的實地范圍再和分幅面范圍比較。超出則提示用戶選擇縮小比例尺適配還是保持比例尺并裁切范圍。實測下來這兩種選擇對應(yīng)的業(yè)務(wù)場景完全不同——前者用于圖面必須容納完整分幅范圍的情況后者用于需要保持統(tǒng)一比例尺的圖幅拼接。還有一個細節(jié)打印分辨率。默認導出PDF的分辨率是300DPI但實際打印中大幅面打印機一般用150DPI就夠了分辨率過高反而導致輸出過程卡死。工具里我把DPI設(shè)置為可配置項并增加了快速預覽模式96DPI方便批量出圖前快速檢查圖廓是否正常。5.3 圖廓線樣式在導出時變細或消失第三個問題是渲染層面的圖廓線在ArcMap界面里顯示正常導出PDF或打印后卻幾乎看不見。這個問題的根源出在符號的線寬單位上。ArcMap圖層符號的線寬有三種單位磅Point、毫米Millimeter、地圖單位Map Unit。圖廓線通常用毫米或磅作為單位但如果誤用了地圖單位——在比例尺縮小的情況下比如1:50000時線寬0.1地圖單位米換算到圖上可能只有0.002毫米肉眼當然看不見。我寫了一個工具函數(shù)統(tǒng)一把圖廓線的線寬單位強制設(shè)置為毫米并在標準情況下為內(nèi)圖廓、外圖廓、刻度線定義了推薦線寬。這個函數(shù)現(xiàn)在是所有用戶必用的沒有例外。字體問題也歸到這一類。經(jīng)緯度注記的字號在界面上看著正常但導出PDF后中文或特殊符號變成亂碼或方框這通常是因為字體嵌入失敗。解決方法是設(shè)置ExportToPDF的EmbedAllFonts參數(shù)為True并把地圖文檔里的字體盡量統(tǒng)一為宋體或黑體這類系統(tǒng)字體。6. 把工具變成工作流設(shè)計參數(shù)面板與交付模板6.1 參數(shù)面板設(shè)計——讓非開發(fā)人員也能操作工具跑通之后下一個要解決的是怎么給同事用的問題。ArcGIS的Python工具箱Python Toolbox比腳本工具更合適因為它的參數(shù)面板能清晰展示多個輸入項還能做級聯(lián)驗證。我做的參數(shù)面板包含四組參數(shù)輸入數(shù)據(jù)分幅面要素、數(shù)據(jù)框名、比例尺。圖廓樣式內(nèi)外圖廓線寬、間距、刻度線長度、注記字體字號。輸出設(shè)置紙張尺寸、方向、DPI、輸出文件夾。輔助選項是否生成接圖表、是否自動添加圖名、橫縱圖廓線是否單獨設(shè)色。每一組參數(shù)在工具內(nèi)部都有默認值用戶只改需要變的部分。實測下來同事用了兩周之后反饋說比原來手畫快太多了這句話比任何代碼優(yōu)化都有成就感。6.2 輸出模板的規(guī)范化圖廓工具的輸出不僅僅是PDF通常還要配套成果圖的元數(shù)據(jù)——圖幅號、生產(chǎn)日期、坐標系、比例尺等這些信息要有統(tǒng)一的格式存檔。我的做法是輸出PDF的同時生成一個同名的XML元數(shù)據(jù)文件里面存儲完整的圖幅信息后續(xù)歸檔、查詢、追溯都非常方便。如果你用的是ArcGIS Pro工具的實現(xiàn)思路完全一樣只是arcpy.mapping換成了arcpy.mp接口名稱略有差異但邏輯模型不用改。我自己目前的主力環(huán)境已經(jīng)是Pro了API從MXD換到APRX之后工具的穩(wěn)定性反而更好——Pro對圖廓的支持比ArcMap強不少至少不會再出現(xiàn)自動更新圖廓時卡死的問題。6.3 從標準圖廓到特殊樣式擴展最后說說擴展。工具的目的一定不是只能畫一種樣式的圖廓。行業(yè)不同圖廓要求千差萬別地質(zhì)圖需要巖性花紋的圖例框礦產(chǎn)圖需要礦權(quán)范圍接圖表地籍圖要加宗地號注記。我在工具里預留了樣式配置文件JSON把所有圖廓參數(shù)抽離出來。不同的項目只需要加載對應(yīng)的樣式配置不需要改代碼。新增樣式時開發(fā)者只需要在配置文件里定義新的線寬、間距、注記前綴等參數(shù)就能生成對應(yīng)的圖廓樣式。這個設(shè)計讓工具的生命周期延長了很多從單純畫圖工具變成可復用的制圖框架。以我個人的經(jīng)驗做這類工具還有一個容易被低估的好處因為出圖邏輯被固化成了代碼任何參數(shù)的變化都能回溯、復現(xiàn)、對比。以前手工作業(yè)時上次的圖是怎么出的根本說不清楚現(xiàn)在每一步都有據(jù)可查。如果后續(xù)有人接手也能很快上手。用一句話概括我的體會圖廓工具的核心不在于畫幾條線而在于把制圖標準用代碼固化下來把人從重復勞動里解放出來。這套思路無論你用ArcMap還是ArcGIS Pro無論做測繪還是做規(guī)劃都值得試一試。本文還有配套的精品資源點擊獲取