Search code examples
matlabplotlinetransparencymatlab-figure

How to make previous inputs progressively fade out in a Matlab plot when I add new inputs


Let's say I have this very simple loop

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

The coordinates that I am plotting correspond to the joints of a multibody system, and I am simulating their positions over time (please see a sample of the plot here):

Periodic plot

Since some of the links move in a periodic way, it gets confusing to keep track visually of the movement. For this reason, now comes the question: how can I plot the lines in a way that, when a new line is plotted, the previous lines are faded progressively? In other words, so that I have a gradient from the most recently plotted data (most opaque) to the oldest data (increasingly transparent until it completely fades out).

This way when a new line is drawn in the same position as very old data, I will notice that it is a new one.


Solution

  • I'm adding a 2nd answer to clearly separate two completely different approaches. My 1st answer uses the undocumented (and as of 2018b, depreciated) transparency option for lines.

    This answer offers a different approach for line drawing which has no compatibility issues (these two 'features' could be implemented independently):

    • Create a fixed n lines and update their position, rather than creating a growing number of lines.
    • Recolour the lines, fading to white, rather than changing transparency.

    Here is the code, see comments for details:

    % "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
    

    Result:

    demo