news 2026/2/12 3:52:33

【教你用ArcPy批量输出图片并生成Mxd(零门槛小白版)】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【教你用ArcPy批量输出图片并生成Mxd(零门槛小白版)】

如何快速批量出图是GISer需要解决的问题,要实现逐栅格图层或矢量图斑的出图则是师妹最近期末作业遇到的难题。还好,Gemini回归,通过不断调试解决这个需求。希望能转发给更多的伙伴!

难点1

通过现有的Mxd工作空间能够实现逐栅格图层或矢量图斑的输出,但是不能保证每个栅格图层或矢量图斑出现在整个输出图幅的正中间。

已解决!!!(居中,且比例尺为动态)

难点2

如何将对应矢量数据与栅格数据同时输出,比如,在市域尺度上的栅格数据,叠加市域尺度的矢量数据作为边界。

已解决!!!(需要在图层中添加Shp,即矢量格式,空白填充,红色,1磅大小,里面包含要输出tif的name字段,如输出石家庄_Lucc.tif,矢量图层中name字段必须也有这个“石家庄” )

难点3

如何如何动态调整经纬度范围,且图名随文件进行变化。

已解决!!!经纬度范围也能够动态进行调整(唯一遗憾是不能自动调整经纬网的疏密)

现有状况,ArcGIS大多数数据驱动页面工具来实现批量出图,出图效果很难满足需要

出图模版

代码如下

(可直接在ArcGIS,Python中运行)

# -*- coding: utf-8 -*-import arcpyimport osimport sys# 强制环境编码reload(sys)sys.setdefaultencoding('utf-8')# --- 1. 参数配置 ---input_folder = r"D:\try\try"mxd_template_path = r"D:\try\try.mxd"output_root = r"D:\try\results"# 图层名称(务必与 MXD 中的 TOC 列表名完全一致)raster_lyr_name = u"石家庄_Lucc2000_reclass.tif"vector_lyr_name = u"京津冀_市级"match_field = "name"# 样式设置FONT_SIZE = 20LEFT_SHIFT = 2.12 # 20磅字偏左3个字的距离Y_OFFSET_FROM_TOP = 1.5 # 距离顶部的间距dpi = 300# --- 2. 文件夹初始化 ---output_jpg_folder = os.path.join(output_root, "JPG_Files")output_mxd_folder = os.path.join(output_root, "MXD_Files")for folder in [output_jpg_folder, output_mxd_folder]:if not os.path.exists(folder):os.makedirs(folder)def batch_process():try:# 获取所有 TIF 文件列表arcpy.env.workspace = input_folder# 同时匹配大写和小写后缀rasters = arcpy.ListRasters("*", "TIF") + arcpy.ListRasters("*", "tif")rasters = list(set(rasters)) # 去重total_count = len(rasters)# --- 调试信息:看看究竟抓到了几个文件 ---print "--------------------------------------------------"print u"正在扫描文件夹: {}".format(input_folder)print u"找到 TIF 文件数量: {}".format(total_count)if total_count > 0:for r in rasters: print " -> " + rprint "--------------------------------------------------"if total_count == 0:print u"错误:文件夹里没找到 TIF 文件,请检查路径或后缀名!"return# --- 开始循环处理 ---for index, raster_name in enumerate(rasters):# 重要:每次循环都重新打开一次模板,保证图层对象是新鲜的mxd = arcpy.mapping.MapDocument(mxd_template_path)df = arcpy.mapping.ListDataFrames(mxd)[0]# 1. 解析文件名if "_" in raster_name:city_key = raster_name.split("_")[0]else:city_key = os.path.splitext(raster_name)[0]raster_base_name = os.path.splitext(raster_name)[0]# 2. 获取图层对象# 放在循环内获取,防止对象失效raster_layer = arcpy.mapping.ListLayers(mxd, raster_lyr_name, df)[0]vector_layer = arcpy.mapping.ListLayers(mxd, vector_lyr_name, df)[0]# 3. 切换数据源raster_layer.replaceDataSource(input_folder, "RASTER_WORKSPACE", raster_base_name, True)# 4. 矢量匹配与缩放query = "{} = '{}'".format(match_field, city_key)vector_layer.definitionQuery = queryarcpy.SelectLayerByAttribute_management(vector_layer, "NEW_SELECTION", query)if int(arcpy.GetCount_management(vector_layer).getOutput(0)) > 0:df.extent = vector_layer.getSelectedExtent()df.scale = df.scale * 1.15else:df.extent = raster_layer.getExtent()arcpy.SelectLayerByAttribute_management(vector_layer, "CLEAR_SELECTION")# 5. 更新标题并精确定位 (保护底部文字)all_texts = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT")# 再次寻找最高文本作为标题target_elm = all_texts[0]max_y = target_elm.elementPositionYfor elm in all_texts:if elm.elementPositionY > max_y:max_y = elm.elementPositionYtarget_elm = elm# 计算坐标df_center_x = df.elementPositionX + (df.elementWidth / 2.0)final_title_x = df_center_x - LEFT_SHIFTdf_top_y = df.elementPositionY + df.elementHeightfinal_title_y = df_top_y - Y_OFFSET_FROM_TOPtarget_elm.text = city_key + u"土地利用分布图"target_elm.fontSize = FONT_SIZEtarget_elm.elementPositionX = final_title_xtarget_elm.elementPositionY = final_title_y# 6. 执行导出arcpy.RefreshActiveView()out_jpg = os.path.join(output_jpg_folder, raster_base_name + ".jpg")arcpy.mapping.ExportToJPEG(mxd, out_jpg, resolution=dpi)out_mxd = os.path.join(output_mxd_folder, raster_base_name + ".mxd")mxd.saveACopy(out_mxd)print u"[{}/{}] 成功生成: {}".format(index + 1, total_count, raster_base_name)# 释放当前 MXD 对象,为下一个循环腾出内存del mxdprint "=================================================="print u"全部完成!JPG 存放在: " + output_jpg_folderprint u"MXD 存放在: " + output_mxd_folderprint "=================================================="except Exception as e:import tracebackprint u"运行出错,详细信息如下:\n" + traceback.format_exc()if __name__ == "__main__":batch_process()

成果图展示

其中第二个的图层不包括tif数据仅输出对应石家庄名称的shp,效果更为明显。(批量输出矢量数据的代码后续也会更新,整体上删除批量遍历栅格数据的过程)

原工程空间及案例数据获取方式

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/10 7:57:27

四川西昌电器门店:30年本地老店,5大优势让你买电器不踩坑!

【四川西昌京东家电】哪家好:专业深度测评开篇:定下基调随着西昌市民对家电品质与服务需求的提升,选择一家靠谱的家电门店成为关键。本次测评聚焦四川西昌家电市场,旨在通过客观数据与真实体验,为消费者提供权威选购参…

作者头像 李华
网站建设 2026/2/6 23:55:28

python 学习笔记(文件和目录操作)

创建目录 os.makedirs可以递归的创建目录结构。 import os os.makedirs(tmp/python/test,exist_okTrue) #exit_ok True指定了,如果某个要创建的目录已经存在,也不报错删除文件或目录 os.remove 可以删除一个文件 os.remove(test.py)**shutil.rmtree()**…

作者头像 李华
网站建设 2026/2/4 19:37:38

实验一 安全威胁与攻击实验

一、实验目的安全威胁与攻击实验与理论教学第一章信息安全概论相对应。本实验在学生完成MAC地址欺骗攻击与防御实验、OSPF路由项欺骗攻击和防御实验的基础上,使学生能够理解威胁、攻击、资产的关系,并理解基本安全设计原则的重要性。具体如下&#xff1a…

作者头像 李华
网站建设 2026/2/5 9:26:28

二十一、pinctrl子系统

前言 前面我们写的GPIO驱动程序都是自己在驱动里面定义好gpio引脚需要用到的寄存器,然后在驱动程序里面直接去配置这些寄存器。Linux是一个成熟的,跨平台的通用操作系统,对于配置引脚这样的最基本的功能,是已经有一套现成的框架可…

作者头像 李华
网站建设 2026/2/8 9:23:17

Java Web 社区医院信息平台系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着信息技术的快速发展,传统社区医院的管理模式已难以满足现代医疗服务的需求。社区医院在日常运营中涉及患者信息管理、医生排班、药品库存、预约挂号等多方面业务,传统的手工记录或单机系统存在效率低下、数据易丢失、信息共享困难等问题。为了提…

作者头像 李华
网站建设 2026/2/8 7:21:18

基于SpringBoot+Vue的IT交流和分享平台管理系统设计与实现【Java+MySQL+MyBatis完整源码】

摘要 随着互联网技术的快速发展,IT技术交流与知识分享的需求日益增长。传统的技术论坛和社交媒体平台虽然提供了基础的交流功能,但在专业性、系统性和用户体验方面仍有较大提升空间。尤其是在技术问答、资源共享和项目管理等方面,缺乏高效的整…

作者头像 李华