ArcPy自動繪製大量地圖並設定地圖要素:Python

疯狂学习GIS發表於2024-04-22

  本文介紹基於Python語言中ArcPy模組,實現ArcMap自動批次出圖,並對地圖要素進行自定義批次設定的方法。

1 任務需求

  首先,我們來明確一下本文所需實現的需求。

  現有透過Python基於Excel資料加以反距離加權空間插值並掩膜圖層所繪製的北京市在2019年05月18日00時至23時(其中不含19時)等23個逐小時PM2.5濃度插值資料柵格圖層,每小時一個圖層,因此共23個圖層;以當日10時為例,該時刻的柵格圖層如下所示。

image

  我們希望做到的有兩點。首先,我們可以看到前述23個柵格圖層的符號系統都為灰度拉伸的狀態,因此希望按照一個給定的模板圖層檔案m.lyr,調整這23個柵格圖層的樣式(即拉伸的顏色),並分別以.lyr格式匯出這23個柵格圖層檔案;且希望匯出圖層檔案的檔名包含具體的時刻。如下圖所示。

  第二點希望做到的是,將每一個柵格圖層都設定為彩色後,新增圖名、指北針、比例尺等地圖要素,並匯出為圖片格式。以當日10時、20時為例,我們所希望匯出的圖片如下所示。

  且希望匯出圖片的檔名同樣包含具體的時刻。

2 程式碼實現

  瞭解了需求後,我們就基於Python中的ArcPy模組,進行詳細程式碼的撰寫與介紹。

  這裡需要說明的是:在編寫程式碼的時候,為了方便執行,所以希望程式碼後期可以在ArcMap中直接透過工具箱執行,即用到Python程式指令碼新建工具箱與自定義工具的方法;因此,程式碼中對於一些需要初始定義的變數,都用到了arcpy.GetParameterAsText()函式。大家如果只是希望在IDLE中執行程式碼,那麼直接對這些變數進行具體賦值即可。關於Python程式指令碼新建工具箱與自定義工具,大家可以檢視ArcMap將Python寫的程式碼轉為工具箱與自定義工具詳細瞭解。

  上面提到需要初始定義的變數一共有七個,其中arcpy.env.workspace參數列示當前工作空間;mxd_file參數列示後期批次出圖時,提供地圖要素參考資訊的地圖文件.mxd檔案;lyr_file參數列示後期批次出圖時,提供地圖著色參考資訊的模板圖層.lyr檔案;mask_path參數列示前述插值柵格圖層所儲存的路徑;new_lyr_path參數列示插值柵格圖層經過樣式修改,並轉為圖層檔案後的儲存路徑;png_path參數列示最終出圖結果的儲存路徑;dpi參數列示最終出圖結果的影像解析度,單位為DPI(Dots per Inch)。

  其中,上述第二個引數,即提供地圖要素參考資訊的地圖文件.mxd檔案需要由使用者自行建立,並在其中配置好圖名、圖例、指北針、比例尺等地圖要素的名稱、文字、位置、樣式等資訊。或許這麼說有點不清楚,大家看下面這幅圖就能比較容易明白了。

  沒錯,這個提供地圖要素參考資訊的地圖文件.mxd檔案其實就是一個在Layout View中設定好各種地圖要素位置、大小、字型、顏色等的地圖文件檔案;它就相當於是一個模板,這個模板裡各種地圖要素長什麼樣子,後期我們批次出圖結果圖的地圖要素就長什麼樣子。

  此外,不知道為什麼,在我的ArcMap中似乎偶爾會出現無法有效執行lyr.visible=Falsearcpy.mapping.RemoveLayer(data_frame,new_lyr[0])等程式碼情況;因此若直接在上述地圖文件檔案中配置圖例,最終出圖結果有時會出現多個圖例堆疊,不能保證出圖結果百分之百完美。基於此,選擇將圖例格式元素(elm.name==”title”)轉換為由一個圖片格式元素(elm.name==”pic”)與兩個文字格式元素(elm.name==”text”)組成的新元素,從而實現最終結果圖中圖例的繪製。

  如果大家還是不明白,可以直接下載我的這一.mxd檔案;下載連結:https://pan.baidu.com/s/18l0l-kjPfdjV1UYcpkKg-w?pwd=fkxx

  具體程式碼如下。

# -*- coding: utf-8 -*-
# @author: ChuTianjia

import arcpy

arcpy.env.workspace=arcpy.GetParameterAsText(0)
mxd_file=arcpy.GetParameterAsText(1)
lyr_file=arcpy.GetParameterAsText(2)
mask_path=arcpy.GetParameterAsText(3)
new_lyr_path=arcpy.GetParameterAsText(4)
png_path=arcpy.GetParameterAsText(5)
dpi=arcpy.GetParameterAsText(6)

my_mxd=arcpy.mapping.MapDocument(mxd_file)
data_frame=arcpy.mapping.ListDataFrames(my_mxd)[0]
my_lyr=arcpy.mapping.Layer(lyr_file)
layer_list=arcpy.mapping.ListLayers(my_mxd)

my_mxd.activeView="PAGE_LAYOUT"

tif_file_list=arcpy.ListRasters("BJ_hour_*","TIF")
for raster in tif_file_list:
    # Import the mask layer into ArcMap
    raster_file=mask_path+"\\"+raster
    arcpy.MakeRasterLayer_management(raster_file,raster.strip(".tif"))

    # Modify the style of the mask layer according to the reference layer
    arcpy.ApplySymbologyFromLayer_management(raster.strip(".tif"),lyr_file)
    new_lyr_file=new_lyr_path+"\\"+raster.strip(".tif")+".lyr"

    # Save and import the mask layer after modifying the style
    arcpy.SaveToLayerFile_management(raster.strip(".tif"),new_lyr_file)
    arcpy.AddMessage("{0} has been saved.".format(raster.strip(".tif")+".lyr"))
    
    new_lyr=arcpy.mapping.Layer(new_lyr_file)
    arcpy.mapping.AddLayer(data_frame,new_lyr,"TOP")

    # Modify the image name
    for element in arcpy.mapping.ListLayoutElements(my_mxd,"TEXT_ELEMENT"):
        if element.name=="title":
            element.text="Interpolation Map of PM2.5 Concentration\n at {0}:00 on May 18, 2019, Beijing".format(raster[8:10])

    new_lyr.visible=True

    # Modify the legend (see the program usage document for details)
    max_pixel=arcpy.GetRasterProperties_management(new_lyr,"MAXIMUM").getOutput(0)[0:5]
    min_pixel=arcpy.GetRasterProperties_management(new_lyr,"MINIMUM").getOutput(0)[0:5]
    for element in arcpy.mapping.ListLayoutElements(my_mxd,"TEXT_ELEMENT"):
        if element.name=="MAX":
            element.text="{:0>5.2f}".format(float(max_pixel))
        if element.name=="MIN":
            element.text="{:0>5.2f}".format(float(min_pixel))

    # Export to picture format
    png_file=png_path+"\\"+raster.strip(".tif")+".png"
    arcpy.mapping.ExportToPNG(my_mxd,png_file,resolution=dpi)
    arcpy.AddMessage("{0} has been saved.".format(raster.strip(".tif")+".png"))
    
    new_lyr.visible=False
    arcpy.mapping.RemoveLayer(data_frame,new_lyr[0])

3 執行結果

  執行上述程式碼,具體得到的結果其實在本文開頭也就和大家講了,這裡就不再贅述。

  不過還有一點,就是如果大家是在ArcMap中直接透過工具箱執行上述程式碼,則可以看到程式碼執行過程中出現的提示——程式執行過程中,對每一個時刻的PM2.5濃度資料分別完成圖層格式儲存與圖片格式儲存等2個操作後,均會輸出執行結果,方便使用者獲知程式的執行情況。

  至此,大功告成。

相關文章