An Efficient way of generating a legend for 'for loops plots'

6 visualizzazioni (ultimi 30 giorni)
Dear all,
I wrote a matlab code to plot various data from a FEM analysis. My problem is creating a legend efficiently. The code uses for loops to plot an different objects multiple times. If i do not specify the objects clearly, the legend function will see thousands of different graphic objects. For this reason my code does something similar to this:
for i = 1 : n
h = plot3(variable(i, 1), variable(i, 2), variable(i, 3));
end
legend(h, 'myvariable')
(the only difference is that h actually stores the information from different lines/data, it is a vector of handles).
The thing i do not like is that i am saving the information about my graphic object multiple time. I have not tested this but i think is clear it will increase the overall plotting time (the amount of data i am plotting can be really large). My solution to this was the following:
h = 0;
for i = 1 : n
if h == 0
h = plot3(variable(i, 1), variable(i, 2), variable(i, 3));
else
plot3(variable(i, 1), variable(i, 2), variable(i, 3));
end
end
legend(h, 'myvariable')
This is likely to work but it will double the length of my code that right now is already 540 lines. Honestly i prefer a compact code, hence my questions: is there any other solution apart from the one I proposed? does anybody have any idea on how i can solve this problem? Am i doing it right?
Thank you!
(PS note: the for loops are necessary, i need to plot line segments which are not connected to each other)
  5 Commenti
Lorenzo Chiaverini
Lorenzo Chiaverini il 31 Mar 2021
Modificato: Lorenzo Chiaverini il 31 Mar 2021
yes, (it is already pretty slow and i was trying to optimise it)
Jan de Jong
Jan de Jong il 31 Mar 2021
One way of avoiding a multitude of line segments you could store the variables into a single vector interleaved with nans.
var1 = randn(6,3);var2 = randn(6,3);
mastervar = [var1;nan(1,3);var2];
plot3(mastervar(:,1),mastervar(:,2),mastervar(:,3))
I do not think storing handle h to your plot will increase the computational burden. It is just a link.

Accedi per commentare.

Risposta accettata

Steven Lord
Steven Lord il 31 Mar 2021
Two suggestions:
1) When you create the graphics object, set its DisplayName property. Then when you want to show the legend, you won't have to specify the names.
x = 0:360;
axis([0 360 -1 1])
hold on
h = gobjects(1, 2);
h(1) = plot(x, sind(x), 'DisplayName', 'sine');
h(2) = plot(x, cosd(x), 'DisplayName', 'cosine');
legend
% or to show just one
legend(h(2))
2) If the lines that you're drawing are all part of the same "thing", rather than creating a lot of small (2 point) line objects you can include NaN values in your data to be plotted to break the line at that point.
figure
x = 1:15;
x(mod(x, 3) == 0) = NaN;
h = plot(x, x)
h =
Line with properties: Color: [0 0.4470 0.7410] LineStyle: '-' LineWidth: 0.5000 Marker: 'none' MarkerSize: 6 MarkerFaceColor: 'none' XData: [1 2 NaN 4 5 NaN 7 8 NaN 10 11 NaN 13 14 NaN] YData: [1 2 NaN 4 5 NaN 7 8 NaN 10 11 NaN 13 14 NaN] ZData: [1×0 double] Show all properties
5 line segments visually, but just one graphics object in memory.
  4 Commenti
Lorenzo Chiaverini
Lorenzo Chiaverini il 1 Apr 2021
I see, that is great. Yes i am adding arrows in a loop, i will try to preallocate the object as you said and see what happens. Thank you!
Lorenzo Chiaverini
Lorenzo Chiaverini il 10 Apr 2021
Just to let everybody interested know, now the plotting time is a way faster, from 200s to about 10. Thank you again.

Accedi per commentare.

Più risposte (0)

Categorie

Scopri di più su Creating, Deleting, and Querying Graphics Objects in Help Center e File Exchange

Prodotti


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by