Streaks while using color indexing with fill

2 views (last 30 days)
I am trying to fill the area between two curves with a color that depends on a value at each point along one of the curves, but I am getting variations in color that should not be there. I have two (100x1) vectors: y1 and y2 which I plot against a third vector x (also 100x1) such that every point in y2 is directly above (or below or at the same location as) a point on y1. I have a fourth vector v that is the same length as x, y1, and y2, which I would like to use as a color index to fill the area between the curves defined by (x,y1) and (x,y2). (The datasets are attached below, for reference.) The command fill needs a closed loop to define the area to be filled, so I have created vectors X and Y to form the loop:
X=[x;flipud(x)];
Y=[y1;flipud(y2)];
If I type
fill(X,Y,'b')
the area between y1 and y2 will be filled in with blue. I want to fill this area with colors defined by the third variable, so I created C to serve as the color index (per the helpfile on fill):
C=[v;flipud(v)];
fill(X,Y,C)
I therefore expect the area between y1 and y2 to be filled with a color that varies horizontally (from one x value to the next), but not vertically, since each value of C corresponds to a single value in X. I get substantial vertical variation, however:
The command fill works as described in the documentation when I do not use a color index, so I believe that I am using it correctly. I have verified that the color index C has the same value at both the upper and lower points in x, since that would account for at least some variation in C between the curves at the same x position. There was no error in the color index, and it would not account for the degree of value variation in any event.
Is this a known issue while working with fill? Does anyone have suggestions as to 1) why this is happening and/or 2) how I can fix it?
  1 Comment
Sarah
Sarah on 16 Feb 2016
Here's the dataset I have been using-- I thought I had attached it to my original question.

Sign in to comment.

Accepted Answer

Sarah
Sarah on 7 Mar 2016
Edited: Sarah on 7 Mar 2016
I solved this two ways: The 'quick and dirty' way, which involved plotting the transpose of my data so that the interpolation looked reasonable (even though the underlying problem was still present--see the discussion below for details), and using rotated text arrow annotations (because textboxes are not rotatable) in conjunction with getframe() to save the figure as it appeared before rotating. (This is fiddly to set up, since you have to manually set the position of the axis and tick labels. It's neither particularly quick nor particularly imprecise, but it's a faster-running fix than the next one.)
And the technically more-correct method, where I selected each consecutive pair of x locations on each curve (so, four points: two each on the upper and lower curves) to form a trapezoid, then filled the trapezoid with the value in the upper left corner (I could have done a simple arithmetic mean of the values or any other combination you could name, but applied the KISS principle instead). This was slower to run, but (surprisingly) faster to set up. It also has the advantage of being able to represent three variables in RGB space (e.g., concentrations in a three-part solution).
All of which will hopefully become obsolete as the older versions of MATLAB are used less and less.
  1 Comment
Mike Garrity
Mike Garrity on 7 Mar 2016
Glad you found a solution.
The breaking it into trapezoids is an instance of the meshing approach that I mentioned in that blog post. If your trapezoids are small enough, you could probably use FaceColor = 'interp' with them.
The "faster to setup" part is probably due to the fact that you know more about the polygon than the patch object does. When it triangulates the patch, it's using a very general purpose triangulation algorithm. A more tailored algorithm, like the one you're using, can often be faster.
I'm not sure what the "slower to run" part is though. Perhaps you're creating lots of separate patch objects? If so, you could probably combine them into a single patch as I show in the cylinder example in this blog post.

Sign in to comment.

More Answers (1)

Star Strider
Star Strider on 16 Feb 2016
I don’t have your data, but from my experience with fill, patch, and their friends, you may want to horizontally concatenate these rather than vertically concatenate them:
X=[x flipud(x)];
Y=[y1 flipud(y2)];
  9 Comments
Sarah
Sarah on 17 Feb 2016
Edited: Sarah on 17 Feb 2016
Thank you so much for your (detailed!) solution! I am working on implementing it now, but I wanted to put it out there that it likely (as you said) an issue with R2014a-- I borrowed a computer running R2015a last night, and it produced a map that had no (or seemingly no) vertical color variation in the fill. I saved it as a .fig file and opened it on my own computer, only to see that the streaks had reappeared. It could be random luck, but it's certainly suggestive of changes in the code of fill (or patch).
Mike Garrity
Mike Garrity on 17 Feb 2016
Those two versions use different polygon triangulators, so the way they subdivide the polygon can be completely different.
But, I would caution against considering it a "fix". It's the sort of thing that can cause you a lot of heartburn. Cases where results appear reasonable, but aren't accurate can be even more dangerous than cases where you clearly get a wrong answer. In release R2014b, we strongly considered making patch error out if the color data wasn't a linear function of the coordinates, so that users would no they were in danger, but there were complaints about it erroring in cases where it "seemed to work".

Sign in to comment.

Products

Community Treasure Hunt

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

Start Hunting!