Attempting to plot one line with multiple colors

74 ビュー (過去 30 日間)
Jbo
Jbo 2016 年 11 月 17 日
コメント済み: Lukas Klar 2025 年 4 月 24 日
Ok, I have looked high and low, and for the life of me I cannot find the answer. If this has already been answered please forgive me.
What I am attempting to do is plot a line with a vector of color data. I.E. plot(x, y, colorVector).
There appears to be a way to trick Mesh or such, but that's computationally slow. I've used a loop method, that plots 2 points of x and y at a time, but that eats up a lot of CPU in overhead to plot (or, I believe it does. Either way it's a lot of computational time). You can use the set call, but because of how the plotting engine works, that results in having to either wait, or drawnow which uses a lot of CPU cycles.
Is there any way that I can do like a plot(x, y, 'color', colorData) ?
Thanks!

採用された回答

Walter Roberson
Walter Roberson 2016 年 11 月 17 日
No. Line objects, and Chart Line objects, and world Primitive Chart Line Objects, all have the restriction that any one line object can only be a single color.
  2 件のコメント
Jbo
Jbo 2016 年 11 月 18 日
編集済み: Walter Roberson 2016 年 11 月 18 日
We can plot multiple lines at a time. Is there a way I could build a cell array or something like:
plotArgs{i}={X(i:i+1), Y(i:i+1),'color', colorVector(i)}
When I try to do this, it works doing plot(plotArgs{1}), but plot(plotArgs{:}) throws an error.
Walter Roberson
Walter Roberson 2016 年 11 月 18 日
Only one 'color' option will be paid attention to for plot() . You can use multiple linespec, but linespec are restricted to the color names, 'b' (blue), 'c' (cyan), 'g' (green), 'k' (black), 'm' (magenta), 'r' (red), 'w' (white) . If your colorVector is a character vector containing those codes then you could
for i = 1 : length(X)-1
plotArgs{i}={X(i:i+1), Y(i:i+1), colorVector(i)};
end
plot(plotArgs{:})
This would be equivalent to
for i = 1 : length(X) - 1
line('XData', X(i:i+1), 'YData', Y(i:i+1), 'Color', colorVector(i));
end
as plot() loops calling line(). But the line() version can be extended,
for i = 1 : length(X) - 1
line('XData', X(i:i+1), 'YData', Y(i:i+1), 'Color', colorVector(i, :));
end
and now colorVector can be a RGB table, one color triple per row.

サインインしてコメントする。

その他の回答 (1 件)

Lukas Klar
Lukas Klar 2023 年 8 月 9 日
編集済み: Lukas Klar 2025 年 4 月 23 日
I struggled with this one 7 years later. Here is my solution: Specify the color in a colormap and use patch with EdgeColor='flat' to plot.
x = 0:10;
y = x.^2;
% specify colors
mycolormap = [1 0 0;...
0 1 0;...
0 0 1];
% assign colors to points, make sure to use all specified colors
c = [1 2 3 2 3 1 1 3 2 1 3];
% add a NaN to the end to avoid closing of the patch
x = [x NaN];
y = [y NaN];
c = [c NaN];
% plot as patch with EdgeColor='flat'
figure
patch(x, y, c, EdgeColor='flat', Marker='.', LineWidth=2, MarkerSize=20)
colormap(mycolormap)
I my case the best solution was to make smooth transition with EdgeColor='interp'
% use EdgeColor='interp' and a smooth colormap
figure
patch(x, y, c, EdgeColor='interp', Marker='.', LineWidth=2, MarkerSize=20)
colormap('cool')
I found no perfect solution to add a legend, I couldn't find a way to alter the line in the legend. But you can paint over it. Disadvantage: it does not correctly scale if the figure is rescaled.
% store figure handle to scale at least with the initial figure size
fh = figure;
% create an empty line because the patch legend is kind of bulky
plot(nan)
hold on
% plot the real multi color line
patch(x, y, c, EdgeColor='interp', Marker='.', LineWidth=2, MarkerSize=20)
colormap('cool')
% add the legend and store its handle
lh = legend('multicolorline', Location='northwest');
% create an invisible axis on the complete figure
annotationAxes = axes(Position=[0, 0, 1, 1], Visible='off', HitTest='off');
annotationAxes.XLim = [0 1];
annotationAxes.YLim = [0 1];
% find the location of the legend line
xpatch = [0.01, 42 / fh.Position(3)] + lh.Position(1); % why 42? Because it's the correct answer
ypatch = [0, 0] + lh.Position(2) + lh.Position(4) / 2; % vertical center of the legend
% paint a multicolor line over the single color line of the legend
patch(xpatch, ypatch, [1 2], EdgeColor='interp', Marker='.', LineWidth=2, MarkerSize=20)
@Alan Hoskins I hope that does the trick for you. If you have multiple lines in the legend you have to tinker with the ypatch variable
  2 件のコメント
Alan Hoskins
Alan Hoskins 2025 年 4 月 17 日
Nice solution. Now is there away to make a gradient line in the legend?
Lukas Klar
Lukas Klar 2025 年 4 月 24 日
Thanks Alan! I updated my post above.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeOrange についてさらに検索

タグ

Community Treasure Hunt

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

Start Hunting!

Translated by