I've been thinking how I could update in Matlab the legend of my plots as the for goes on, basically, I have a for
which creates a graph that is added to the plot
(using hold on
) in every iteration, I'd like to update the legend of the aforementioned plot.
This is how I've done it:
clear all; close all; clc;
x0 = 10;
t = linspace(0, 2, 100);
v0 = 0;
g = [10:10:100];
str = [];
hold on
for i = 1:length(g)
x = x0 v0*t - 1/2*g(i)*t.^2;
v = v0 - g(i)*t;
plot(t, x)
axis([0, 2, -200, 10]);
str = [str, sprintf("g = %d", g(i))];
legend(str, 'Location','southwest');
pause(0.3);
end
hold off
i.e. using that size-changing string str. I have a feeling that there is a better and more performant way of doing this but I don't know how else to approach the problem.
CodePudding user response:
An improvement would be to update the String
property of the legend, instead of creating a new legend in each iteration. This "update instead of re-create" idea is common practice for graphical objects that change with time, and results in faster execution. In your example code this will hardly have any impact, but it still looks like a cleaner approach:
clear all; close all; clc;
x0 = 10;
t = linspace(0, 2, 100);
v0 = 0;
g = [10:10:100];
str = [];
le = legend(str, 'Location','southwest'); %%% new: create empty legend
hold on
for i = 1:length(g)
x = x0 v0*t - 1/2*g(i)*t.^2;
v = v0 - g(i)*t;
plot(t, x)
axis([0, 2, -200, 10]);
str = [str, sprintf("g = %d", g(i))];
le.String = str; %%% changed: update String property of the legend
pause(0.3);
end
hold off
Alternatively, you can avoid storing str
, and directly append the new part to the legend. Again, the main reason for this is that the code arguably looks cleaner, as you avoid keeping the same information in two places (the variable and the graphical object):
clear all; close all; clc;
x0 = 10;
t = linspace(0, 2, 100);
v0 = 0;
g = [10:10:100];
% str = []; %%% removed
le = legend(str, 'Location','southwest'); %%% new: create empty legend
hold on
for i = 1:length(g)
x = x0 v0*t - 1/2*g(i)*t.^2;
v = v0 - g(i)*t;
plot(t, x)
axis([0, 2, -200, 10]);
% str = [str, sprintf("g = %d", g(i))]; %%% removed
le.String = [le.String sprintf("g = %d", g(i))]; %%% changed: append new string
pause(0.5);
end
hold off
As a side note, speaking of performance, you may want to replace clear all
by clear
; see relevant links: 1, 2, 3.
CodePudding user response:
Use DisplayName
in the plot
function, and toggle AutoUpdate
in legend
. This is my attempt of your for-loop:
for i = 1:length(g)
x = x0 v0*t - 1/2*g(i)*t.^2;
v = v0 - g(i)*t;
plot(t, x,'DisplayName',sprintf("g = %d", g(i)));
axis([0, 2, -200, 10]);
% str = [str, sprintf("g = %d", g(i))];
% legend(str, 'Location','southwest');
legend('Location','southwest','AutoUpdate',1);
pause(0.3);
end