简介:整合版m_map工具包已内置高清海岸线数据(gshhg)与高清地形数据(etopo1),专供MATLAB用户进行海洋、气象、地理等专业绘图。包内m_gshhs.m与m_etopo2.m的函数路径已预先调整,使用者只需将m_map文件夹复制到MATLAB的toolbox目录并添加路径,即可直接调用,免去自行下载、转换海量数据的繁琐步骤。资源共140个文件,以74个m脚本为核心,辅以36张png效果预览图、15个b格式海岸线/河流/国界矢量数据、若干txt与mat数据文件,压缩包整体约252.34MB,目录结构清晰。目前已有911人学习下载,适合需要快速搭建高质量地图绘制环境、从事海岸线与地形可视化研究的学生和科研人员。内置gshhs_f/h/i/l等多级海岸线数据及wdb_rivers、wdb_borders要素,配合etopo1地形数据,可轻松绘制出版级海洋地形图。 第一次用M_Map画近海地形图的时候,我卡在了一个特别尴尬的环节:海岸线数据下载好了,ETOPO1地形文件也下载好了,结果两个数据在坐标系和格式上互不兼容,画出来的岸线要么浮在半空,要么地形底图东一块西一块,折腾两小时才把底图拼对。后来我把整套M_Map函数包和配套的GSHHG海岸线数据、ETOPO1地形数据整理成了一个整合版工具包,坐标统一、文件路径配好,拿到就能直接用。这篇文章就聊聊这套整合包到底解决哪些痛点,以及从安装到出图的一整套实操流程,适合用MATLAB做海洋、气象、地质底图绘制的科研人员和学生。
1. 为什么需要一份“整合版”:原始方案的三座大山
1.1 海岸线数据GSHHG的价值与坑点
GSHHG的全称是Global Self-consistent, Hierarchical, High-resolution Geography Database,可以理解为GSHHS海岸线数据库的升级版,里面除了海岸线,还有湖泊、河流以及陆地边界等要素。数据分了五个分辨率等级,由粗到细是crude、low、intermediate、high、full,分别对应不同的比例尺需求。画全球大洋用crude就行,如果画某个海湾或者港口区域,必须上high甚至full,否则岸线的锯齿感会非常明显。
但数据好归好,实际用起来坑点不少。M_Map里的m_gshhs函数读取的是特定格式的二进制文件,后缀一般是.b,但很多朋友从网上下载到的是Shapefile或者netCDF格式,直接扔给m_gshhs根本读不了。就算下载对了格式,还得保证文件名和函数内部的调用名一致,版本对不上就会报错。另一个容易被忽视的问题是分辨率选择,有人图省事全程用full级,画全球图时M_Map会去处理和渲染极其密集的折线点,速度慢到能让人怀疑电脑死机。
1.2 地形数据ETOPO1的隐藏成本
ETOPO1是NOAA发布的全球地形模型,分辨率1弧分,大约1.8公里一个格点,还分为冰面和基岩两个版本。这个数据对画海洋地形底图来说非常关键,水深、陆高都包含在一个网格里,配合M_Map可以做出科研论文里常见的那种带地形底色的地图。
问题在于ETOPO1的原始数据是netCDF格式,全球网格规模大约是21601乘10801,直接全量读进MATLAB,内存占用轻松上GB级别。更麻烦的是,数据的经度范围通常是0到360度,而我们画中国周边或者大西洋区域时习惯用-180到180度,坐标系不换过来,画出来的地形分布位置就是错的。至于裁剪、插值、投影变换这些步骤,每一步都需要自己写代码,对不熟悉数据结构的人来说,光是把ETOPO1“喂”给M_Map就是一个不小的门槛。
1.3 整合版方案的核心收益
整合版工具包的核心逻辑很简单:把函数库、GSHHG二进制数据、ETOPO1地形数据、示例脚本全部放在一起,并且把数据文件和函数的版本对齐。这样用户拿到手之后,不用再跨越好几个网站去下载数据,也不用纠结文件格式对不对、坐标系统怎么统一,直接把整个工具包路径添加进MATLAB就能开始画图。
更深一层的好处是版本匹配问题被解决了。M_Map在更新过程中,对数据格式的要求也有细微变化,很多时候报错并不是代码写错了,而是函数和数据版本不匹配。整合包在打包时就完成了这层适配,这点对于刚接触M_Map的学生来说尤其省心,避免在环境配置阶段就被劝退。
2. 环境准备与安装部署
2.1 目录结构与数据放哪里
拿到整合包之后,先看一下整体目录结构。典型的结构大致是这样:
m_map_toolbox/ ├── m_map/ M_Map函数库 ├── gshhg/ GSHHG海岸线二进制文件 ├── etopo1/ ETOPO1地形数据文件 └── examples/ 示例脚本GSHHG目录下常见的文件包括gshhs_f.b、gshhs_h.b、gshhs_i.b、gshhs_l.b、gshhs_c.b这几个海岸线主文件,以及对应分辨率的河流文件如wdbii_rivers_f.b等。各分辨率级别和适用场景可以参考下表:
| 文件名 | 分辨率级别 | 适用场景 | 数据量 |
|---|---|---|---|
| gshhs_f.b | full | 局部港湾、大比例尺出图 | 最大,最精细 |
| gshhs_h.b | high | 区域海图、近岸研究 | 较大 |
| gshhs_i.b | intermediate | 省级行政区、边缘海 | 中等 |
| gshhs_l.b | low | 大洲、大洋尺度 | 较小 |
| gshhs_c.b | crude | 全球示意图 | 最小 |
ETOPO1目录下对应的是netCDF格式的原始地形文件,正常情况下文件名类似ETOPO1_Ice_g_gmt4.grd。建议不要改动目录名,因为示例脚本里默认按这个路径去找数据,改了就得同步改代码,没必要给自己找麻烦。
2.2 将工具包加入MATLAB路径
安装步骤其实就两步。第一步是添加路径,在MATLAB命令行执行:
addpath(genpath('D:\你的路径\m_map_toolbox')); savepath;这里用genpath是为了把m_map子目录一起加进去,不加子目录的话,M_Map的函数根本找不到。savepath是让路径设置永久保存,不然下次启动MATLAB又得重新addpath一遍。我习惯在脚本开头再加一次addpath,这样换电脑、换环境后只要改一个路径字符串就行,不依赖全局配置。
第二步是切换当前文件夹。直接把MATLAB的当前目录切到m_map_toolbox,或者用cd命令。因为m_gshhs这类函数在读取数据文件时,会优先在当前路径下找gshhs开头的文件,切到整合包根目录能省去不少路径匹配的麻烦。
2.3 快速验证安装是否成功
装没装好,画一幅最简单的图就知道了。在命令行里输入:
m_proj('lambert', 'long', [-130 -60], 'lat', [30 60]); m_gshhs('patch', [0.8 0.8 0.8], 'edgecolor', 'k'); m_grid('box', 'fancy');如果几秒钟内出现一幅北美区域的阴影地图,海岸线清晰、边框完整,说明M_Map函数库和GSHHG数据都正常。接着再测试ETOPO1读取,用ncread读取地形文件的x、y、z变量,检查维度信息是否匹配,这一步能尽早发现netCDF文件损坏或路径错误的问题,不用等到正式画图时才发现。
3. 核心功能实现与绘图实操
3.1 投影设置与坐标系选择
M_Map里面所有绘图都建立在投影之上。m_proj函数用来设置投影,常见参数包括'mercator'、'lambert'、'stereographic'、'albers'等。选投影的原则其实很直接:低纬度或航海用途选墨卡托,中高纬度的大区域选Lambert或Albers,极地研究选极方位立体投影。
举个例子,画南海区域的海底地形图,我一般用:
m_proj('mercator', 'long', [105 125], 'lat', [0 25]);这段代码的含义是采用墨卡托投影,经度范围东经105到125度,纬度范围北纬0到25度。墨卡托投影在低纬度变形小,画航线、叠加站位点都很舒服,是海洋研究里最常用的投影方式之一。
3.2 绘制高清海岸线:m_gshhs的核心姿势
画海岸线主要用m_gshhs函数。传入首字母表示使用哪个分辨率等级,比如'f'代表full、'h'代表high。最简单的方式是:
m_gshhs('h', 'patch', [0.6 0.8 0.6], 'edgecolor', 'k', 'linewidth', 0.8);其中'patch'是填充陆地的颜色,'edgecolor'设置岸线描边颜色,'linewidth'控制岸线粗细。如果只想画岸线不填充陆地,可以不传patch参数:
m_gshhs('h', 'linewidth', 0.6, 'color', [0.2 0.2 0.2]);这里建议根据出图比例尺灵活选择分辨率。画整个南海,high级完全够用,但如果你缩放到了珠江口甚至某个具体潮汐站周边,就得上full级才能看清湄洲岛这类小岛。一个容易踩的坑是,同一个研究区域如果只用一个分辨率级别,放大之后细节不足,这时候可以换用更高一级的数据重新出图,而不是在低分辨率图上硬抠。
如果还需要叠加河流线,可以加参数:
m_gshhs('h', 'rivers', 'linewidth', 0.5, 'color', 'b');河流和海岸线用的是同一套数据文件里的不同要素,M_Map会自动到gshhg目录里找对应的河流文件。
3.3 绘制地形底图:把ETOPO1喂给M_Map
ETOPO1不能直接用m_contourf画,需要先读取出经纬度网格和地形高程矩阵,再通过M_Map的投影函数绘制。推荐用netCDF方式读取:
fname = 'etopo1/ETOPO1_Ice_g_gmt4.grd'; lon = ncread(fname, 'x'); lat = ncread(fname, 'y'); z = ncread(fname, 'z');读取之后建议先把经度统一到-180到180范围,因为原始数据的经度范围可能是0到360:
lon(lon > 180) = lon(lon > 180) - 360;然后对研究区域做裁剪,避免全量网格进入绘图流程。假设我们要画南海北部区域:
region_lon = [105 125]; region_lat = [0 25]; idx_lon = lon >= region_lon(1) & lon <= region_lon(2); idx_lat = lat >= region_lat(1) & lat <= region_lat(2); LON = meshgrid(lon(idx_lon), lat(idx_lat)); % 注意MATLAB的meshgrid输出维度,需要转置成lat-by-lon矩阵 [LON, LAT] = meshgrid(lon(idx_lon), lat(idx_lat)); Z = z(idx_lat, idx_lon);实际绘图时,可以用m_pcolor配合shading flat绘制色块图,也可以用m_contourf绘制填充等值线。我的经验是,区域小、网格细的时候用m_pcolor效果更细腻,但数据量大的时候m_pcolor会明显卡顿,这时换成m_contourf加等值线级别控制,速度和内存占用都会好很多:
m_proj('mercator', 'long', region_lon, 'lat', region_lat); levels = -8000:200:6000; m_contourf(LON, LAT, Z, levels, 'edgecolor', 'none'); colormap(m_colmap('topo')); colorbar;m_colmap是M_Map自带的色标函数,'topo'模式是蓝绿棕渐变,用来表示从深海到高山很自然。如果没有这个函数,也可以用MATLAB内置的colormap搭配手动设置颜色断点,只是效果需要多调几次。
3.4 一点完整的组合示例
把地形、岸线和观测站位画在同一张图上,是科研出图最常见的需求。下面这个示例画的是南海北部海域,我叠加了ETOPO1地形底图、high级海岸线以及几个模拟站位点:
addpath(genpath('D:\你的路径\m_map_toolbox')); region_lon = [105 125]; region_lat = [0 25]; % 1. 先读ETOPO1并裁剪 fname = 'etopo1/ETOPO1_Ice_g_gmt4.grd'; lon = ncread(fname, 'x'); lat = ncread(fname, 'y'); z = ncread(fname, 'z'); lon(lon > 180) = lon(lon > 180) - 360; idx_lon = lon >= region_lon(1) & lon <= region_lon(2); idx_lat = lat >= region_lat(1) & lat <= region_lat(2); [LON, LAT] = meshgrid(lon(idx_lon), lat(idx_lat)); Z = z(idx_lat, idx_lon); % 2. 初始化投影 m_proj('mercator', 'long', region_lon, 'lat', region_lat); % 3. 画地形底图 levels = -8000:200:6000; m_contourf(LON, LAT, Z, levels, 'edgecolor', 'none'); colormap(m_colmap('topo')); caxis([-5000 3000]); % 4. 画海岸线与河流 m_gshhs('h', 'patch', [0.7 0.7 0.7], 'edgecolor', 'k', 'linewidth', 0.8); m_gshhs('h', 'rivers', 'linewidth', 0.4, 'color', [0.3 0.5 0.9]); % 5. 叠加站位点 sta_lon = [110 112 115 118]; sta_lat = [18 19 20 21]; m_scatter(sta_lon, sta_lat, 50, 'r', 'filled'); % 6. 画网格、边框和色标 m_grid('box', 'fancy', 'tickdir', 'out'); colorbar;这段流程是很多海洋底图的通用模板,把地形、岸线和站位点三要素组合在一起。实际使用时,大家可以替换成自己研究区域的经纬度范围和站位数据。
4. 常见问题与排查技巧实录
4.1 数据文件不识别或直接报错
最常见的报错是:
Cannot open GSHHS file gshhs_f.b出现这个错误,先检查两个地方。第一,gshhs_f.b文件是否真的存在于gshhg目录下;第二,当前工作目录或MATLAB搜索路径是否能找到这个目录。很多朋友下载整合包之后直接双击示例脚本运行,但当前文件夹没切到整合包根目录,导致函数找不到数据。解决办法很简单:把当前目录切到m_map_toolbox,或者在脚本开头用addpath手动添加gshhg目录的路径。
还有一种情况是文件名不匹配。GSHHG数据在更新后可能采用gshhg-gshhs_f.b这种带前缀的命名,而老版本M_Map只认gshhs_f.b。遇到这种情况,把文件改名为M_Map能识别的名字就行,或者检查整合包是否已经做过这一步处理。ETOPO1数据读取报错通常和缺失netCDF支持库有关,MATLAB的ncread依赖底层HDF5库,个别精简版MATLAB需要安装支持包,这种情况比较少见但存在。
4.2 绘图太慢与内存不足怎么缓解
ETOPO1全量数据太大,画全球地形时尤其明显。我这里有一个在实际项目中摸索出来的降载方案:
- 画草稿预览图时,先用粗分辨率,比如Z(1:4:end, 1:4:end),相当于把网格缩小到原来的四分之一,速度能快十倍不止。
- 正式出图前再加载完整分辨率,切换网格密度即可。
- 绘图函数的选择也很关键,m_contourf比m_pcolor更适合大区域,因为它是等值线填充,实际渲染的图形对象数量少得多。
- 海岸线同理,预览时用'intermediate'或者'low'级,最终出图再切回'high'或'full'。
如果遇到MATLAB直接提示内存不足,优先检查是否误把全球Z矩阵整个传给了绘图函数。记得先做裁剪,只保留研究区域的数据,内存占用通常能下降一个数量级。
4.3 岸线错位、地形空白或南北颠倒
地形空白大概率是经度范围没统一。ETOPO1如果是0到360度,而你的研究区域用-180到180度表达,直接索引就会取出一堆空值。先做lon(lon > 180) = lon(lon > 180) - 360这步,再检查研究区域是否跨了本初子午线或180度经线。如果区域跨180度,简单裁剪可能失败,更稳妥的办法是把区域拆成两段分别处理后再拼图。
南北颠倒的问题通常是netCDF数据的lat维度方向与MATLAB索引不一致。GMT格网数据的纬度方向默认从北极向南极排列,也就是lat(1)对应90度,lat(end)对应-90度,直接用idx_lat索引后画出来的地形会上下颠倒。解决办法是读取后手动翻转:
lat = flipud(lat); z = flipud(z);或者在索引前先判断lat(1)和lat(end)的大小,确保边界判断正确。
4.4 常见问题速查表
| 症状 | 可能原因 | 解决办法 |
|---|---|---|
| Cannot open GSHHS file | 数据文件路径未添加或文件名不匹配 | 添加gshhg目录到搜索路径;重命名文件 |
| ETOPO1读取后全是NaN | netCDF文件读取路径错误或文件损坏 | 检查文件路径;查看ncinfo确认变量结构 |
| 地形图空白但岸线正常 | ETOPO1经度范围与研究区域不一致 | 统一到-180到180;检查裁剪索引 |
| 地形黑白条纹交替 | 数据中存在NaN或值域异常 | 检查Z矩阵中的NaN;设置caxis范围 |
| 图画出来南北颠倒 | lat维度方向与预期相反 | 对lat和z做flipud |
| 绘图卡顿明显 | 数据量过大或full级岸线渲染过重 | 降采样、裁剪、先低分辨率预览 |
4.5 岸线和地形的细微偏差问题
ETOPO1数据本身的海岸线定义和GSHHG海岸线并不完全一致,因为ETOPO1的地形网格是平滑后的结果,而GSHHG是矢量岸线,两者的边界在某些海湾会出现几个像素的偏差。我的建议是,出大比例尺图时以GSHHG岸线为准来勾勒陆地轮廓,地形底图只负责颜色表达,两者不要追求绝对重合。如果差异实在明显,可以检查ETOPO1是冰面版本还是基岩版本,在高纬度地区冰面版本的海岸线会更偏向冰架边界,和基岩岸线自然差得远。
5. 实操心得与扩展建议
5.1 我用这个工具包时总结的几条经验
第一条经验是路径管理一定要规范。我习惯把整合包固定放在一个没有中文、没有空格的路径下,所有脚本统一用addpath调用。这样可以避免MATLAB在某些环境下因为中文路径或者空格引起的文件访问异常。
第二条经验是分层出图。先用最低分辨率把整张图的版式、位置、色彩调好,锁定布局后,再切换到高分辨率数据只做局部替换和细节强化,最后导出高分辨率PNG或PDF。这样既保证出图质量,又不会在反复调整配色时耗费大量等待时间。
第三条经验是色标范围要提前想好。地形数据里如果包含马里亚纳海沟这种极深区域,直接用默认色标范围会导致大部分浅水区颜色平淡。我通常先查看数据的分位数分布,再设定caxis,比如南海区域我常常用-5000到3000,把重点放在陆架和岛礁区域。
5.2 还能怎么扩展这套工具
整合包并不只是用来画静态底图,它可以作为很多研究工作的底图基础。比如结合MATLAB的m_line和m_scatter,可以把CTD站位、浮标轨迹、船走航断面全部叠在底图上,做出一张标准的调查站位图。还可以用m_quiver叠加海流矢量,或者用m_contourf叠加温度、盐度平面场,直接生成论文里常见的环境要素分布图。
另一个比较实用的扩展方向是把出图流程封装成函数。比如写一个my_map_base(region, data_path)函数,内部固定执行投影初始化、地形绘制、岸线绘制、网格绘制,这样每次换区域只需要改一行参数,不必重复十几行代码。我在实际项目中就是这样封装的,后面无论是画南海还是画东海的图,调用一个函数就搞定,避免重复劳动和低级错误。
最后想分享一个小技巧:在最终出图之前,先用m_coastline和m_gshhs函数做一次“快速预览”,确认投影参数、区域范围、数据索引都正确之后,再跑完整绘图流程。这一步看起来多花了几十秒,实际能帮你省下大量因为参数错误导致返工的时间。工具包的价值在于开箱即用,但真正顺手,还是要靠在细节上反复磨合。
本文还有配套的精品资源,点击获取