
简介本资源面向地理信息科学、地球物理及遥感方向的科研人员与高年级本科生提供一套基于GMTGeneric Mapping Tools实现栅格数据本地化裁剪与山体阴影增强的完整实践方案。针对GIS中常见需求——使用Shapefile矢量边界精确裁剪遥感影像或DEM栅格并叠加光照模拟地形立体效果资源封装了从shp读取、坐标匹配、grdclip裁剪到grdimage山体阴影渲染的全流程GMT脚本与配套数据。压缩包共11个文件289KB含shp/shx/dbf/prj等标准矢量组件、gmt配置脚本、bat批处理命令及png示例图结构紧凑可直接运行调试。已有82人学习下载读者可即刻获得可复用的裁剪模板、光照参数调优经验及shp与栅格协同处理的关键排错提示显著降低GMT地理可视化入门门槛。1. 项目概述当本地矢量遇上全球栅格在地理信息处理GIS和地球科学制图领域我们常常会遇到一个非常具体的需求手头有一份特定区域的矢量边界文件比如某个县的行政边界、一个研究区的范围或者一条河流的流域同时还有一份覆盖范围更大的栅格数据比如全球地形数据、遥感影像或气候模型输出。我们的目标很明确就是把这个大范围的栅格数据精准地“裁剪”到我们关心的那个小区域里并在此基础上制作出具有立体感、能直观反映地形起伏的山体阴影图。这听起来像是专业GIS软件如ArcGIS的典型工作但今天我们要聊的是如何用一款在科研和制图领域备受推崇的命令行工具——GMTGeneric Mapping Tools——来高效、精准地完成这项任务。你可能会问为什么不用更“傻瓜式”的桌面软件原因在于效率、可重复性和批量处理能力。当你需要处理成百上千个区域或者你的数据处理流程需要嵌入到一个自动化的脚本中时命令行工具的优势就凸显出来了。GMT正是这样一款利器它以强大的数据处理和高质量制图能力著称尤其擅长处理全球尺度的网格数据。本次项目“GMT使用本地shp文件裁剪栅格文件并使用山体阴影”核心就是解决“如何利用本地的Shapefile矢量文件作为蒙版去裁剪一个栅格文件并基于裁剪后的地形数据生成美观的山体阴影图”这一问题。整个过程可以拆解为几个关键环节首先是环境与数据的准备确保你的GMT安装正确并且手头有合适的.shp矢量文件和.grd或其它格式栅格文件其次是用GMT读取并处理这些数据核心步骤是执行裁剪操作最后是基于裁剪结果计算并可视化山体阴影。虽然项目标题提及了.rar压缩包这通常意味着里面包含了示例数据和可能的工作脚本但我们的重点在于理解其背后的原理和命令流程这样你就能举一反三处理自己的数据了。接下来我将以一个具体的场景为例假设我们手头有中国云南省的县级行政区划Shapefile以及一份SRTM全球地形数据目标是制作某个县的地形山体阴影图。2. 前期准备理解你的数据与工具链在动手写任何命令之前花点时间弄清楚你手里的“原料”和“厨具”至关重要。这一步没做好后面很可能步步维艰。2.1 核心工具GMT的安装与模块认知GMT不是一个单一的软件而是一个庞大的工具集。我们不需要一次性掌握所有命令但必须了解本项目会用到的几个核心模块gmt这是GMT 6版本后的主命令所有功能都通过它来调用格式如gmt module [options]。grdcut/grdclip栅格裁剪的核心命令。虽然grdcut常用于按矩形范围裁剪但结合其他工具也能实现基于矢量的复杂裁剪。grdmask这是实现矢量裁剪栅格的关键命令。它的本质是创建一个与栅格文件同范围、同分辨率的“掩膜mask网格”在矢量区域内的值设为1或指定值区域外的值设为0或NaN。然后利用这个掩膜网格与原栅格进行计算从而实现裁剪。grdgradient用于计算山体阴影hillshade或坡度gradient。它需要输入地形栅格通过模拟光照效果输出一个表示光照强度的新栅格这是生成立体地形图的灵魂。grdimage用于将栅格数据无论是原始地形还是山体阴影渲染成图像。pscoast,psxy用于绘制海岸线、边界、矢量要素等。在成果图中叠加行政区划边界会使得地图更专业。grdinfo查看栅格文件信息的利器比如范围、网格间距、数据格式等在操作前务必先用它摸清数据底细。确保你的GMT已正确安装并且版本在6.0以上。可以在终端输入gmt --version来验证。如果还没安装请根据你的操作系统Linux/macOS/Windows WSL去GMT官网查找安装指南。2.2 数据准备栅格与矢量的“握手”数据是项目的基石。我们需要两类数据A. 栅格文件待裁剪对象常见格式有NetCDF (.grd, .nc)GeoTIFF (.tif)ESRI .asc等。GMT对NetCDF格式支持最原生。例如我们可以使用SRTM航天飞机雷达地形测绘任务的90米或30米分辨率数字高程模型DEM。假设我们已经下载了覆盖中国区域的SRTM数据并拼接成了一个名为srtm_china.grd的文件。提示在操作前务必使用gmt grdinfo srtm_china.grd查看其经纬度范围x_min, x_max, y_min, y_max、网格间距和数据类型。记下这个范围后续设置绘图区域时会用到。B. 矢量文件裁剪模具这就是我们的本地Shapefile.shp。一个完整的Shapefile通常由多个文件组成.shp, .shx, .dbf, .prj等你需要确保这些文件都在同一目录下并且GMT能够读取。GMT通过psxy或grdmask命令的-S选项来识别矢量数据。 例如我们有一个云南省某县边界的Shapefile文件基名为county_boundary即目录下存在county_boundary.shp,county_boundary.shx等文件。关键兼容性检查投影一致性这是最容易出错的地方。栅格数据和矢量数据必须使用相同的地理坐标系或投影坐标系。你可以通过.prj文件或使用GDAL的ogrinfo/gdalinfo命令来查看数据的投影信息。如果两者投影不同必须先进行投影转换确保它们“说同一种语言”。GMT虽然能在绘图时进行动态投影转换但在进行像grdmask这类网格操作时强烈建议先统一投影。范围包含关系你的矢量区域必须完全或部分位于栅格数据的覆盖范围内。如果你想裁剪的区域完全在栅格范围之外那结果自然是空的。3. 核心操作解析从矢量掩膜到栅格裁剪理解了工具和数据我们就可以进入核心的裁剪流程了。这个过程不是简单的一步到位而是通过创建一个中间产品——掩膜网格——来实现的。3.1 第一步创建矢量掩膜网格如前所述grdmask是我们的核心武器。它的作用是在一个指定的网格范围内这个范围通常要略大于你的矢量区域并且包含你的栅格数据范围生成一个新的网格文件。这个新网格在矢量多边形内部的节点上赋值为1外部的节点上赋值为0或者No Data值如NaN。假设我们的栅格数据srtm_china.grd的范围是100E/110E/20N/30N网格间距是0.000833度约90米。我们想用county_boundary.shp来创建掩膜。一个基本的命令如下gmt grdmask county_boundary.shp -Gsrtm_china.grd -R100/110/20/30 -I0.000833 -N0/1/1 -r -V -Mcounty_mask.grd让我们拆解这个命令county_boundary.shp输入的矢量文件。-Gsrtm_china.grd这是一个关键参数。它告诉grdmask参考srtm_china.grd的网格注册方式像素点注册还是网格线注册和数据类型。这能确保生成的掩膜网格与原地形网格在空间上完全对齐这是后续正确计算的前提。你也可以用-R -I直接指定范围和间隔但用-G引用原文件更不容易出错。-R100/110/20/30指定生成掩膜的区域范围经度最小值/最大值/纬度最小值/最大值。这里我们用了原栅格的范围确保掩膜覆盖整个可能区域。-I0.000833指定输出掩膜网格的间距分辨率。这里设置为和原地形数据一致。-N0/1/1这是掩膜值的设置。格式为outside/inside/boundary。0/1/1表示多边形外部值为0内部值为1边界上也设为1。你也可以用-NNaN/1/1这样外部就是NaN非数字在后续计算中会被自动忽略。-r注册方式。确保与原栅格一致通常是网格线注册-r或像素注册-rp。使用-G引用原文件时这个参数有时可以省略因为会继承原文件的属性。-V显示详细处理信息方便调试。Mcounty_mask.grd输出的掩膜网格文件名。执行完这一步你会得到一个county_mask.grd文件。你可以用gmt grdimage county_mask.grd -JX10c -B -C快速查看一下它应该是一个二值图你的目标区域是白色值1其他区域是黑色值0。3.2 第二步应用掩膜裁剪栅格有了掩膜网格裁剪就变成了一个简单的网格间乘法或条件赋值操作。我们使用grdmath命令。gmt grdmath srtm_china.grd county_mask.grd MUL county_dem_clipped.grd这个命令非常直观grdmath是GMT的网格计算器。srtm_china.grd MUL county_mask.grd表示将地形网格与掩膜网格逐像元相乘。在掩膜为1的区域地形值乘以1保持不变在掩膜为0的区域地形值乘以0就变成了0。这样我们就得到了一个仅在目标区域有地形值、其他区域为0的新网格county_dem_clipped.grd。如果你在创建掩膜时使用了-NNaN/1/1那么外部是NaN。NaN与任何数进行算术运算结果都是NaN。所以乘法后区域外依然是NaN区域内保留原值。NaN在GMT中被视为“无数据”在绘图和后续处理中会被自动忽略这通常是更干净的做法。命令是一样的。为什么是乘法这是一种高效且数学上清晰的掩膜方法。除了乘法你也可以用grdclip或grdmath的条件语句来实现但乘法是最直接和常见的。3.3 第三步计算山体阴影裁剪得到了纯净的县域地形数据county_dem_clipped.grd现在可以为它制作“光影效果”了。这用到grdgradient命令。gmt grdgradient county_dem_clipped.grd -Gcounty_hillshade.grd -A315 -Nt0.8 -Vcounty_dem_clipped.grd输入的地形网格。-Gcounty_hillshade.grd输出的山体阴影网格。-A315光照方向方位角。315度表示光线从西北方向照射这是制图中非常经典的角度能产生良好的立体感。你可以调整这个值来改变阴影方向。-Nt0.8-N指定标准化方式t表示使用-A指定的方位角进行地形斜率计算0.8是一个增强因子exaggeration factor。值1.0表示原始坡度小于1会减弱阴影对比大于1会增强。0.8是一个比较稳健的默认值能使地形起伏看起来更自然避免过强的“浮雕感”。-V显示进度。生成的county_hillshade.grd是一个灰度网格值通常在 -1 到 1 之间表示每个像元受到光照的强度亮到暗。4. 成果可视化绘制专业地形图有了裁剪后的地形和计算好的山体阴影我们就可以绘制一张专业的地形图了。通常我们会将山体阴影作为底图提供明暗纹理再给地形高度叠加上颜色提供高程信息。4.1 创建色标文件CPT首先我们需要一个颜色映射表CPT来将高程值映射为颜色。我们可以基于裁剪后地形数据的范围来生成。# 首先获取裁剪后地形的高程范围 gmt grdinfo county_dem_clipped.grd -T100 # 假设输出建议的色标分段是 -T100/5000/100即从100米到5000米每100米一段。 # 然后基于这个范围创建一个色标。这里使用GMT内置的‘dem2’色标它非常适合地形。 gmt makecpt -Cdem2 -T100/5000/100 -Z topography.cpt-Cdem2使用内置的dem2配色方案。-T100/5000/100指定颜色映射的数据范围最小值/最大值/间隔。这里的值需要根据你实际的grdinfo输出进行调整。-Z创建连续变化的色标。 topography.cpt将生成的色标保存到文件。4.2 绘制地图现在使用grdimage来组合绘制。通常的顺序是先绘制山体阴影作为灰度底图再在上面叠加彩色地形使用半透明效果让阴影透上来。gmt begin county_topographic_map pdf # 1. 设置绘图区域和投影。这里使用墨卡托投影范围由裁剪后的地形决定。 gmt grdinfo county_dem_clipped.grd -I- # 获取数据的精确范围假设是 R102.5/103.5/24.8/25.5 gmt basemap -R102.5/103.5/24.8/25.5 -JM10c -Baf -BWSent云南省XX县地形图 # 2. 首先绘制山体阴影灰度图。使用 -I 选项将山体阴影网格作为强度光照图层。 gmt grdimage county_hillshade.grd -I -Q # 3. 在上面叠加彩色地形。使用 -C 指定色标-t 设置透明度例如50%即0.5。 gmt grdimage county_dem_clipped.grd -Ctopography.cpt -t50 # 4. 叠加行政区划边界使其更清晰。 gmt psxy county_boundary.shp -W1p,black -O -K # 5. 添加比例尺和图例 gmt basemap -Tm103.2/24.9w2co0c/0.5c # 比例尺 gmt colorbar -Ctopography.cpt -Bxa1000f500 -BylElevation (m) -DJMRw5c/0.3ch -O gmt end命令解析gmt begin ... end这是GMT 6的现代模式用于管理一个绘图会话。-JM10c使用墨卡托投影地图宽度为10厘米。-Baf自动绘制带有刻度的边框。-I在grdimage中表示接下来的网格county_hillshade.grd将作为强度图层即山体阴影使用它会调制后面绘制的彩色地形的亮度。-Q禁用插值对于山体阴影这种表示纹理的网格禁用插值可以保持其清晰度。-t50设置50%的透明度这样彩色地形不会完全遮盖住底下的山体阴影纹理两者融合效果更好。-W1p,black用1点粗的黑色线绘制矢量边界。执行上述脚本后你将得到一个名为county_topographic_map.pdf的高质量矢量图它清晰地展示了该县的地形起伏兼具科学性与美观性。5. 实战中的陷阱与精进技巧按照上述流程你大概率能成功出图。但在实际项目中总会遇到一些“坑”。下面分享几个我踩过之后总结出来的经验。5.1 矢量数据自身的问题问题1Shapefile多边形不闭合或自相交这是一个常见问题尤其来自某些不太规范的来源。grdmask在处理有几何错误的多边形时可能会失败或产生奇怪的结果。排查使用ogrinfo -al county_boundary.shp | grep -i ring或QGIS等软件检查几何有效性。解决在GMT外部修复。推荐使用GDAL/OGR的ogr2ogr命令ogr2ogr -f ESRI Shapefile county_boundary_fixed.shp county_boundary.shp -nlt POLYGON -makevalid这个命令会尝试修复几何错误。然后用修复后的文件进行后续操作。问题2矢量与栅格范围不匹配掩膜结果为全NaN或全0排查首先分别用gmt grdinfo和ogrinfo -so查看两者的范围。确保矢量至少有一部分落在栅格范围内。解决如果矢量范围远大于栅格考虑先裁剪矢量。如果只是略有偏差可以适当扩大grdmask的-R范围确保覆盖矢量区域。但最根本的还是要保证数据源的空间参考一致。5.2 栅格数据处理中的精度与性能问题裁剪后边缘有锯齿或数据异常原因这可能源于两个网格在边界处像元不对齐或者原始栅格数据本身在边界就有异常值如SRTM数据边缘的填充值。解决对齐确保grdmask的-R、-I、-r参数与原始地形网格完全一致。使用-G引用原文件是最稳妥的方法。处理NoData在裁剪前先处理原始地形中的无效值。例如SRTM的海洋区域可能是-32768。你可以先用grdclip将其设为NaNgmt grdclip srtm_china.grd -Sb-32767/NaN -Sa-32769/NaN -G srtm_china_nan.grd然后用处理过的srtm_china_nan.grd进行后续操作。性能优化处理大范围高分辨率数据全球高分辨率地形数据如30米SRTM体积庞大。直接对整个大文件进行grdmask和grdmath操作可能非常慢且消耗内存。技巧先粗略确定矢量范围然后用grdcut将大栅格切出一个稍大的子区域再对这个子区域进行精细的矢量裁剪。# 先用 ogrinfo 获取矢量范围假设是 102/104/24/26 gmt grdcut srtm_china.grd -R102/104/24/26 -G srtm_subregion.grd # 然后基于 srtm_subregion.grd 和矢量文件进行上述掩膜、裁剪流程这能极大提升处理速度。5.3 山体阴影效果的艺术性调整默认参数生成的山体阴影可能太“平”或太“刺眼”。光照方向-A315度是标准但尝试45度东北光或135度东南光可能会突出不同的地形特征。增强因子-Nt-Nt1.2会增加对比度让山脉看起来更陡峭-Nt0.5会减弱对比度效果更柔和。对于丘陵地区可能需要调高对于高山地区默认值可能就很好。多方向光照合成这是制作出版级地形图的技巧。通过组合两个或多个不同方向的光照可以消除单一光源造成的死角阴影让地形细节更丰富。gmt grdgradient county_dem_clipped.grd -Ghill_nw.grd -A315 -Nt1 gmt grdgradient county_dem_clipped.grd -Ghill_ne.grd -A45 -Nt0.6 gmt grdmath hill_nw.grd hill_ne.grd ADD 2 DIV hill_combined.grd然后将hill_combined.grd用作强度图层。这需要一些实验来找到最佳权重组合。5.4 自动化与批处理如果你需要对多个县多个Shapefile执行相同的操作手动重复是不可接受的。编写一个Shell脚本Bash或Python脚本是必然选择。一个简单的Bash脚本框架如下#!/bin/bash # 假设所有县的shp文件都在 county_shps/ 目录下命名为 county_01.shp, county_02.shp ... BASE_DEMsrtm_china.grd for SHP in county_shps/*.shp; do COUNTY_NAME$(basename $SHP .shp) echo Processing $COUNTY_NAME... # 1. 创建掩膜 gmt grdmask $SHP -G$BASE_DEM -NNaN/1/1 -r -Mmask_${COUNTY_NAME}.grd # 2. 裁剪DEM gmt grdmath $BASE_DEM mask_${COUNTY_NAME}.grd MUL dem_${COUNTY_NAME}.grd # 3. 计算山体阴影 gmt grdgradient dem_${COUNTY_NAME}.grd -Ghillshade_${COUNTY_NAME}.grd -A315 -Nt0.8 # 4. 绘制地图 (这里需要为每个县定制 -R 范围可以从裁剪后的DEM获取) RANGE$(gmt grdinfo dem_${COUNTY_NAME}.grd -I-) gmt begin map_${COUNTY_NAME} pdf gmt basemap -R$RANGE -JM10c -Baf -BWSent${COUNTY_NAME}地形图 gmt grdimage hillshade_${COUNTY_NAME}.grd -I -Q gmt grdimage dem_${COUNTY_NAME}.grd -Ctopography.cpt -t50 gmt psxy $SHP -W0.5p,black gmt colorbar -Ctopography.cpt -DJMRw5c/0.3ch -Bxa1000f500 -BylElevation (m) gmt end # 5. 清理中间文件可选 rm mask_${COUNTY_NAME}.grd done echo All counties processed!这个脚本实现了自动化批量处理大大提升了工作效率。关键在于利用循环和变量将单次流程封装起来。本文还有配套的精品资源点击获取