Shade between curves
Image Analyst
on 6 Nov 2024 at 16:18
It would be nice to have a function to shade between two curves. This is a common question asked on Answers and there are some File Exchange entries on it but it's such a common thing to want to do I think there should be a built in function for it. I'm thinking of something like
plotsWithShading(x1, y1, 'r-', x2, y2, 'b-', 'ShadingColor', [.7, .5, .3], 'Opacity', 0.5);
So we can specify the coordinates of the two curves, and the shading color to be used, and its opacity, and it would shade the region between the two curves where the x ranges overlap. Other options should also be accepted, like line with, line style, markers or not, etc. Perhaps all those options could be put into a structure as fields, like
plotsWithShading(x1, y1, options1, x2, y2, options2, 'ShadingColor', [.7, .5, .3], 'Opacity', 0.5);
the shading options could also (optionally) be a structure. I know it can be done with a series of other functions like patch or fill, but it's kind of tricky and not obvious as we can see from the number of questions about how to do it.
Does anyone else think this would be a convenient function to add?
7 Comments
What would be the expected behavior in these cases below?
figure()
tiledlayout()
nexttile()
th = 0:.01:2*pi;
x = cos(th);
y = sin(th);
plot(x,y,'-b')
hold on
plot([-.2 2], [-2 .2], '-r')
axis padded square
title("Example 1")
nexttile()
plot(th,y,'-k')
hold on
plot(th+7, y+.5, '-b')
title("Example 2")
nexttile()
x = linspace(-5, 5, 100);
y1 = 0.5*x.^2;
plot(x,y1,'-m')
hold on
refline(-1.5,10)
axis padded
title("Example 3")
nexttile()
th = .8:.1:1.8*pi;
x = cos(th);
y = sin(th);
plot(x,y,'-b')
hold on
plot([-2 2], [0 0], 'k-')
title("Example 4")
axis equal
Additional thoughts:
I would recommend that shadeBetweenCurves operate on the entire curves by default. Otherwise, the user should be able to specify the lower and/or upper limits for shading.
The first input should be for the lower curve and the second input for the upper curve. I would expect that inputting the upper and then lower would yield no shading, similar to how 3:1 yields an empty vector.
It would be a good idea to also allow shading in either direction. This would be vertical by default (between x values) but also allowable for horizontal (between y values). Then, this function, or a new one designed similar to this one, could be extended to 3D plots by creating surfaces between curves or volumes between surfaces.
I agree that a built-in function to shade between lines would be very helpful. I also agree that the syntax could be tricky. Perhaps it could operate on handles of already-plotted curves. For example:
h1 = plot(x1, y1, 'r-');
h2 = plot(x2, y2, 'b-');
shadeBetweenCurves(h1, h2, opts);
That way, the plot options for each of the curves would not clutter the function signature for shading between them. And, the opts struct (or name-value pairs) could accommodate the typical patch properties.