在MATLAB中:如何使用不断变化的行数更新XData和YData?

时间:2016-04-01 00:43:39

标签: matlab plot

我正在寻找一种方法,在动态迁移数据(位置与时间)的动态更新图中添加分隔连续日的垂直分界线。部分挑战是这些分隔符的数量随着绘图域扩展以显示更多时间数据而改变:例如,当绘图中的天数从3增加到5时,分隔符的数量增加2。

用MATLAB编写的最小代码示例如下所示:

xcols = [1; 1];
ycols = [0; 1];

figure(4)
clf
h.divs = plot(xcols,ycols,':k');
xlabel('time')
ylabel('location')
for ii=2:6
    xcols(:,end+1) = [ii; ii];
    ycols(:,end+1) = [0; 1];
    % set(h.divs, 'XData', xcols, 'YData', ycols);
    % set(h.divs, {'XData'}, num2cell(xcols',2), {'YData'}, num2cell(ycols',2));
    drawnow
    pause(1)
end

问题集中在已注释掉的两条线上。如果我在第一个中注释尝试用每个新的分频器更新XData和YData(给定为2 x DividerCount矩阵xcols和ycols),那么我收到一个错误,这些输入“必须是数字类型的向量”。如果我在第二行中注释为使用单元格数组来解决此问题(per this Stack Overflow postthis MATLAB Newsgroup post),则代码返回错误“单元数组句柄维度必须与句柄向量长度匹配“一旦分隔线的数量发生变化。

Hacky解决方案当然是可行的。例如,分隔线可以绘制为单线水平和垂直线段,其中水平线段位于图的y轴极限的上方和下方。或者可以使用固定数量的分频器,其中一些分频器绘制在曲线的x轴极限之外。问题在于是否存在非hacky方法 - 可以在循环的每次传递中绘制同一图中可能变化的相同样式的线数。

2 个答案:

答案 0 :(得分:1)

假设我们在开始时

xcols = [1:3; 1:3];
ycols = [0 0 0; 1 1 1];

然后h.divs = plot(xcols,ycols,':k');将创建3个线对象。 使用

set(h.divs,{'XData'},num2cell(xcols',2),{'YData'},num2cell(ycols',2));
size(xcols, 2)>3

将失败,因为这假设有超过3个图形对象来设置值(但numel(h.divs)仍然是3)。 那么我们必须为每个分频器创建一个新的情节吗?

不!,因为如果我们将NaN插入到数据中,我们可以在行中引入间隙。 作为第一次迭代,我们可以使用它:

xcols = [1 1];
ycols = [0 1];

figure(4)
clf
h.divs = plot(xcols,ycols,':k');
for ii=2:6
    xcols(end+(1:3)) = [nan ii ii];
    ycols(end+(1:3)) = [nan 0 1];
    set(h.divs, 'XData', xcols, 'YData', ycols);
    drawnow
    pause(1)
end

从我们绘制的一个分隔符开始,然后我们生成数据向量(一维!),其中一个新值对与旧数据分开nan

这当然会增加循环中的数据向量,这不是很好。相反,如果我们知道会有多少分频器,我们可以预先分配NaN s并仅在循环中填入新数据:

n_div = 6;
xcols = nan(3 * n_div, 1);
ycols = nan(3 * n_div, 1);
figure(4)
clf
h.divs = plot(xcols,ycols,':k');
for ii=1:6
    xcols((ii - 1)*3 + (1:2)) = [ii ii];
    ycols((ii - 1)*3 + (1:2)) = [0 1];
    set(h.divs, 'XData', xcols, 'YData', ycols);
    drawnow
    pause(1)
end

这样做的好处是,我们可以分别指定XDataYData,就像新的句柄语法一样:

h.divs.XData = xcols;
h.divs.YData = cols;

(甚至更好:h.divs.XData((ii - 1)*3 + (1:2)) = [ii ii];),因为长度不会改变。

答案 1 :(得分:0)

您可以从分隔符定义开始:

divider.x=[];
divider.y=[];
divider.counter=0;
h.div=line('xdata',divider.x,'ydata',divider.y,'linestyle',':','color','k');

哪个不会画线,但会设置句柄。

然后,也许在某个循环中,您可以调用:

divider.counter=divider.counter+1;                 % increase the counter
divider.x=[divider.x,nan,divider.counter*[1 1]];   % append X coords of new divider line
divider.y=[divider.y,nan,divider.counter*[0 1]];   % append Y coords of new divider line
set(h.div,'xdata',divider.x,'ydata',divider.y)     % update dividers
drawnow                                            % update figure immediately

这种方法有效,因为NaN值可以传递给line函数但不会被绘制,也不会是来自邻居点的行。