George Wilson
George Wilson

Reputation: 143

Animation in MATLAB - Animating several moving points simultaneously

Below is a MATLAB function that plots 2D Bezier curves. My goal is to animate all of the different components that are being used in the background i.e. tangents to the Bezier curve, points between the control points etc. I'd like to have something looking similar to the animation towards the end of this video: Cubic Bezier Curves - Under the Hood.

My problem is that when I attempt to plot all of the points running between the control points simultaneously, I get quite a severe flickering.

I'm fairly new to animation with MATLAB and a lot of code for animation has been pulled from various sources. Any help would be great!

P.S. The control points I have been using are [1 1;2 6;7 7;10 2].

function bezier_anim(coords) % Coords to be entered in the format [x1 y1;x2 y2;...;xn yn]

close all

n = length(coords(:,1)); % Number of control points

syms t;
syms p;
B = zeros(2,1); % Bezier function

for i = 0:n-1
    % Equation for Bezier curve
    B = B + nchoosek(n-1,i) .* (1-t).^(n-1-i) .* t^i .* coords(i+1,:).'; 
end

for i = 1:n
   % Plot and label P_i
   x=coords(i,1);
   y=coords(i,2);
   plot(x,y,'kx')
   txt1 = '$$\mathbf{P}_';
   txt2 = num2str(i-1);
   txt3 = '$$';
   txt = [txt1 txt2 txt3];
   text(x,y,txt,'Interpreter','latex','VerticalAlignment','bottom','HorizontalAlignment','center')
   hold on
end

plot(coords(:,1),coords(:,2),'k--') % Plot lines between control points

L = sym('t',[2 n-1]); % Vector where eqs of lines are to be added

for i = 1:n-1 
    % Parametric equations of the straight lines between the control
    % points, for p between 0 and 1
    L(1,i) = (1-p)*coords(i,1) + p*coords(i+1,1);
    L(2,i) = (1-p)*coords(i,2) + p*coords(i+1,2);
end

% Animation of Bezier curve
g = animatedline;
x = matlabFunction(B(1));
y = matlabFunction(B(2));

for t = 0:0.01:1
    l = subs(L,'p',t); % Substitute current t value into eq for the lines
    addpoints(g,x(t),y(t));
    for k = 1:length(l(1,:)) % Plot all points running along each line simultaneously
        h(k) = plot(l(1,k),l(2,k),'r.');
        drawnow
        delete(h(k)) % Delete current point after it has been drawn 
                     % so there is not a trail
    end
    drawnow
end

end

Upvotes: 1

Views: 843

Answers (1)

Suever
Suever

Reputation: 65430

You are likely getting degraded performance because you are creating new plot objects inside of your last nested for loop rather than updating existing plot objects. You can rewrite that loop to modify the XData and YData properties of the existing plot object instead

% Animation of Bezier curve

% Create the plot object to use later
hplot = plot(NaN, NaN, 'r.');

for t = 0:0.01:1
    l = subs(L,'p',t); % Substitute current t value into eq for the lines
    addpoints(g,x(t),y(t));

    for k = 1:length(l(1,:)) % Plot all points running along each line simultaneously
        % Update the position of the existing plot object
        set(hplot, 'XData', l(1,k), 'YData', l(2,k))
        drawnow
    end
    drawnow
end

You can also make sure that you have the DoubleBuffer property of the figure set to 'on' to reduce flickering.

set(gcf, 'DoubleBuffer', 'on')

Also, I think the "flickering" may actually just be that MATLAB is rendering the movement of the red point very fast (and it's jumping between line segments) and you're seeing it as flickering. I think rather than that inner for loop, plotting the red points on all line segments at the same time may be easier to see

% Create the plot object to use later
hplot = plot(NaN, NaN, 'ro');

for t = 0:0.01:1
    l = subs(L,'p',t); % Substitute current t value into eq for the lines
    set(hplot, 'XData', l(1,:), 'YData', l(2,:));

    addpoints(g,x(t),y(t));

    drawnow
end

Upvotes: 3

Related Questions