假设我想用新数据更新绘图。我应该选择什么方法?
- 将
XDataSource
属性设置为某个名称,更新变量,然后调用refreshdata
- 擦除原来的
plot
,然后再次调用plot
命令。 - 采用
Set('Xdata',...')
假设我想用新数据更新绘图。我应该选择什么方法?
XDataSource
属性设置为某个名称,更新变量,然后调用refreshdata
plot
,然后再次调用plot
命令。Set('Xdata',...')
简短的回答:总是使用 Set('Xdata',...')
.
示例代码:
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
set(h,'XData',x,'YData',y);
end
长答案:
应该通过三种相关措施来选择最佳方法。
现在,让我们分析可能的方法。
方法(1)——刷新数据
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
refreshdata(h,'caller');
end
M-lint 立即在该行发出警告y=sin(x.^3)
The value assigned to variable `y` might be unused
为什么会这样? refreshdata
使用eval
并且m-lint
不知道您将使用y
. 有人阅读您的代码,不妨完全删除此行。发生这种情况是因为您违反了封装原则。refreshdata
从调用者工作区访问变量。另一种看待这个的方法,假设您将绘图的句柄传递给另一个函数。读者不知道你到底写了y = sin(x.^3);
什么,又和剧情更新有什么关系。
现在让我们讨论速度/运行时间。通过查看refreshdata
源代码,您会注意到两个丑陋的 for 循环,它们遍历您空间中的所有图形句柄变量。这是第一个:
% gather up all the objects to refresh
objs = {};
for k = 1:length(h)
obj = h(k);
objfields = fields(obj);
for k2 = 1:length(objfields)
% search for properties ending in DataSource
if strncmpi(fliplr(objfields{k2}),'ecruoSataD',10)
objs = {objs{:},obj, objfields{k2}};
end
end
end
想象一下,您没有一个地块,而是 100 个地块,并且您只想更新第一个地块。这将非常慢,因为对于每个地块,您都试图找到您需要的地块!(我将作为练习离开,让读者弄清楚什么是ecruoSataD
,以及如何使用它。)
即使您将相关情节作为论据,您仍然有第二个循环,该循环运行eval
多次。不完全有效。最后我会展示一个时间比较。
结论:难以理解、难以重构、运行缓慢
方法(2) - 删除并重新绘制
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
delete(h);
h = plot(x,y);
end
这种方法对读者来说是很清楚的。您删除了情节,并绘制了一个新情节。但是,正如我们将在最后的时间比较中看到的那样,这是最慢的方法。
结论:易于理解,易于重构,运行时非常慢
方法(3) - set('XData',...,'YData')
代码真的很清楚。您想修改绘图的两个属性,XData
并且YData
. 这正是你所做的。此外,代码运行得非常快,从下面的比较中可以看出。
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
set(h,'XData',x,'YData',y);
end
由于新的图形引擎 hg2(R2014b 及更高版本),如果您更喜欢这种表示法,您还可以使用属性语法来指定数据:
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
h.XData = x;
h.YData = y;
end
结论:易于理解、易于重构、运行速度快
这是时间比较代码
function PlotUpdateTimeCompare()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
tic
for i=1:100
refreshdata(h,'caller');
end
toc
tic
for i=1:100
delete(h);
h = plot(x,y);
end
toc
tic
for i=1:100
set(h,'XData',x,'YData',y);
end
toc
end
结果:
经过的时间是 0.075515 秒。
经过的时间是 0.179954 秒。
经过的时间是 0.002820 秒。
您可以调用该函数drawnow
并执行以下操作:
h = plot(nan);
for i = 1:n
y = ...
set(h,'YData',y);
drawnow %update the graph
end
假设我想用新数据更新绘图。我应该选择什么方法?
如果给定轴中有多个线对象,则方法:
- 将 XDataSource 属性设置为某个名称,更新变量,然后调用
refreshdata
将在 MATLAB R2012b 中生成错误。安德烈的回答中提供了一个适当的例子。
一个错误已提交给 Mathworks。