Reputation: 143
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
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