当前位置: 首页 > news >正文

【教你用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,效果更为明显。(批量输出矢量数据的代码后续也会更新,整体上删除批量遍历栅格数据的过程)

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

http://www.jsqmd.com/news/217638/

相关文章:

  • xampp-linux-1.8.1.tar.gz 怎么安装?Linux下XAMPP离线安装完整步骤
  • 数智孪生,金流·物流全透视:构建某银行制造业贷后风控新范式—— 基于领码 SPARK 融合平台的技术解决方案
  • 四川西昌电器门店:30年本地老店,5大优势让你买电器不踩坑!
  • springboot事务触发滚动与不滚蛋
  • ​ ⛳️赠与读者[特殊字符]1 概述基于城市场景下无人机三维路径规划的导航变量的多目标粒子群优化算法(NMOPSO)研究摘要随着无人机应用场景的复杂化,城市场景下的三维路径规划需同时优化
  • Python 内置函数:那些你见过但未必真正了解的“老朋友“
  • 鸿蒙PC上Qt原生应用开发:从零搭建开发环境到部署实战,附HarmonyOS SDK配置与避坑指南(C++实现)
  • 鸿蒙PC Qt开发环境配置全攻略:从零搭建到第一个原生应用实战
  • 基于Java+SpringBoot+SSM合同信息管理系统(源码+LW+调试文档+讲解等)/合同管理信息系统/合同信息管理平台/合同管理系统/信息管理系统/合同管理软件/合同资料管理系统
  • 鸿蒙PC开发指南:从零配置Qt环境到实战部署完整流程
  • 鸿蒙PC版Electron开发指南:手把手教你搭建环境并打包跨端应用
  • 鸿蒙PC上Electron原生应用开发:从零到部署的实战避坑指南
  • 从零到一:基于Qt on HarmonyOS的鸿蒙PC原生应用开发实战与性能优化指南
  • 《实战指南:Electron框架鸿蒙PC化,跨端迁移的完整配置与核心代码解析》
  • 鸿蒙PC原生应用开发避坑指南:Qt 6.6与Electron 28兼容性问题全解析
  • 1. 数据存储结构
  • 实时数字信号处理——AM发射器
  • 在日常里也要制造积极情绪
  • 前后端分离海滨体育馆管理系统系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程
  • 墙绘产品展示交易平台信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
  • 5. enum(枚举)关键字在C/C++中的作用
  • Java SpringBoot+Vue3+MyBatis 社区医院信息平台系统源码|前后端分离+MySQL数据库
  • 包装对象揭秘:前端新人踩坑后才懂的JS冷知识
  • 前后端分离Web足球青训俱乐部管理后台系统系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程
  • 基于SpringBoot+Vue的网上租赁系统管理系统设计与实现【Java+MySQL+MyBatis完整源码】
  • python 学习笔记(文件和目录操作)
  • 三阶幻方了解-七年级上册
  • 【毕业设计】SpringBoot+Vue+MySQL Web足球青训俱乐部管理后台系统平台源码+数据库+论文+部署文档
  • SpringBoot+Vue 社区医院信息平台管理平台源码【适合毕设/课设/学习】Java+MySQL
  • 基于SpringBoot+Vue的学科竞赛管理管理系统设计与实现【Java+MySQL+MyBatis完整源码】