将线数据插值到网格matlab

时间:2015-09-01 18:21:43

标签: matlab line interpolation

我有一个由5列组成的矩阵,第一列和第二列用于x_start&该行的y_start,第三个和第四个用于x_end& y_end第五个是 - 该行污染物的浓度 -
例如:

%  x_start  y_start  x_end   y_end concentration
frac= [0         0      1       1     0.3
       1         1      3       3     0.6
       3         3      10      2     1.2
       3         3      10      8     0.5];

如果我假设我有一个感兴趣的域10mx10m并且该域被有限差分单元大小1mx1m除(即域是10个单元格10个单元格)
我想插入上面提到的线值,使每个单元格与某条线相交,可以取线的浓度值

这是一个例子:
a link http://www14.0zz0.com/2015/09/01/21/201797784.jpg
用于离散化域的原理图预览
该线具有浓度值,交叉单元应采用相同的值

我知道matlab中的这些函数可以做到这一点但不幸的是对于分散的点,例如

   interp2 & griddata

我为这个问题尝试了一个小代码,但它仍然会出错,而interp2函数是为散点插值而设计的(点不是直线)

   [X,Y] = meshgrid(0:10);
   conc=interp2(frac(:,1),frac(:,2),frac(:,5),X,Y); 

1 个答案:

答案 0 :(得分:1)

我将展示一个较小域名的示例。这将允许显示中间矩阵,有助于理解代码正在做什么。但是,如果需要,代码可以完全扩展到更大的域,甚至可以扩展到曲线而不是行。

首先我需要定义域限制然后我创建一个网格。

%% // Domain Parameters
domainProps.Xlim = [0 5] ; 
domainProps.Ylim = [0 5] ;
domainProps.nCellX = 5 ;       %// number of cells into the domain (X axis)
domainProps.nCellY = 5 ;       %// number of cells nito the domain (Y axis)

xd = linspace( domainProps.Xlim(1) , domainProps.Xlim(2) , domainProps.nCellX+1 ) ;
yd = linspace( domainProps.Ylim(1) , domainProps.Ylim(2) , domainProps.nCellY+1 ) ;
[Xq,Yq,Zq] = meshgrid( xd, yd, 0 ) ;

到目前为止,没有什么太奇特了。然后我将定义一个任意行(你必须从 frac 中获取行坐标。

然后我使用interp1重新插入Y网格上的线的X值,使点与Y网格线相交。

%% // example for first line
xl1 = [0 5] ;      %// X for line 1 - take these data from your table "frac"
yl1 = [1 3.8] ;    %// Y for line 1 - take these data from your table "frac"

%// reinterp the Y values over the X-Grid defining the domain
yi1 = interp1( xl1 , yl1 , xd ) ;

所以到目前为止我们有:

%% // display what we've got so far
figure ; grid on ; hold on
hp = plot(xl1,yl1) ;
hpi = plot(xd , yi1,'or')
set(gca,'Xlim',domainProps.Xlim,'YLim',domainProps.Ylim,'XTick',xd,'YTick',yd)

linegrid1

现在来了有趣的部分。您会注意到,对于每个由红色圆圈突出显示的点,我应该照亮右侧上的网格块和左侧的网格块(当然,除了域边界外)。因此,我所要做的就是找到域的哪些网格线 segments 与您的线相交。这可以通过比较网格点的Y坐标(我们在上面定义的矩阵Yq中)和与它们相交的线的Y坐标来轻松完成(这是yi1 )。所以我们走了:

%// find the elements of the grid lower or equal to the corresponding value of yi
Z = bsxfun(@le,Yq,yi1) ;
%// keep only the "boundary" values (between "0" and "1" domains)
Z(1:end-1,:) = xor( Z(1:end-1,:) , Z(2:end,:) ) ;
%// now replicate the pattern to the left (because each point at
%// intersection must illuminate both block on the left and on the right
Z(:,1:end-1) = Z(:,1:end-1) | Z(:,2:end) ;

*答案的最后将给出这里发生的事情的细节。

现在您有一个逻辑矩阵Z,即您的域的大小,其中包含1true),用于该行遍历的每个块,以及0false)其他地方。
因此,分配您的浓度现在很容易,只需将Z乘以所需的浓度值即可完成:

%% // Assign value to block traversed by the line
conc = Z .* 0.8 ;           %// use the concentration value from your table
figure
hpc = pcolor(Xq,Yq,conc) ;  %// plot the domain with the illuminated blocks

%% // cosmetic changes
set(hpc,'EdgeColor',[0.5 0.5 0.5] )
caxis([0 1])
colorbar
hold on
hpp = plot(xl1,yl1,':k','LineWidth',2) ;
hpi = plot(xd , yi1,'or')

et voila:

linegrid2

正如我之前所说,这是完全可扩展的。它适用于更大的域大小......至于不那么直线: examples

说明:

(域名大小为5个区块)

>> Z = bsxfun(@le,Yq,yi1)
Z =
     1     1     1     1     1     1
     1     1     1     1     1     1
     0     0     1     1     1     1
     0     0     0     0     1     1
     0     0     0     0     0     0
     0     0     0     0     0     0

但是matlab坐标系统是从上到下,而矩阵索引是从上到下,所以为了像你看到的那样表示矩阵值,我垂直翻转矩阵(仅用于显示,不要在真实的计算)。 所以:

>> flipud( Z )
ans =
     0     0     0     0     0     0
     0     0     0     0     0     0
     0     0     0     0     1     1
     0     0     1     1     1     1
     1     1     1     1     1     1
     1     1     1     1     1     1

所有这些ones表示域下面或遍历的域的块。不幸的是,我只想要“遍历”的,而不是下面的那个,所以我必须只保留10之间的接口。这是通过将矩阵移动一行并应用xor过滤器(同样,实际上不使用flipud)来完成的:

>> Z(1:end-1,:) = xor( Z(1:end-1,:) , Z(2:end,:) ) ;
>> flipud(Z)
ans =
     0     0     0     0     0     0
     0     0     0     0     0     0
     0     0     0     0     1     1
     0     0     1     1     0     0
     1     1     0     0     0     0
     0     0     0     0     0     0

由于我们在上面说过,每个交叉点的左侧都必须突出显示,我们还会将模式复制到左侧一列:

>> Z(:,1:end-1) = Z(:,1:end-1) | Z(:,2:end) ;
>> flipud(Z)
ans =
     0     0     0     0     0     0
     0     0     0     0     0     0
     0     0     0     1     1     1
     0     1     1     1     0     0
     1     1     0     0     0     0
     0     0     0     0     0     0

我们完成了:-)。乘以你想要的值,只有突出显示的单元格会有一个值,其余的将保持为0。

重要提示:

到目前为止,我只使用Y个交叉点。它工作得非常好,因为Y渐变是平滑的(线条具有<45度的角度,它总是比X块更多Y块。 如果你的线斜率是> 45度,最好使用相同的方法但是反转轴(重新插入你的线,例如你在X网格交叉点获得xi1值(Y),与Xq而不是Yq进行比较。 如果你的曲线同时具有垂直水平渐变(例如,如果我放大幅度,就像上面的正弦波一样),那么你将不得不使用两种方法(超过X并超过Y),然后将生成的Z合并为一个(类似Z= Zx | Zy)。