关于制图,是一项非常庞大的部分,这里只简单的介绍如何读取文档,设置图例、标题以及出图。

arcpy.mapping

arcpy.mapping 是ArcPy中用于操作地图文档 (.mxd) 和图层文件 (.lyr) 的的模块,可以使用arcpy.mapping 很方便的创建专题地图册等。

读取mxd文档

arcpy.mapping读取地图文档,使用的是arcpy.mapping.MapDocument方法,其定义非常简单:

  1. MapDocument(mxd_path)

mxd_path就是mxd文档的路径。MapDocument打开一个地图文档后,将会返回一个MapDocument对象。

示例:

  1. mxd_file = arcpy.mapping.MapDocument(mxdFilePath)
  2. # do something
  3. del mxd_file

注1:有一点需要指出,arcpy中一些方法在官网上都没有看到返回值的说明,但是其会一个返回值。一般对于操作而言,返回值的就是这个操作的结果。
注2:使用完MapDocument后记得释放资源

获取地图文档中数据框

ArcGIS中允许定义多个数据框,数据框的获取,是通过arcpy.mapping.ListDataFrames方法来实现的。arcpy.mapping.ListDataFrames方法可以获取到指定地图文档中的所有数据框列表,其语法如下:

  1. ListDataFrames(map_document, {wildcard})

其参数的意义如下:
map_document: 用于查看数据框的MapDocument对象
wildcard: 数据库名通配符,与之前讲到的类似。

ListDataFrames返回的是所有的数据框的列表,可以通过索引来获取指定的数据框,如果要获取map_document中激活的数据框,则可以通过map_document.activeDataFrame来获取

获取数据框中的图层

获取图层是通过arcpy.mapping.ListLayers来实现的。ListLayers可以获取到当前地图文档的所有图层,要获取指定的数据框中的图层,需要将该数据框作为一个参数传递到方法里面。ListLayers的语法如下:

  1. ListLayers(map_document_or_layer, {wildcard}, {data_frame})

其参数定义如下:
map_document_or_layer:地图文档或则是lyr图层(注:凡是未指定为lyr图层的图层均为普通图层)
wildcard:图层名通配符
data_frame:数据框

例如,获取某个地图文档中的第一个数据框中第一个图层:

  1. import arcpy
  2. mxd = arcpy.mapping.MapDocument(r"xxx\xxx\x.mxd")
  3. df = arcpy.mapping.ListDataFrames(mxd)[0]
  4. print arcpy.mapping.ListLayers(mxd, "", df)[0].name
  5. del mxd

注:此段代码来自ArcGIS官网

制图

说实话,直接通过ArcPy来对地图进行符号化等设置是比较麻烦的,还好ArcGIS提供lyr图层文件。与普通的shapefile文件和要素类等相比,lyr图层文件可以将数据及符号化的结果都保存在一起(注意,lyr图层对数据的保存仅仅是保存的是数据的路径,其主要保存的内容为符号系统的设置)。因此我们可以先使用ArcGIS定义好符号系统,在通过ArcPy来进行操作,因此这里将不在讲讲解。

制图有三大不可缺少的东西:方向、比例尺、图例,合称为地图三要素

制作地图册时,如果直接通过ArcPy来创建三要素,对于要素的摆放位置是难以可视化调整的,我们可以通过预先摆放好三要素,然后在通过ArcPy动态的更新其内容显示的地图图层内容即可,尤其是方向、比例尺,我们基本可以不用改变,仅仅来控制图例以及地图标题即可。

对于三要素以及标题等这些,在ArcGIS中统称为布局要素。获取布局要素,使用的是arcpy.mapping.ListLayoutElements方法,其语法定义如下:

  1. ListLayoutElements (map_document, {element_type}, {wildcard})

其中参数的意义如下:

map_document:用于操作的MapDocument对象
element_type:筛选返回的布局元素列表的元素类型的字符串。其可选择如下:DATAFRAME_ELEMENTGRAPHIC_ELEMENTLEGEND_ELEMENTMAPSURROUND_ELEMENTPICTURE_ELEMENTTEXT_ELEMENT
wildcard:用于筛选返回结果的通配符

我们的图中往往有标题,但是我们并没在element_type发现标题布局元素,这因为标题也是属于文本元素TEXT_ELEMENT。假如我们地图中只有一个文本类型的元素——标题,那我们可以使用如下方法更改地图的标题:

  1. def adjust_the_title(mxd_file, titleText):
  2. # 获取布局元素标题
  3. titleEle = arcpy.mapping.ListLayoutElements(mxd_file, "TEXT_ELEMENT")[0]
  4. # 更改标题内容
  5. titleEle.text = titleText

再来看个动态修改图例的例子:

  1. def adjust_the_legend(mxd_file, data_frame, layer, colCount):
  2. # 获取布局元素图例
  3. legendEle = arcpy.mapping.ListLayoutElements(mxd_file, "LEGEND_ELEMENT")[0]
  4. # 向数据框中添加图层
  5. arcpy.mapping.AddLayer(data_frame, layer, "TOP")
  6. # 调整图例中列数
  7. if colCount > 1:
  8. legendEle.adjustColumnCount(colCount)

在ArcGIS中,如果向数据框中添加图层,图例中会自动显示该图层;如果从数据框移出图层,图例中会自动移除该图层。因此,我们不用管图例中图层的显示问题。因此,我们只需要在需要的时候对图例的列数进行调整即可。

导出地图

arcpy.mapping下有一系列的ExportTo*方法用于导出地图,例如:ExportToPDFExportToPngExportToJPEG等,分别用来将地图导出为pdf、png、和jpg文件。这些方法虽然参数比较多,但是其最简单的使用如下:

  1. # 导出为pdf
  2. arcpy.mapping.ExportToPDF(mxd_file_object, r"C:\xx\xxx\xxxx.pdf")
  3. # 导出为png
  4. arcpy.mapping.ExportToPNG(mxd, rr"C:\xx\xxx\xxxx.png")
  5. # 导出为jpg
  6. arcpy.mapping.ExportToJPEG(mxd, rr"C:\xx\xxx\xxxx.jpg")

各个方法的具体语法请见ArcGIS的官网
https://desktop.arcgis.com/zh-cn/arcmap/10.3/analyze/arcpy-mapping/exportXXX.htm

批量制图

在制作系列专题地图时,我们可能会要求图例、比例尺不变,仅仅是数据的数据源发生变化,比如对某一地区的各类POI数据进行制图,并使得各类POI各出图一张。在ArcPy中操作符号系统是一件比较困难的事情,这时我们可以使用arcpy.mapping.UpdateLayer函数,其语法如下:

  1. UpdateLayer (data_frame, update_layer, source_layer, {symbology_only})

其参数定义如下:
data_frame:一个数据框DataFrame对象
update_layer:要被进行的图层
source_layer:用于更新 update_layer 图层的图层
symbology_only:是否只更新 update_layer 图层的符号系统,默认是True

例如,用已经做号符号系统的lyr图层文件去动态生成多个地图并导出,其示例代码如下:

  1. source_layer = arcpy.mapping.Layer("base.lyr")
  2. ···
  3. # shp_list 为一系列shapefile文件路径
  4. for shp_file in shp_list:
  5. # 创建一个图层,并将其加入到数据框中
  6. add_layer = arcpy.mapping.Layer(shp_file)
  7. add_layer.visible = True
  8. arcpy.mapping.AddLayer(data_frames, add_layer)
  9. # 更新图层的符号系统
  10. update_layer = arcpy.mapping.ListLayers(map_document, "*", data_frames)[0]
  11. arcpy.mapping.UpdateLayer(data_frames, update_layer, source_layer, True)
  12. # 获取shapefile的文件名(不带扩展名)
  13. file_name = get_file_name(shp_file)
  14. # 导出为png
  15. out_file = arcpy.env.workspace + "/png/" + get_parent_dir(shp_file) + '/' + file_name + ".png"
  16. dir_path = os.path.dirname(out_file)
  17. if not os.path.exists(dir_path):
  18. os.makedirs(dir_path)
  19. arcpy.mapping.ExportToPNG(map_document, out_file)
  20. # 将刚刚加入到数据框中的图层移除
  21. # 注意,不能直接移除add_layer,因为添加到数据框后 add_layer 与 data_frames)[0] 是两个对象
  22. arcpy.mapping.RemoveLayer(data_frames, arcpy.mapping.ListLayers(map_document, "*", data_frames)[0])

该示例的完整代码与数据可见示例代码下 5/batchMapping 文件夹。

制作地图册

创建一个pdf的地图册可以使用PDFDocumentCreate方法,将多个pdf地图文件合并为一个地图册:

  1. pdf_atlas = arcpy.mapping.PDFDocumentCreate(r"C:\xx\xxx.pdf")
  2. pdf_atlas.appendPages(r"C:\xx\a.pdf")
  3. pdf_atlas.appendPages(r"C:\xx\b.pdf")
  4. pdf_atlas.saveAndClose()
  5. del pdf_atlas

注:使用完PDFDocumentCreate后记得释放资源

将数据驱动页面和PDFDocumentCreate结合,可以很方便的创建一系列专题地图册。

该示例的完整代码与数据可见示例代码下 5/atlas 文件夹。