
说起今天这个实践,简直是给我整不会了。起因不是我自己要折腾什么高大上的数据,而是我那不成器的侄子小明,年底要交毕业设计了,他搞了个环境监测的项目,数据收上来那叫一个惨不...
说起今天这个实践,简直是给我整不会了。起因不是我自己要折腾什么高大上的数据,而是我那不成器的侄子小明,年底要交毕业设计了,他搞了个环境监测的项目,数据收上来那叫一个惨不忍睹。
他那项目,简单说就是在一个山头不同位置测了些温度、湿度、气压啥的。他跑过来找我,一屁股坐下,把笔记本往桌上一摔,哭丧着脸说:“叔,你帮我看看,老师说我这数据就是一堆毫无章法的点,让我画成一个看得过去的‘地表曲面’,我用啥软件画都跟狗啃的一样,答辩肯定过不了!”
我一看他那Excel文件,密密麻麻的X、Y、Z三列数据,加起来好几百行。X是经度,Y是纬度,Z就是那个测到的数值(比如温度)。他用Matlab自带的scatter3跑了一下,确实,屏幕上像撒了一把芝麻,根本看不出什么规律,更别提曲面了。
他试了半天,抓耳挠腮,就指着这几十个点直接去连线画图。我心想你这散点图想变曲面图?那不是直接用点连线那么简单,你必须先得把这些散乱的点“插值”到一个规则的网格上去,把那些没测到的地方也估算出个值来,才能画出平滑的面。
我接过电脑,当时我猛地就想起来了,这种把“稀疏散点”变成“连续曲面”的需求,Matlab里最擅长干这活儿的就是那个叫griddata的函数。

这函数名字起得也够直白,就是把数据放到一个网格(grid)上去。我的思路一下就清晰了,这事儿需要分成三步走:
griddata帮你插值,然后用surf函数把结果一画就大功告成了。说干就干,我直接敲起了代码。
我把小明那三列数据扔进了三个变量:X_raw, Y_raw, 和 Z_raw。这些都是原始、混乱的输入点。

第一步:构造网格
为了画曲面,我们不能直接用原始的X和Y,必须先搞一套规则的坐标轴出来。这里就要用到meshgrid这个函数了。我先找了找原始数据里X和Y的最小值和最大值,确定了曲面的范围,然后设置了一个分辨率,比如每隔几个单位取一个点(我设置了100个点,这样画出来的面才够光滑)。
% 简单模拟,实际是读文件
% X_raw = [1 2 3 1 2 3 ...];
% Y_raw = [1 1 1 2 2 2 ...];
% Z_raw = [10 12 15 11 13 16 ...];
% 构造新的规则网格
xi = linspace(min(X_raw), max(X_raw), 100);
yi = linspace(min(Y_raw), max(Y_raw), 100);
[XI, YI] = meshgrid(xi, yi);
这一步做完,我就有了新的、规则的网格坐标XI和YI,现在就缺它们对应的Z值了。
第二步:griddata 插值魔法
关键来了,我们现在要把原始的Z_raw值,按照原始的X_raw和Y_raw位置,估算(插值)出在新的XI和YI网格上的高度值。就是用griddata来干这个脏活累活。
我试了一下默认的插值方法,效果一般般。对于这种不规则的散点,我直接敲了一个参数'v4',这个方法虽然速度慢一点,但是对于这种数据稀疏的区域,它画出来的曲面效果往往更平滑、更漂亮,符合小明那种“地表”数据的展示需求。
% 插值计算,生成网格上的Z值
ZI = griddata(X_raw, Y_raw, Z_raw, XI, YI, 'v4');
这一下,ZI就生成了,它是一个100x100的矩阵,就是我们想要的那个三维曲面的高度数据!
第三步:绘制三维曲面
有了XI, YI, 和ZI这三兄弟,画图就简单了,直接用surf函数,再加点美化的指令,让它看起来高级一点。
figure;
surf(XI, YI, ZI);
title('基于测量散点的环境数据曲面');
xlabel('经度 (X)');
ylabel('纬度 (Y)');
zlabel('测定值 (Z)');
colorbar; % 加个颜色条更专业
代码一跑起来,小明那眼睛都直了!屏幕上立刻出现了一个非常光滑、颜色渐变的三维曲面图。之前那些乱七八糟的散点,现在变成了一张清晰展示数值高低的“地图”,哪个区域值高,哪个区域值低,一目了然。
我对小明说:“看到没,用griddata和surf,把你的散点数据抬到了一个新高度。你下次别再瞎搞plot3了,解决这类问题,思路比努力重要。” 他赶紧把代码拷走,说这下答辩稳了,真是让我松了一口气。
所以说,今天这个实践记录,也算是给大家提个醒:如果你手头有三维散点数据,需要画一个漂亮的曲面来展示趋势,griddata + meshgrid + surf,就是这个组合拳,绝对好使,比你用什么专业GIS软件简单太多了。这就是我今天折腾下来的全部过程,分享给有同样需求的朋友们!