当我添加新输入时,如何使以前的输入在 Matlab 图中逐渐淡出
How to make previous inputs progressively fade out in a Matlab plot when I add new inputs
假设我有这个非常简单的循环
for i=1:10
[xO, yO, xA, yA, xB, yB, xC, yC] = DoSomething(i);
line([xO,xA,xB,xC],[yO,yA,yB,yC]);
pause(0.1);
end
我正在绘制的坐标对应于多体系统的关节,我正在模拟它们随时间的位置(请在此处查看绘图示例):
由于某些链接以周期性方式移动,因此很难直观地跟踪移动。出于这个原因,现在出现了一个问题:如何以一种方式绘制线条,当绘制新线条时,先前的线条会逐渐消失?换句话说,这样我就有了从最近绘制的数据(最不透明)到最旧的数据(越来越透明直到完全消失)的梯度。
这样当一条新线画在与非常旧的数据相同的位置时,我会注意到它是一条新线。
您可以通过修改过去几行的第 4 个 Color
属性来做到这一点。
这是生成的 gif 演示演示,其中我将每帧的透明度淡出 10%,因此只有最近的 10 行可见。
代码如下,详见我的评论:
% Set up some demo values for plotting around a circle
a = 0:0.1:2*pi; n = numel(a);
[x,y] = pol2cart( a, ones(1,n) );
% Initialise the figure, set up axes etc
f = figure(1); clf; xlim([-1,1]); ylim([-1,1]);
% Array of graphics objects to store the lines. Could use a cell array.
lines = gobjects( 1, n );
% "Buffer" size, number of historic lines to keep, and governs the
% corresponding fade increments.
nFade = 10;
% Main plotting loop
for ii = 1:n
% Plot the line
lines(ii) = line( [0,x(ii)], [0,y(ii)] );
% Loop over past lines.
% Note that we only need to go back as far as ii-nFade, earlier lines
% will already by transparent with this method!
for ip = max(1,ii-nFade):ii
% Set the 4th Color attribute value (the alpha) as a percentage
% from the current index. Could do this various ways.
lines(ip).Color(4) = max( 0, 1 - (ii-ip)/nFade );
end
% Delay for animation
pause(0.1);
end
如果线路很多,您可能需要进行一些 plot/memory 管理。您可以通过添加类似
的内容来删除透明线
if lines(ii).Color(4) < 0.01
delete(lines(ii));
end
循环内。这样你的身材就不会有大量的透明残留物。
备注:
- 我生成了实际的 gif using
imwrite
以防你也感兴趣。
- 显然第 4 种颜色值 'feature' 已在 R2018b 中贬值(不确定是否有正式记录)。
获得足够的赞成票来激励制作一个更有趣的演示...
Matlab 2018a 或更高版本(或更早,至少晚于 2012a)的解决方案
由于 Matlab 2018a 不再支持作为 alpha 值的第四个颜色参数(并且显然从来没有像 Cris Luengo 指出的那样支持),这里是使用 patchline
函数在 Matlab 2018a 中工作的解决方案来自文件交换(归功于 Brett Shoelson)。
% init the figure
figure(); axes();
hold on; xlim([-1 0.5]); ylim([0 1]);
% set fraction of alpha value to take
alpha_fraction = 0.7;
n_iterations = 200;
% looping variable to prevent deleting and calling already deleted lines
% i.e. to keep track of which lines are already deleted
delete_from = 1;
for i=1:n_iterations
% your x, y data
[x, y] = doSomething(i);
% create line with transparency using patchline
p(i) = patchline(x,y, 'linewidth', 1, 'edgecolor', 'k');
% set alpha of line to fraction of previous alpha value
% only do when first line is already plotted
if i > 1
% loop over all the previous created lines up till this iteration
% when it still exists (delete from that index)
for j = delete_from:i-1
% Update the alpha to be a fraction of the previous alpha value
p(j).EdgeAlpha = p(j).EdgeAlpha*alpha_fraction;
% delete barely visible lines
if p(j).EdgeAlpha < 0.01 && delete_from > j
delete(p(j));
% exclude deleted line from loop, so edgealpha is not
% called again
delete_from = j;
end
end
end
% pause and behold your mechanism
pause(0.1);
end
我按照@Wolfie 的建议(我自己的,可能不太优雅的实现)包括了删除几乎不可见的行
这里是快速释放机制的演示:
我正在添加第二个答案以明确区分两种完全不同的方法。我的 对线条使用未记录(并且从 2018b 开始,已折旧)的透明度选项。
这个答案提供了一种不同的画线方法,没有兼容性问题(这两个 'features' 可以独立实现):
- 创建固定的
n
行并更新它们的位置,而不是创建越来越多的行。
- 重新给线条着色,淡化为白色,而不是改变透明度。
代码如下,详见评论:
% "Buffer" size, number of historic lines to keep, and governs the
% corresponding fade increments.
nFade = 100;
% Set up some demo values for plotting around a circle
dt = 0.05; a = 0:dt:2*pi+(dt*nFade); n = numel(a); b = a.*4;
[x1,y1] = pol2cart( a, ones(1,n) ); [x2,y2] = pol2cart( b, 0.4*ones(1,n) );
x = [zeros(1,n); x1; x1+x2]; y = [zeros(1,n); y1; y1+y2];
% Initialise the figure, set up axes etc
f = figure(1); clf; xlim([-1.5,1.5]); ylim([-1.5,1.5]);
% Draw all of the lines, initially not showing because NaN vs NaN
lines = arrayfun( @(x)line(NaN,NaN), 1:nFade, 'uni', 0 );
% Set up shorthand for recolouring all the lines
recolour = @(lines) arrayfun( @(x) set( lines{x},'Color',ones(1,3)*(x/nFade) ), 1:nFade );
for ii = 1:n
% Shift the lines around so newest is at the start
lines = [ lines(end), lines(1:end-1) ];
% Overwrite x/y data for oldest line to be newest line
set( lines{1}, 'XData', x(:,ii), 'YData', y(:,ii) );
% Update all colours
recolour( lines );
% Pause for animation
pause(0.01);
end
结果:
假设我有这个非常简单的循环
for i=1:10
[xO, yO, xA, yA, xB, yB, xC, yC] = DoSomething(i);
line([xO,xA,xB,xC],[yO,yA,yB,yC]);
pause(0.1);
end
我正在绘制的坐标对应于多体系统的关节,我正在模拟它们随时间的位置(请在此处查看绘图示例):
由于某些链接以周期性方式移动,因此很难直观地跟踪移动。出于这个原因,现在出现了一个问题:如何以一种方式绘制线条,当绘制新线条时,先前的线条会逐渐消失?换句话说,这样我就有了从最近绘制的数据(最不透明)到最旧的数据(越来越透明直到完全消失)的梯度。
这样当一条新线画在与非常旧的数据相同的位置时,我会注意到它是一条新线。
您可以通过修改过去几行的第 4 个 Color
属性来做到这一点。
这是生成的 gif 演示演示,其中我将每帧的透明度淡出 10%,因此只有最近的 10 行可见。
代码如下,详见我的评论:
% Set up some demo values for plotting around a circle
a = 0:0.1:2*pi; n = numel(a);
[x,y] = pol2cart( a, ones(1,n) );
% Initialise the figure, set up axes etc
f = figure(1); clf; xlim([-1,1]); ylim([-1,1]);
% Array of graphics objects to store the lines. Could use a cell array.
lines = gobjects( 1, n );
% "Buffer" size, number of historic lines to keep, and governs the
% corresponding fade increments.
nFade = 10;
% Main plotting loop
for ii = 1:n
% Plot the line
lines(ii) = line( [0,x(ii)], [0,y(ii)] );
% Loop over past lines.
% Note that we only need to go back as far as ii-nFade, earlier lines
% will already by transparent with this method!
for ip = max(1,ii-nFade):ii
% Set the 4th Color attribute value (the alpha) as a percentage
% from the current index. Could do this various ways.
lines(ip).Color(4) = max( 0, 1 - (ii-ip)/nFade );
end
% Delay for animation
pause(0.1);
end
如果线路很多,您可能需要进行一些 plot/memory 管理。您可以通过添加类似
的内容来删除透明线if lines(ii).Color(4) < 0.01
delete(lines(ii));
end
循环内。这样你的身材就不会有大量的透明残留物。
备注:
- 我生成了实际的 gif using
imwrite
以防你也感兴趣。 - 显然第 4 种颜色值 'feature' 已在 R2018b 中贬值(不确定是否有正式记录)。
获得足够的赞成票来激励制作一个更有趣的演示...
Matlab 2018a 或更高版本(或更早,至少晚于 2012a)的解决方案
由于 Matlab 2018a 不再支持作为 alpha 值的第四个颜色参数(并且显然从来没有像 Cris Luengo 指出的那样支持),这里是使用 patchline
函数在 Matlab 2018a 中工作的解决方案来自文件交换(归功于 Brett Shoelson)。
% init the figure
figure(); axes();
hold on; xlim([-1 0.5]); ylim([0 1]);
% set fraction of alpha value to take
alpha_fraction = 0.7;
n_iterations = 200;
% looping variable to prevent deleting and calling already deleted lines
% i.e. to keep track of which lines are already deleted
delete_from = 1;
for i=1:n_iterations
% your x, y data
[x, y] = doSomething(i);
% create line with transparency using patchline
p(i) = patchline(x,y, 'linewidth', 1, 'edgecolor', 'k');
% set alpha of line to fraction of previous alpha value
% only do when first line is already plotted
if i > 1
% loop over all the previous created lines up till this iteration
% when it still exists (delete from that index)
for j = delete_from:i-1
% Update the alpha to be a fraction of the previous alpha value
p(j).EdgeAlpha = p(j).EdgeAlpha*alpha_fraction;
% delete barely visible lines
if p(j).EdgeAlpha < 0.01 && delete_from > j
delete(p(j));
% exclude deleted line from loop, so edgealpha is not
% called again
delete_from = j;
end
end
end
% pause and behold your mechanism
pause(0.1);
end
我按照@Wolfie 的建议(我自己的,可能不太优雅的实现)包括了删除几乎不可见的行
这里是快速释放机制的演示:
我正在添加第二个答案以明确区分两种完全不同的方法。我的
这个答案提供了一种不同的画线方法,没有兼容性问题(这两个 'features' 可以独立实现):
- 创建固定的
n
行并更新它们的位置,而不是创建越来越多的行。 - 重新给线条着色,淡化为白色,而不是改变透明度。
代码如下,详见评论:
% "Buffer" size, number of historic lines to keep, and governs the
% corresponding fade increments.
nFade = 100;
% Set up some demo values for plotting around a circle
dt = 0.05; a = 0:dt:2*pi+(dt*nFade); n = numel(a); b = a.*4;
[x1,y1] = pol2cart( a, ones(1,n) ); [x2,y2] = pol2cart( b, 0.4*ones(1,n) );
x = [zeros(1,n); x1; x1+x2]; y = [zeros(1,n); y1; y1+y2];
% Initialise the figure, set up axes etc
f = figure(1); clf; xlim([-1.5,1.5]); ylim([-1.5,1.5]);
% Draw all of the lines, initially not showing because NaN vs NaN
lines = arrayfun( @(x)line(NaN,NaN), 1:nFade, 'uni', 0 );
% Set up shorthand for recolouring all the lines
recolour = @(lines) arrayfun( @(x) set( lines{x},'Color',ones(1,3)*(x/nFade) ), 1:nFade );
for ii = 1:n
% Shift the lines around so newest is at the start
lines = [ lines(end), lines(1:end-1) ];
% Overwrite x/y data for oldest line to be newest line
set( lines{1}, 'XData', x(:,ii), 'YData', y(:,ii) );
% Update all colours
recolour( lines );
% Pause for animation
pause(0.01);
end
结果: