本篇博客记录如何使用ArcPy制图模块管理地图文档和图层文件,包括在地图文档文件中添加和移除地图图层和表,将图层插入到数据框中,在地图文档中移动图层,以及更新图层属性和符号系统。
ArcGIS制图模块提供了自动化的制图功能,包括管理地图文档和图层文件,以及这些文件中的数据。此外,还提供自动导出和打印地图、创建PDF地图册和将地图文档发布成ArcGIS Server地图服务等功能。
引用地图文档的途径有两种:
mxd=mapping.MapDocument("CURRENT")
只有在ArcGIS的python窗口或ArcToolBox的自定义脚本工具中运行脚本时,才可以使用CURRENT关键字。如果在IDLE或其它开发环境中运行脚本时使用CURRENT关键字,则无法访问当前加载在ArcGIS中的地图文档。
import arcpy.mapping as mapping
mxd = mapping.MapDocument(r"E:\test\Crime_Ch2.mxd")
print(mxd.title)
mxd.title = "Copy of Crime Project"
mxd.saveACopy("E:/test/crime_copy.mxd")
import arcpy.mapping as mapping
mxd = mapping.MapDocument(r"E:\test\crime_copy.mxd")
layers = mapping.ListLayers(mxd)
for lyr in layers:
print(lyr.name)
使用通配符和在ArcMap的内容列表中指定的数据框来限制返回的图层。
下述例子是获取地图文档中数据框名为Crime中的以Burg开头的图层名称。
import arcpy.mapping as mapping
mxd = mapping.MapDocument(r"E:\test\crime_copy.mxd")
for df in mapping.ListDataFrames(mxd):
if (df.name == 'Crime'):
layers = mapping.ListLayers(mxd,"Burg*",df)
for layer in layers:
print(layer.name)
如果没有选择要素,调用zoomToSelectedFeatures()方法会缩放至数据库中所有要素的范围。
import arcpy.mapping as mapping
mxd=mapping.MapDocument("current")
mxd.activeDataFrame.zoomToSelectedFeatures()
import arcpy.mapping as mapping
mxd=mapping.MapDocument("current")
df=mapping.ListDataFrames(mxd,"Crime")[0]
layer=mapping.ListLayers(mxd,"Burglaries*",df)[0]
df.extent=layer.getSelectedExtent()
或者将缩放后的效果重新保存一个地图文档
import arcpy.mapping as mapping
mxd=mapping.MapDocument(r"E:\test\crime_copy.mxd")
df=mapping.ListDataFrames(mxd,"Crime")[0]
layer=mapping.ListLayers(mxd,"Burglaries*",df)[0]
df.extent=layer.getSelectedExtent()
mxd.saveACopy("E:/test/crime_copy11.mxd")
使用图层的定义查询属性来更新地图范围。
下述例子是查找图层名为Crime Density by School District中要素记录名为Lackland ISD的学校区域。
import arcpy.mapping as mapping
mxd = mapping.MapDocument("CURRENT")
for df in mapping.ListDataFrames(mxd):
if (df.name == 'Crime'):
layers = mapping.ListLayers(mxd,'Crime Density by School District',df)
for layer in layers:
query = '"NAME" = \'Lackland ISD\''
layer.definitionQuery = query
df.extent = layer.getExtent()
arcpy.mapping模块提供了在已有的地图文档中添加图层或图层组的功能。
使用AddLayer()函数将图层添加到地图文档中,当把图层添加到地图文档中,该图层必须引用一个已有的图层,即能够在磁盘上的图层文件、同一个地图文档和数据框、同一个地图文档但不相同的数据框或完全不同的地图文档中找到的图层。
import arcpy.mapping as mapping
mxd = mapping.MapDocument("CURRENT")
df = mapping.ListDataFrames(mxd)[0]
layer = mapping.Layer(r"C:\ArcpyBook\data\School_Districts.lyr")
mapping.AddLayer(df,layer,"AUTO_ARRANGE")
上述例子中“AUTO_ARRANGE”(默认值)自动地放置图层在数据框中的位置,也可以使用BOTTOM或TOP,指定图层放置在数据框或图层组的底层或顶层。
arcpy.mapping模块提供的AddLayerToGroup()函数可以把图层添加到图层组中。
图层也可以从数据框或图层组中移除。RemoveLayer()函数用来移除指定数据框中的图层或图层组。如果有两个图层的名字相同,只移除检索到的第1个图层
AddLayer()函数仅仅提供把图层添加到数据框或图层组中的功能,并且只可以使用自动排序地放置图层的位置,或者选择放置在顶层或底层。使用InsertLayer()函数可以准确地指定图层添加到数据框或图层组中的位置。InsertLayer()函数使用一个参考图层来指定位置,新图层将会添加在指定参考图层的上方或下方。
因为InsertLayer()函数需要使用参考图层,所以不能对空数据框使用该函数。
import arcpy.mapping as mapping
mxd = mapping.MapDocument("CURRENT")
df = mapping.ListDataFrames(mxd, "Crime")[0]
refLayer = mapping.ListLayers(mxd, "Burglaries*", df)[0]
insertLayer = mapping.Layer(r"C:\ArcpyBook\data\CityOfSanAntonio.gdb\Crimes2009")
mapping.InsertLayer(df,refLayer,insertLayer,"BEFORE")
上例中Burglaries*图层是参考图层,通过“BEFORE”参数将要插入的图层添加到Burglaries*图层的上方。
图层在数据框或图层组中的位置是可以改变的。MoveLayer()函数提供了在数据框或图层组中移动图层位置的功能,但是图层的移动只能在同一个数据框内,而不能把一个数据框中的图层移动到另一个数据框中。同InsertLayer()函数一样,MoveLayer()函数需要引用参考图层来改变图层的位置。
或者在第三方Python编辑器中使用下述代码插入图层到mxd,其中需要调用save()方法来保存对mxd更改的结果。
import arcpy.mapping as mapping
mxd = mapping.MapDocument(r"C:\Users\admin\Desktop\test.mxd")
df = mapping.ListDataFrames(mxd, "Layers")[0]
refLayer = mapping.ListLayers(mxd, "area", df)[0]
insertLayer = mapping.Layer(r"E:\test.gdb\sanpoly")
mapping.InsertLayer(df,refLayer,insertLayer,"BEFORE")
mxd.save()
del mxd
UpdateLayer()函数可以更改地图文档中图层的符号系统,也可以改变图层的各种属性。
使用UpdateLayer()函数更新符号系统
import arcpy.mapping as mapping
mxd = mapping.MapDocument("CURRENT")
df = mapping.ListDataFrames(mxd, "Crime")[0]
updateLayer = mapping.ListLayers(mxd,"Crime Density by School District",df)[0]
sourceLayer = mapping.Layer(r"C:\ArcpyBook\data\CrimeDensityGradSym.lyr")
mapping.UpdateLayer(df,updateLayer,sourceLayer,True)
UpdateLayer()函数,传入数据框(df)、更新图层(updateLayer)、源图层(sourceLayer)和用来表明仅更新符号系统的参数(True)。第四个参数True值,表明仅更新图层的符号系统,而不更新属性。
要更新图层的符号系统,首先必须确保更新图层和源图层具有相同的几何图层(点、线、面)。根据渲染器的要求,还需要检查属性定义是否相同。例如:分级色彩和分级符号都基于一个特定的属性。
UpdateLayer()函数也提供移除一个图层并把另一个图层添加到该位置的功能,这两个图层可以完全不相关,因此不需要像定义图层符号系统一样,确保两个图层的几何类型和属性字段是相同的。这个功能本质上与先调用RemoveLayer()函数再调用AddLayer()函数执行的操作是一样的。设置symbology_only参数的值为False,可以实现该功能。
UpdateLayer()可以用来更新图层的各种属性,如字段别名、定义查询、标注字段等。
一种常见的情况是,有一个图层被添加到多个地图文档中,而GIS分析人员需要在全部地图文档中改变所有该图层实例的某个特定的图层属性。要实现这一功能,需要在ArcMap中修改特定图层属性并将该图层保存为图层文件,然后把保存的图层文件作为源图层,用来更新update_layer图层的属性。
import arcpy.mapping as mapping
mxd = mapping.MapDocument("CURRENT")
df = mapping.ListDataFrames(mxd, "Crime")[0]
updateLayer = mapping.ListLayers(mxd,"Crimes2009",df)[0]
sourceLayer = mapping.Layer(r"C:\ArcpyBook\data\BurglariesNoForcedEntry.lyr")
mapping.UpdateLayer(df,updateLayer,sourceLayer,False)
如何启用图层的时间属性,然后编写脚本,循环遍历图层的时间范围并导出PDF地图,用来展示以7天为间隔的犯罪数据。
import arcpy.mapping as mapping, os
mxd = mapping.MapDocument("CURRENT")
df = mapping.ListDataFrames(mxd, "Crime")[0]
dft = df.time
dft.currentTime = dft.startTime
while dft.currentTime <= dft.endTime:
fileName = str(dft.currentTime).split(" ")[0] + ".pdf"
mapping.ExportToPDF(mxd,os.path.join(r"C:\ArcpyBook\Ch2", fileName))
print("Exported " + fileName)
dft.currentTime = dft.currentTime + dft.timeStepInterval