
简介一份面向海洋学、地理信息系统与环境科学方向的MATLAB绘图代码资源主要解决水深分布图的读取、处理与可视化问题。压缩包共包含2个文件1个MATLAB脚本文件和1张结果示意图整体压缩包大小仅291KB结构简洁易于上手。脚本覆盖从ASCII格网或二进制格式水深数据的读取、矩阵化转换、缺失值与异常值筛查到调用绘图函数生成图像、设置色彩映射、添加颜色条并兼顾经纬度坐标转换与地图投影等环节可输出带区域地理元素和颜色标注的深度图。示例示意图便于对照程序运行效果用户可据此快速验证参数调整结果并迁移到自己的数据中。目前已有5176人学习下载适合海洋、地学等相关领域的科研人员、学生以及MATLAB初学者作为参考资料和复用模板。1. 水深分布图的本质是先网格化再谈用 matlab 把它画成可发布的地图在水文调查、航道疏浚和海洋工程验收里水深分布图是必须交付的成果图。很多人第一次用 matlab 画水深分布图时手头只有一串测深散点经度、纬度、水深下意识就 scatter 一张彩色点图交差。点图只能表达“哪些位置测到了什么值”完全体现不出连续的水下地形走向评审第一眼就会打回。真正可用的水深分布图要先对散点做空间插值得到覆盖整个测区的规则网格再用伪彩色填色、等深线、色标三件套把它渲染出来。matlab 在这一链条上没有短板从 readmatrix 读日志、scatteredInterpolant 插值到 contourf 出图全程不需要切到外部 GIS。下面按读数据、网格化、渲染、三维与排错四步走每段代码都给出参数含义和常见坑。2. 为水深分布图备数据四种文件载入与符号、重复点清洗水深数据的落盘格式远比想象中杂。外业多波束测深项目交付时常见的是按航次组织的 CSV 或 Excel 日志每行一条 ping 记录海图数字化结果多为空格分列的 txt公开地形数据则大量封装成 netCDF还有人从旧项目里直接递来一个 .mat。我接到新任务后第一步不是看数据全不全而是先写一段清洗脚本把符号、缺测、重复点三件事定死否则后面插值出的地形全是假象。提示水深方向约定在行业内并不统一。海图常用负值表示低于海面但部分测深软件用正值存储。进入 MATLAB 后我习惯统一为负值海底越深数值越小。这样 colormap 和等深线分层都按“负值越小越深”的自然逻辑走标色标时不用来回换算。2.1 不同文件格式的载入方式对比下表给出我日常处理四类文件时对应的读取命令。刻意不写成 GUI 导入因为脚本化才能在换一批数据时直接复用。文件类型常用命令主要坑CSV / Excelreadmatrix / readtable表头、混合列会让 readmatrix 直接报错空格分隔 txtimportdata 或 readmatrix缺测字段表现为 NaN需 isfinite 过滤.matload再用 whos 查变量变量名不固定别写死字段名netCDFncread配合 ncdisp 看结构维度顺序和 fillvalue 识别读 netCDF 时我一般先执行ncdisp(bathy.nc)确认第一维是 lon 还是 lat再决定ncread后面要不要做 permute。很多人栽在“读出来全是 NaN”上其实是 fillvalue 没被识别需要手动把等于 fillvalue 的点置 NaN 后再参与计算。2.2 一次完整的清洗模板% 读取测深日志前 3 列分别是经度、纬度、水深 data readmatrix(cruise_2024.csv); lon data(:, 1); lat data(:, 2); z data(:, 3); z(z 0) -z(z 0); % 统一水深为负值 rowsOk isfinite(lon) isfinite(lat) z 0 z -10000; lon lon(rowsOk); lat lat(rowsOk); z z(rowsOk); % 同一测站存在多次回波合并为均值避免插值报重复点 [site, ~, idx] unique([lon, lat], rows, stable); zsite accumarray(idx, z(:), [], mean); lon site(:, 1); lat site(:, 2); z zsite;每行过滤都有目的。isfinite拿掉读文件产生的 NaNz 0守住符号约定防止正高程混入z -10000是一个粗合理性下限马里亚纳海沟也就 -11034 m浅水区调查我一般收紧到 -3000 m。unique(..., rows, stable)与accumarray的组合不常见作用是合并同坐标重复测点外业船在锚地来回扫测时同一个站位出现几十条 ping 是常态不合并的话scatteredInterpolant后面会直接报重复点错误。读 .mat 时如果不确定变量名先whos(-file, bathy.mat)列出全部变量再按需 load 精确字段。3. 水深分布图的网格化插值scatteredInterpolant 与 griddata 的选型依据3.1 为什么必须插值成规则网格MATLAB 里 pcolor、surf、contourf 这三个能真正表现“面”的函数都要求 Z 是与 X、Y 一一对应的二维矩阵。散点数据的 X、Y 是无规则列向量直接传给 contourf 会得到一张无法解释的三角网图甚至报维度错误。网格化就是把研究区切成一个矩形网格每个网格点上用周围散点推算一个水深值得到完整的 Z 面。网格密度是这里唯一需要决策的参数。我一般按原始测线间距的 23 倍取网格间距设计间距 100 m网格就设成 200300 m网格过密不会增加地质信息只会放大插值噪声。经纬度网格在跨带时容易变形简单做法是在投影坐标下完成插值出图前再把坐标轴标签改回经纬度。3.2 scatteredInterpolant 与 griddata 的对比散点插值有两个主入口很多 matlab 教程只讲 griddata 一个函数导致遇到大数据或需要反复求值时很被动。真正的区别在两点第一griddata 每次调用都重算scatteredInterpolant 先构造插值对象之后对该对象任意查询新网格多次求值几乎零成本第二griddata 对外推无能为力查询点一旦落在散点凸包之外就变成 NaN而 scatteredInterpolant 可以在构造时单独指定外推方式。对比项scatteredInterpolantgriddata多次网格求值构造一次任意查询每次重新计算支持插值方法nearest / linear / naturalnearest / linear / natural / cubic / v4外推控制单独设置 extrapolationMethod不支持凸包外为 NaN十万点以上性能明显更快内存与耗时暴涨返回结果插值对象直接返回 Z 矩阵选择上我几乎只用 scatteredInterpolant。唯一例外是评审需要对比 cubic 效果时griddata 的 cubic 更平滑但船舷两侧的陡坎地形会被打圆v4 是全局径向基函数样点多时慢到无法接受日常不推荐。3.3 构造插值对象并检查过冲% 基于清洗后的散点构造插值器 F scatteredInterpolant(lon, lat, z, natural, linear); xq linspace(min(lon), max(lon), 300); % 目标网格经度向量 yq linspace(min(lat), max(lat), 220); % 目标网格纬度向量 [Xg, Yg] meshgrid(xq, yq); Zg F(Xg, Yg); Zg(Zg 0) NaN; % 过冲产生的正地形一律弃掉scatteredInterpolant(lon, lat, z, natural, linear)的第四个参数是插值方法第五个是外推方法。水深属于空间连续缓变场natural自然邻域对数据密度变化不敏感也不会像 cubic 那样在断面突变处产生过冲这是水深图用 natural 而非 cubic 的核心原因。外推设 linear 只是给测区边界外一点余量如果外推后出现扇形深值区说明查询网格盖过了散点范围要回到 3.1 收紧网格边界。% 快速检查散点叠加在插值面上看边界是否贴边 figure; pcolor(Xg, Yg, Zg); shading interp; hold on; plot(lon, lat, .k, MarkerSize, 3); clim([min(z) max(z)]);clim 是 R2022a 之后推荐的写法老版本用 caxis 也兼容。检查时看两点点云边缘是否和颜色突变带贴合测区角落有没有异常深值区。出现异常就直接回到清洗脚本查原始日志不要在插值参数上反复试。插值只能平滑数据不能凭空造出数据。4. 用 contourf 把网格化水深渲染成分布图填色、等深线与陆域掩膜4.1 渲染管线总览插值得到 Xg、Yg、Zg 后出图阶段固定走五步掩膜陆域、选择填色对象、设置色标区间、叠加等深线、标注坐标。五步全写在一个脚本里换数据只改文件名和分层向量。不要偷懒用 imagesc 直接画矩阵它会把 X、Y 坐标当像素索引经纬度标签会差一个网格边长看似正常刻度全错。figure(Color, w); ax axes(NextPlot, add); Zg(Zg -1) NaN; % 水深大于 -1 m 视为陆域或干出滩 levels 0:-5:-100; % 等深线分层0 到 -100 m每 5 m 一条 contourf(ax, Xg, Yg, Zg, levels, LineStyle, none); colormap(ax, deepBlue(256)); cb colorbar(ax); cb.Label.String 水深 / m; clim(ax, [-100 0]); % 色标上下限与 levels 尾部对齐 hold(ax, on); [C, h] contour(ax, Xg, Yg, Zg, levels, Color, [0.3 0.3 0.3], LineWidth, 0.5); clabel(C, h, FontSize, 7, LabelSpacing, 400); hold(ax, off); xlabel(ax, 经度 / °E); ylabel(ax, 纬度 / °N); axis(ax, equal); axis(ax, tight);contourf 的 levels 是严格递增向量同时决定分层边界和填色数量如果 min(Zg) 比 levels 最深处更深多出的段会画成最深色的纯色块视觉上很怪所以 levels 尾值要接近实际最深处比如调查区最深 -86 m就写0:-5:-90。LineStyle, none去掉分层之间的白线这是用 matlab 画图时填色图最常见的像素级瑕疵。clabel的LabelSpacing控制相邻标注间距大洋大图给 600800小港湾区 300 左右。4.2 配一张适合深水的渐变色标colormap 用从浅青到深蓝的渐变浅水区绝不能出现亮黄色。构造方式和色阶数量直接决定打印效果function cmap deepBlue(n) % 构造水深图专用渐变 colormap % n 为色阶数量常规出图 256出版级可给 512 cmap [linspace(0.85, 0.10, n), ... linspace(0.95, 0.35, n), ... linspace(0.90, 0.55, n)]; end三个 linspace 分别对应 R、G、B 通道随水深值从浅到深的变化。256 个色阶在多数显示器上不会有可见分带白底打印也够出版级输出把 n 提到 512PDF 导出几乎无感。注意 colormap 作用对象是 axes 而不是数据本身同一张图叠了两个 axes 时各设各的 colormap互不影响。4.3 属性速查与局部图复用对象/属性取值示例用途与注意contourf LineStylenone去掉分层线保持纯填色shadinginterp对 pcolor 生效让像素色平滑过渡contour LineWidth0.30.8等深线粗细打印越粗越稳clim / caxis[-100 0]色标上下限必须与 levels 尾部对齐daspect[1 1 v]三维俯视时控制垂直拉伸这套参数确定后复现性是稳定的。当天要出局部放大图把 xq、yq 换成子区间的 linspace重新对同一个 F 求值脚本其余部分原样复用。这就是一开始用 scatteredInterpolant 对象而不是 griddata 的回报换区域重画一次图的速度完全支撑多轮修改。5. 水深分布图进阶surf 三维地形、高清导出与 3 个高频报错5.1 三维海底地形渲染二维填色图展示分区三维图展示起伏两张配合才能把报告写厚。在 Zg 上直接 surf再配合光照就是一张能进 PPT 的海底地形面。垂直比例必须压扁否则水深 100 m、水平跨度 10 km 的区域会被拉成悬崖。surf(Xg, Yg, Zg, EdgeColor, none); view(-55, 60); % 视角方位角 -55仰角 60 axis vis3d; light(Position, [1 -0.5 1], Style, infinite); lighting gouraud; material([0.4 0.5 0.2]); daspect([1 1 0.01]); % 第三个分量 垂直 / 水平比daspect 第三分量按实际跨度换算水平跨度约 10 km水深变化约 100 m 时写 0.01 就是自然比例只展示航道走向时可放到 0.03。光照固定放在左前上方避免沟槽阴影和真实地形混淆。5.2 三个高频报错与对应处理排查顺序固定先查原始数据再查网格范围最后查矩阵方向。scatteredInterpolant 报重复点错误信息围绕 unique 展开原因是原始测点有同坐标重复。用 2.2 的 unique 加 accumarray 合并不要只删不平均。contourf 报 Z 尺寸不足或维度不匹配先 size(Zg)再对照 size(Xg)、size(Yg)。最常见是 meshgrid 写出顺序时第一、二参数写反产生维度错觉直接 transpose 就能过。大片白板白板不是没数据而是查询网格超出散点凸包。把 xq、yq 的 min/max 缩回散点范围或加一层边界多边形掩膜范围外的点置 NaN。出正式图用 exportgraphics替代老式 print 能自动裁剪白边exportgraphics(gcf, bathy_final.png, Resolution, 300);R2020a 之前的版本用print(gcf, -dpng, -r300, bathy_final.png)等效。导出前再把散点层关掉、关掉多余的标题栏保证版面上只有最终成果图。本文还有配套的精品资源点击获取