Here is my answer.
8 CommentsOldest to Newest
Hi Doug, thanks for this interesting video. In your example, the goal appears to be to color 1-D points. What if we need to color actual 2-D line segments, as implied by your blog post title? Is there a simple way to achieve this, or will we have to construct a loop and manually color each line object? Thanks in advance.
This is a good question. You would need to make each segment independently. I was actually going to start with that when I saw the question posted but realized this was pre-built. Seems like next week’s topic is now picked!
Here is a related question on Stack Overflow: http://stackoverflow.com/questions/11855011/plot3-line-color-based-on-value
@Brad: In the matlab file exchange there are at least 2 functions that does that for you. To find them look for cline.
Base MATLAB has always offered colour 3-D plots, based on height, gradient or some other value, out of the box, using the builtin surface, as used in the popular example peaks. For 2-D plots, the only option seems to be scatter which is fine if you want a scatter plot with separate points but no good for a line plot.
Faced with this problem quite some years ago I coded my own solution which used multiple lines for segment of a curve, allowing each line to be a distinct colour. More recently I spotted a very useful trick with this entry “Colored line or scatter plot” on the FEX. surface() will render 2-D lines, as a special case of 3-D, but you must pass into matrix valued data to make it work, so you have to duplicate the vector:
%% Some Data x = linspace(0, 2*pi)'; y = sin(x); plot(x, y); % a basic monochrome plot %% Trick surface into a 2-D plot surface('XData', [x x], ... % N.B. XYZC Data must have at least 2 cols 'YData', [y y], ... 'ZData', zeros(numel(x),2), ... 'CData', [y y], ... 'FaceColor', 'none', ... 'EdgeColor', 'interp', ... 'Marker', 'none');
Coloring a line is more than slightly misleading here. You use scatter, which creates a separate patch object for each data point (until 2014a). That is horrible for anything more than “a few” elements.
I have requested to have CData property for line objects quite a few times since maybe1995. Since it still has not happened I have also used surface to act as a line. color_line in file exchange.
I mostly used that terminology because the people looking for something like this would not be googling for patch object, they would be googling for words in my title. I agree, this does not scale to big sizes well, but for the right situations, this is a decent solution.
Thank you. I have looked for something like your surface trick for a long time. That works well, is fast and tolerates NaNs in the Cdata. For a case with N points and N-1 segments between them, I modified it to, e.g., [x(1:(end – 1)) x(2:end)] for Xdata, which also works.