分散数据由一组点组成X
和相应的值V
,这些点的相对位置之间没有结构或顺序。对分散数据进行插值有多种方法。一种广泛使用的方法是对点进行Delaunay三角剖分。
这个例子展示了如何通过对点进行三角化并将顶点提升一个幅度来构造插值曲面V
正交的维度X
.
对于如何应用此方法,有不同的方法。在这个例子中,插值被分解成单独的步骤;通常,整个插值过程是通过一个函数调用来完成的。
在抛物面表面上创建一个分散的数据集。
X = [-1.5 3.2;1.8 - 3.3;-3.7 - 1.5;-1.5 - 1.3;...0.8 - 1.2;3.3 - 1.5;-4.0 - -1.0;-2.3 - -0.7;0 -0.5;2.0 - -1.5;3.7 - -0.8;-3.5 - -2.9;...-0.9 - -3.9;2.0 - -3.5;3.5 - -2.25);V = x(:,1)。^2 + x (:,2).^2;持有在plot3 (X (: 1) X(:, 2), 0(15日1),“* r”)轴([- 4,4,- 4,4,0,25]);网格stem3 (X (: 1), (:, 2), V,“^”,“填满”)举行从视图(322.5,30);
创建一个Delaunay三角剖分,提升顶点,并在查询点计算插值Xq
.
图(“颜色”,“白色”) t = delaunay(X(:,1),X(:,2));持有在trimesh (t) X (: 1), X(:, 2), 0(15日1),...“EdgeColor”,“r”,“FaceColor”,“没有”) defaultFaceColor = [0.6875 0.8750 0.8984];trisurf (t) X (: 1), X (:, 2), V,“FaceColor”,...defaultFaceColor,“FaceAlpha”, 0.9);plot3 (X (: 1) X(:, 2), 0(15日1),“* r”)轴([- 4,4,- 4,4,0,25]);网格plot3 (-2.6, -2.6, 0,‘* b”,“线宽”, 1.6) plot3([-2.6 - -2.6],[-2.6 - -2.6],[0 13.52]”,“- b”,“线宽”, 1.6)从视图(322.5,30);文本(-2.0,-2.6,Xq的,“FontWeight”,“大胆”,...“HorizontalAlignment”,“中心”,“写成BackgroundColor”,“没有”);
此步骤通常涉及遍历三角剖分数据结构,以查找包含查询点的三角形。找到点后,计算值的后续步骤取决于插值方法。您可以计算邻域中最近的点,并使用该点的值(最近邻插值方法)。你也可以计算三角形的三个顶点的值的加权和(线性插值方法)。这些方法和它们的变体包括在文本和参考分散数据插值。
虽然插图强调了2-D插值,但您可以将此技术应用于更高维度。更一般地说,给定一组点X
和相应的值V
,则可以构造该形式的插值函数V = f (x)
.您可以在查询点计算插值Xq
,给予Vq = F(Xq)
.这是一个单值函数;对于任何查询点Xq
的凸包内X
,它将产生独特的价值矢量量化
.假设样本数据尊重这一性质,以产生一个令人满意的插值。
MATLAB®提供两种方法来执行基于三角测量的分散数据插值:
的griddata
函数支持二维分散数金宝app据插补。的griddatan
函数支持N-D离散金宝app数据插值;然而,对于中等到大型的点集,它在高于6-D的维度上是不实用的,因为底层三角剖分所需要的内存呈指数增长。
的scatteredInterpolant
类支持二维和金宝app三维空间的离散数据插值。我们鼓励使用这个类,因为它更有效,并且易于适应更广泛的插值问题。
的griddata
而且griddatan
函数取一组样本点,X
,对应的值,V
,和查询点,Xq
,并返回插值的值,矢量量化
.每个函数的调用语法都类似;主要的区别是2-D和3-Dgriddata
函数让你定义点X
,Y
/X
,Y
,Z
坐标。这两个函数在预定义的网格点位置插入分散的数据;其目的是生成网格化数据,因此得名。插值在实践中更为普遍。你可能想要在点的凸包内的任意位置进行查询。
这个例子展示了如何griddata
函数在一组网格点上插入分散的数据,并使用该网格化数据创建等高线图。
画出海底山
数据集(a)海底山是一座水下的山)。该数据集由一组经度(x
)和纬度(y
)位置,以及相应的海底山
海拔高度(z
)在这些坐标上测量。
负载海底山plot3 (x, y, z,“。”,“markersize”(12)包含“经”) ylabel (“纬度”) zlabel (“脚的深度”网格)在
使用meshgrid
在经纬度平面上创建一组二维网格点,然后使用griddata
在这些点上插入相应的深度。
图(xi, yi) = meshgrid (210.8:0.01:211.8 -48.5:0.01: -47.9);Zi = griddata(x,y,z,xi,yi);冲浪(xi,咦,zi);包含(“经”) ylabel (“纬度”) zlabel (“脚的深度”)
现在数据是网格格式的,计算并绘制等高线。
图[c,h] =等值线(xi,yi,zi);clabel (c、h);包含(“经”) ylabel (“纬度”)
你也可以使用griddata
在数据集的凸包内的任意位置进行插值。例如,坐标(211.3,-48.2)处的深度为:
Zi = griddata(x,y,z, 211.3, -48.2);
基本的三角剖分是在每次griddata
函数被调用。如果使用不同的查询点重复插入相同的数据集,则会影响性能。的scatteredInterpolant
类中描述的使用scatteredInterpolant类插值分散数据在这方面更有效率。
MATLAB软件还提供griddatan
支持更金宝app高维度的插值。调用语法类似于griddata
.
的griddata
函数在需要插值以查找一组预定义格点位置上的值时非常有用。在实践中,插值问题往往比较一般,而scatteredInterpolant
类提供了更大的灵活性。该类具有以下优点:
它生成了一个可以有效查询的插值函数。也就是说,底层三角测量只创建一次,并在后续查询中重用。
插值方法可以独立于三角剖分而改变。
数据点上的值可以独立于三角剖分而改变。
数据点可以增量地添加到现有的插值器中,而无需触发完整的重新计算。数据点也可以有效地删除和移动,前提是编辑的点数量相对于样本点的总数较小。
它提供了外推功能,用于逼近落在凸包之外的点的值。看到外推分散的数据获取更多信息。
scatteredInterpolant
提供以下插值方法:
“最近的”
-最近邻插值,插值曲面不连续。
“线性”
-线性插值(默认),其中插值曲面是连续的C0。
“天然”
-自然邻居插值,其中插值面是C1连续的,除了在样本点。
的scatteredInterpolant
类支持二维和金宝app三维空间的离散数据插值。你可以通过调用来创建插值scatteredInterpolant
以及传递点的位置和相应的值,以及可选的插值和外推方法。看到scatteredInterpolant
类的语法的详细信息,请参阅scatteredInterpolant
.
这个例子展示了如何使用scatteredInterpolant
来插值一个分散的抽样山峰
函数。
创建分散的数据集。
rng默认的;X = -3 + 6。*兰德(250 [2]);V =峰值(X(:,1),X(:,2));
创建插值。
F = scatter interpolant (X,V)
F = scatteredInterpolant with properties: Points: [250x2 double]值:[250x1 double]方法:'linear' ExtrapolationMethod: 'linear'
的点
属性表示数据点的坐标,而值
属性表示关联的值。的方法
属性表示执行插值的插值方法。的ExtrapolationMethod
属性表示查询点落在凸包之外时使用的外推方法。
的属性F
的字段,以同样的方式访问结构体
.例如,使用F.Points
检查数据点的坐标。
求插值值。
scatteredInterpolant
提供插值器的下标求值。它的计算方法与函数相同。你可以计算插值如下。在本例中,查询位置的值由矢量量化
.你可以在一个查询点上计算:
Vq = F([1.5 1.25])
Vq = 1.4838
你也可以传递单独的坐标:
Vq = F(1.5, 1.25)
Vq = 1.4838
你可以在点位置的向量上求值:
Xq = [0.5 0.25;0.75 - 0.35;1.25 - 0.85);Vq = F(Xq)
Vq =3×10.4057 1.2199 2.1639
你可以评估F
在网格点位置并绘制结果。
[Xq,Yq] = meshgrid(-2.5:0.125:2.5);Vq = F(Xq,Yq);冲浪(Xq Yq Vq);包含(“X”,“fontweight”,“b”), ylabel (“Y”,“fontweight”,“b”);zlabel (“值- V”,“fontweight”,“b”);标题(“线性插值法”,“fontweight”,“b”);
修改插补方法。
你可以在飞行中改变插值方法。将方法设置为“最近的”
.
F.Method =“最近的”;
像以前一样重新计算并绘制插值函数。
Vq = F(Xq,Yq);图冲浪(Xq, Yq Vq);包含(“X”,“fontweight”,“b”), ylabel (“Y”,“fontweight”,“b”) zlabel (“值- V”,“fontweight”,“b”)标题(“最近邻插值法”,“fontweight”,“b”);
将插值方法改为自然邻域,重新计算,并绘制结果。
F.Method =“天然”;Vq = F(Xq,Yq);图冲浪(Xq, Yq Vq);包含(“X”,“fontweight”,“b”), ylabel (“Y”,“fontweight”,“b”) zlabel (“值- V”,“fontweight”,“b”)标题(“自然邻居插值法”,“fontweight”,“b”);
替换样本数据位置的值。
您可以更改这些值V
在样本数据位置,X
,在飞行中。这在实践中很有用,因为一些插值问题可能在同一位置有多个值集。例如,假设您想插值一个由位置(x
,y
,z
)和相应的组件化速度向量(Vx
,v
,Vz
).您可以通过将每个速度分量分配给values属性(V
)依次。这具有重要的性能优势,因为它允许您重用相同的内插,而不会每次都产生计算新内插的开销。
下面的步骤展示了如何更改示例中的值。您将使用表达式计算值, .
V = X(:,1).*exp(-X(:,1).^2-X(:,2).^2);F.Values = V;
求插值值并绘制结果。
Vq = F(Xq,Yq);图冲浪(Xq, Yq Vq);包含(“X”,“fontweight”,“b”), ylabel (“Y”,“fontweight”,“b”) zlabel (“值- V”,“fontweight”,“b”)标题(' v = x.*exp(-x.^2-y.^2)的自然邻居插值')
向现有的插值器添加额外的点位置和值。
这将执行有效的更新,而不是使用增强的数据集进行完整的重新计算。
在添加示例数据时,重要的是要同时添加点位置和相应的值。
继续这个例子,创建新的样本点如下所示:
X = -1.5 + 3.*兰特(100,2);V = X(:,1).*exp(-X(:,1).^2-X(:,2).^2);
将新的点和相应的值添加到三角剖分中。
F.Points(end+(1:100),:) = X;F.Values(end+(1:100)) = V;
求出改进后的插值值并绘制结果。
Vq = F(Xq,Yq);图冲浪(Xq, Yq Vq);包含(“X”,“fontweight”,“b”), ylabel (“Y”,“fontweight”,“b”);zlabel (“值- V”,“fontweight”,“b”);
从插值器中删除数据。
您可以增量地从插值器中删除样本数据点。您还可以从插值器中删除数据点和相应的值。这对于去除虚假异常值很有用。
在删除样本数据时,重要的是同时删除点位置和相应的值。
去掉第25点。
F.Points(25,:) = [];F.Values(25) = [];
去掉第5到15点。
F.Points(5:15,:) = [];F.Values(5:15) = [];
保留150点,去掉其余的。
F.Points(150:end,:) = [];F.Values(150:end) = [];
当你评估和绘图时,这会创建一个更粗糙的表面:
Vq = F(Xq,Yq);图冲浪(Xq, Yq Vq);包含(“X”,“fontweight”,“b”), ylabel (“Y”,“fontweight”,“b”);zlabel (“值- V”,“fontweight”,“b”);标题(' v = x.*exp(-x.^2-y.^2)剔除样本点后的插值')
这个例子展示了当每个样本位置的值很复杂时,如何插值分散的数据。
创建示例数据。
rng (“默认”X = -3 + 6*rand([250 2]);V = complex(X(:,1).*X(:,2), X(:,1)。^2 + x (:,2).^2;
创建插值。
F = scatter interpolant (X,V);
创建一个由查询点组成的网格,并在网格点处计算插值。
[Xq,Yq] = meshgrid(-2.5:0.125:2.5);Vq = F(Xq,Yq);
的实分量矢量量化
.
VqReal = real(Vq);图冲浪(Xq, Yq VqReal);包含(“X”);ylabel (“Y”);zlabel (“真实价值- V”);标题(“内插值的实分量”);
的虚分量矢量量化
.
VqImag = imag(Vq);图冲浪(Xq, Yq VqImag);包含(“X”);ylabel (“Y”);zlabel (虚值- V);标题(“内插值的虚分量”);
前几节中的许多说明性示例处理了在光滑表面上采样的点集的插值。此外,这些点的间距相对均匀。例如,点簇之间并没有相对较大的距离。此外,插值在点位置的凸包内得到了很好的评价。
在处理真实世界的插值问题时,数据可能更具挑战性。它可能来自测量设备,可能产生不准确的读数或异常值。底层数据可能不会平滑地变化,值可能会从一个点跳到另一个点。本节将为您提供一些识别和解决分散数据插值问题的指导方针。
您应该预处理包含的示例数据南
值,以删除南
作为该数据的值不能用于插值。如果一个南
删除时,相应的数据值/坐标也应删除,以确保一致性。如果南
值出现在样例数据中,构造函数将在调用时出错。
下面的示例说明如何删除南
年代。
创建一些数据并将一些条目替换为南
:
X =兰特(25,1)*4-2;Y = rand(25,1)*4-2;V = x.²+ y.²;x(5) = NaN;x(10) = NaN;y(12) = NaN;V(14) = NaN;
F = scatter interpolant (x,y,V);
南
S,然后构造插值函数:nan_flags = isnan(x) | isnan(y) | isnan(V);X (nan_flags) = [];Y (nan_flags) = [];V(nan_flags) = [];F = scatter interpolant (x,y,V);
南
值。X =兰特(25,2)*4-2;V = x(:,1)。^2 + x (:,2).^2;X(5,1) = NaN;X(10,1) = NaN;X(12,2) = NaN;V(14) = NaN;
F = scatter interpolant (X,V);
nan_flags = isnan (X (: 1)) | isnan (X (:, 2)) | isnan (V);X(nan_flags,:) = [];V(nan_flags) = [];F = scatter interpolant (X,V);
griddata
而且griddatan
返回南
方法查询凸包外的点时的值“线性”
或“天然”
方法。方法查询相同的点,则可以得到数值结果“最近的”
方法。这是因为与查询点最近的邻居同时存在于凸包内部和外部。
如果你想计算凸包外的近似值,你应该使用scatteredInterpolant
.看到外推分散的数据获取更多信息。
输入数据很少是“完美的”,您的应用程序可能不得不处理重复的数据点位置。数据集中相同位置的两个或多个数据点可以具有不同的对应值。在这种情况下,scatteredInterpolant
合并这些点并计算相应值的平均值。这个例子展示了scatteredInterpolant
在具有重复点的数据集上执行插值。
在平面上创建一些样本数据:
X =兰特(100,1)*6-3;Y = rand(100,1)*6-3;V = x + y;
通过将点50的坐标分配给点100来引入一个重复的点位置:
X (50) = X (100);Y (50) = Y (100);
创建插值。请注意,F
包含99个独特的数据点:
F = scatter interpolant (x,y,V)
检查与第50个点相关的值:
F.Values (50)
这个值是原始第50和第100个值的平均值,因为这两个数据点的位置相同:
(V (50) + V (100)) / 2
在一些插值问题中,多组样本值可能对应于相同的位置。例如,一组值可能在不同时间的相同位置被记录。为了提高效率,您可以插入一组读数,然后替换这些值来插入下一组读数。
在替换存在重复点位置的值时,始终使用一致的数据管理。假设您有两组与100个数据点位置相关的值,并且希望通过替换值来依次插入每组值。
考虑两组值:
V1 = x + 4*y;V2 = 3*x + 5*y
创建插值。scatteredInterpolant
合并重复的位置,插值器包含99个唯一的样本点:
F = scatter interpolant (x,y,V1)
F.Values = V2
意味着给99个样本分配100个值。前一个合并操作的上下文丢失;样本位置的数量与样本值的数量不匹配。插值器需要解决不一致以支持查询。金宝app在这个更复杂的场景中,有必要在创建和编辑插值器之前删除重复项。使用独特的
函数求唯一点的下标。独特的
还可以输出用于标识重复点的索引的参数。
[~, I, ~] = unique([x y],'first','rows');I = sort(I);x = x(I);y = y(I);V1 = V1(i);V2 = V2(i);F = scatter interpolant (x,y,V1)
F
对第一个数据集进行插值。然后您可以替换这些值来插入第二个数据集。F.Values = V2;
scatteredInterpolant
允许您编辑表示样例值的属性(F.Values
)和插值方法(F.Method
).由于这些属性独立于底层三角测量,因此可以有效地执行编辑。但是,与处理大型数组一样,在编辑数据时应该注意不要意外地创建不必要的副本。当多个变量引用一个数组并编辑该数组时,就会进行复制。
在下列情况下不制作副本:
A1 =魔法(4)A1(4,4) = 11
A1
而且A2
一旦编辑完成,不能再共享相同的数据:A1 =魔术(4)A2 = A1 A1(4,4) = 32
scatteredInterpolant
包含数据,它的行为就像一个数组,在MATLAB语言中,它被称为值对象。MATLAB语言的设计目的是在将应用程序结构化为驻留在文件中的函数时提供最佳性能。在命令行上进行原型设计可能无法产生相同级别的性能。
下面的例子演示了这种行为,但应该注意的是,本例中的性能提高不能推广到MATLAB中的其他函数。
这段代码不会产生最佳性能:
X =兰特(1000000,1)*4-2;Y = rand(1000000,1)*4-2;Z = x.*exp(-x.²-y.²);抽搐;F = scatter interpolant (x,y,z);toc抽搐;F.Values = 2*z;toc
当MATLAB执行一个由驻留在文件中的函数组成的程序时,它拥有代码执行的完整图像;这使得MATLAB可以优化性能。当您在命令行中输入代码时,MATLAB无法预测您接下来要输入什么,因此它无法执行相同级别的优化。通过创建可重用函数来开发应用程序是一般和推荐的实践,MATLAB将优化这种设置下的性能。
Delaunay三角剖分非常适合于离散数据插值问题,因为它具有良好的几何性质,可以产生良好的结果。这些属性是:
摈弃银形三角形/四面体,而倾向于更多的等边三角形。
空的圆周属性,它隐式地定义了点之间的最近邻关系。
空的圆周属性确保插值值受到查询位置附近的样本点的影响。尽管有这些特性,在某些情况下,数据点的分布可能会导致较差的结果,这通常发生在样本数据集的凸包附近。当插值产生意想不到的结果时,样本数据的图形和底层三角测量通常可以提供对问题的洞察。
这个例子显示了在边界附近恶化的插值曲面。
创建一个示例数据集,它将显示边界附近的问题。
T = 0.4*pi:0.02:0.6*pi;X1 = cos(t)';Y1 = sint '-1.02;X2 = x1;y = y *(-1);X3 = linspace(-0.3,0.3,16)';Y3 = 0 (16,1);X = [x1;x2;x3];Y = [y1;y2;y3];
现在把这些样本点举到表面上 插值曲面。
Z = x.²+ y.²;F = scatter interpolant (x,y,z);[xi, yi] = meshgrid (-0.3: .02:0.3, -0.0688:0.01:0.0688);zi = F(xi,yi);网格(xi,咦,zi)包含(“X”,“fontweight”,“b”), ylabel (“Y”,“fontweight”,“b”) zlabel (“值- V”,“fontweight”,“b”)标题(插值结果的);
实际曲面为:
Zi = xi。^2 + yi.^2;图网格(xi,yi,zi)实际表面的)
为了理解插值表面在边界附近恶化的原因,查看潜在的三角剖分是有帮助的:
dt = delaunayTriangulation(x,y);图绘制(x, y,“* r”)轴平等的持有在triplot (dt)情节(x1, y1,“- r”)情节(x2, y2,“- r”)标题(三角剖分用于创建插值)举行从
红色边界内的三角形形状相对较好;它们是由接近的点构造的,插值在这个区域工作得很好。在红色边界之外,三角形是银色的,并连接彼此远离的点。没有足够的采样来准确地捕捉表面,所以这些区域的结果很差也就不足为奇了。在3d中,对三角测量的视觉检查会变得有点棘手,但查看点分布通常有助于说明潜在的问题。
MATLAB®4griddata
方法,v4的
,不基于三角剖分,不受边界附近插值曲面退化的影响。
[xi, yi] = meshgrid (-0.3: .02:0.3, -0.0688:0.01:0.0688);Zi = griddata(x,y,z,xi,yi,v4的);网格(xi,咦,zi)包含(“X”,“fontweight”,“b”), ylabel (“Y”,“fontweight”,“b”) zlabel (“值- V”,“fontweight”,“b”)标题(用v4方法从griddata中插值曲面,“fontweight”,“b”);
插值的曲面griddata
使用v4的
方法对应于预期的实际曲面。