Update multiple plot fills using XData and YData

I was doing the following to generate n filled areas on a graph between n pairs of upper and lower curves.
for i = 1:n
x = % x values, function of i
y1 = % upper curve, function of i
y2 = % lower curve, function i
fill([x fliplr(x)], [y2 fliplr(y1)]);
hold on
end
However, I need to be able to plot an empty fill, and then add the fills in a loop using XData and YData, like this (I know the following won't work, but schematically)
h = fill(nan, nan, 'r');
for i = 1:n
x = % x values, function of i
y1 = % upper curve, function of i
y2 = % lower curve, function i
h(i).XData = [x fliplr(x)]
h(i).YData = [y2 fliplr(y1)]
end
What's the proper way to do this? My need for this stems from using scrollplots, which doesn't work well with re-plotting the data, but instead you need to update the data of the existing plot if changes are made. Any ideas?

1 Comment

It is not clear, what you want to do. What is "an empty fill"? "Doesn't work well" is no clear description of the problem you have.

Sign in to comment.

Answers (1)

Jan
Jan on 29 Jan 2018
Edited: Jan on 29 Jan 2018
[EDITED] Sorry, I've posted some nonsense code here by accident. Thanks, Walter. I do not remove the answer to keep the valuable comments.

8 Comments

This attempts to set the XData and YData of placeholder objects.
fill() returns patch objects, so you could create empty patch objects. But you could probably just loop that fill(nan,nan) to create distinct patch objects that you could later set the XData and YData for.
Imagine the following scenario:
h1 = plot(data1);
h2 = scatter(data2);
h3 = fill(data3);
scrollplot;
scrollplot will then draw a small, scrollable window under the main plot area that will let you pan and zoom through a plot. But if you change the data and try and re-plot it, as I want to through edit boxes, the changes will get reflected in the mini-scrollable window, not the main plot window itself. Essentially any plot command run after you invoke scrollplot will only plot those changes in the scrollplot window, not the main plot window.
To get around this, you update the data set. So for the scatter plot, I can plot an empty set of data (since the input from the user in the edit box hasn't been entered yet)
p2 = scatter(nan, nan);
scrollplot;
And then in a callback connected to an edit box, I do
p2.XData = newXdata;
p2.YData = newYdata;
And this works great. But I don't know how to make this work with the fill area portion of the plot. I can do it with a single fill area like
p3 = fill(nan, nan);
And then in a callback
p3.XData = [x fliplr(x)]
p3.YData = [y2 fliplr(y1)]
And this works great. But my first code block in the original post creates n filled areas, and I need to replace them all (in a loop) with new data like above when the user changes input data.
Save a vector of the handles of fill(nan,nan) and adjust each with the appropriate data.
If you had a fixed number of plots then another possibility is to use surf() instead of fill(), and put the appropriate variables describing each into the base workspace, and then call refreshdata() . That triggers graphics items that have an XDataSource or YDataSource or ZDataSource to look in the base workspace for updates to the variables used to construct them, and do the appropriate graphics changes. This does not happen to be supported by patch() but is supported by surface objects.
... but in my opinion changing the XData and YData properties directly is cleaner and more flexible.
Would that look like this? (assuming two fills)
p3 = [fill(nan, nan, 'r') fill(nan, nan, 'r')];
for i = 1:2
x = whatever
y1 = curve 1
y2 = curve 2
p3(1, i).XData = [x fliplr(x)];
p3(1, i).YData = [y2 fliplr(y1)];
end
When I try something like this, I get an "Invalid or deleted object." error.
Make sure you "hold on" before that p3 call.
That did the trick. Thanks a ton. How might I generalize that p3 vector from 2 to n?
p3 = [fill(nan, nan, 'r') fill(nan, nan, 'r')];
I tried multiplying fill(nan, nan, 'r') by a 1 x n vector of ones, but that gave me an error concerning the multiplication.
I also tried (with just 3 entries)
(this works)
p3 = [fill(nan, nan, 'r') fill(nan, nan, 'r') fill(nan, nan, 'r')
and
(this doesn't)
p3(1, 1:3) = fill(nan, nan, 'r')
Replacing the x & y data of both attempts in a loop with
p3(1, i).XData = [x fliplr(x)];
p3(1, i).YData = [y2 fliplr(y1)];
Any reason why those two behave differently?
p3(1, 1:3) = fill(nan, nan, 'r') would assign the same patch handle to those elements.
The easiest fix is to loop. But you could use an implicit loop such as
arrayfun(@(~) fill(nan,nan), 1:3)

Sign in to comment.

Products

Tags

Asked:

on 29 Jan 2018

Commented:

on 30 Jan 2018

Community Treasure Hunt

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

Start Hunting!