动态图例(每次递归更新)

8

我有一个 for i=1:15 的循环。在其中我生成了一个变量 d=1:0.01:10,它是 x 的轴,基于这个轴,我创建了一个连续的函数 F(d),它有两个唯一的变量 pitch 和 yaw。然后,我使用 cmap = hsv(15); 在每次递归中使用不同的颜色进行绘制。

d=1:0.01:10;
cmap = hsv(15);

for i=1:15
    pitch = unidrnd(10);
    yaw   = unidrnd(10);

    for j=1:length(d)
        F(j) = d(j)*3*pitch*yaw; %// some long calculation here
    end

    p1 = plot(d,F,'Linewidth', 1.0);
    title ('blah blah')
    set(p1, 'Color', cmap(i,:));
    hold on;
    legend (['pitch,yaw:', num2str(pitch) num2str(yaw)]) 
end 
hold off;

这段代码每次递归更新唯一的pitch和yaw值(它们之间没有空格,有点令人不舒服),但未能做到以下两点:

  1. 应用正常的颜色,如图所示。
  2. 保留上一次迭代的颜色和pitch,yaw值。

不确定您想要做什么,但在每次迭代结束时使用drawnow可能会很有用。 - Luis Mendo
不幸的是,drawnow 没有任何改变。 - Kots
3个回答

29

半文档化解决方案

使用“动态图例”可以通过循环向图例中添加行,如在undocumentedmatlab.com上所述

其思想是将legend命令替换为:

legend('-DynamicLegend');

然后使用 DisplayName 参数更新 plot 命令:

plot(d,F,'Linewidth',1.0,'DisplayName',sprintf('俯仰,偏航:%d,%d',pitch,yaw));

这样添加到坐标轴的图形会自动添加到图例中:

enter image description here

如果您不喜欢半文档化的功能,请使用“DisplayName”技巧,并简单地切换传说的开/关。也就是说,使用-DynamicLegend,而不是:
legend('off'); legend('show');

一种不使用DisplayName-DynamicLegend的不同变化是使用存储字符串的数组删除并重新创建图例。

官方解决方案

MathWorks推荐的官方解决方案是获取现有图例的线句柄,并手动使用这些句柄更新图例。与上面的动态图例解决方案相比,这相当繁琐:

% Get object handles
[LEGH,OBJH,OUTH,OUTM] = legend;

% Add object with new handle and new legend string to legend
legend([OUTH;p1],OUTM{:},sprintf('pitch,yaw: %d,%d',pitch,yaw))

4
很棒的 .gif 使用! - jerad
这段代码可以改变颜色,但我无法添加所需的数值,而不是单词"data%d"。不过.GIF很好! - Kots
有一个方法可以做到这一点('DisplayName),已更新。 - chappjc
1
太好了。还要注意,在“plot”命令中可以指定颜色:p1=plot(d,F,'Linewidth', 1.0,'DisplayName', sprintf('pitch,yaw: %d,%d',pitch,yaw), 'Color', cmap(i,:)); - chappjc
哇草!我不知道MATLAB有动态图例,.gif 的使用也很赞。 - rayryeng
显示剩余2条评论

1
作为R2014+默认的HG2替代@chappjc官方MW解决方案,人们可以利用图例被重新实现为自己的类而不是其他图形对象的欺骗。这使得事情变得更简单,更容易互动。

尽管这些新的legend对象没有将图例项链接到绘制对象的公开属性,但它们确实具有这样的属性'PlotChildren',它是一个对象句柄数组。

例如:

x = 1:10;
y1 = x;
y2 = x + 1;

figure
plot(x, y1, 'ro', x, y2, 'bs');
lh = legend({'Circle', 'Square'}, 'Location', 'NorthWest');

pc = lh.PlotChildren

返回:
pc = 

  2x1 Line array:

  Line    (Circle)
  Line    (Square)

step1

要更新我们的legend对象而不再调用legend,我们可以修改现有legend对象的'PlotChildren''String'属性。只要在'PlotChildren'中每个对象都有一个'String'条目,它就会在图例中呈现。
例如:
y3 = x + 2;
hold on
plot(x, y3, 'gp');

% To make sure we target the right axes, pull the legend's PlotChildren 
% and get the parent axes object
parentaxes = lh.PlotChildren(1).Parent;

% Get new plot object handles from parent axes
newplothandles = flipud(parentaxes.Children); % Flip so order matches

% Generate new legend string
newlegendstr = [lh.String 'Pentagram'];

% Update legend
lh.PlotChildren = newplothandles;
lh.String = newlegendstr;

这会返回:

yay


这个功能可以封装成一个通用的帮助函数,以支持追加一个或多个图例条目。我们已经在 GitHub 上使用 legtools 进行了封装。

0

从MATLAB 2017a开始, 当添加或删除图形对象时,图例会自动更新。

因此,现在不需要做任何特定的事情。首先创建图例,然后在循环中可以向轴添加线条,它们将自动出现在图例中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接