- iterate from starting point until reaching the end
Animate creation of a circle clockwise and anticlokwise for different staringpoints
10 views (last 30 days)
Show older comments
Hey I'm developing a little GUI with App Desinger that is supposed to animate circles clockwise and anticlockwise for different starting points. The animation has to be done with given starting point, given endpoint and given i- and j-parameters. I and j is the distance from the startingpoint to the center point in x- and y-direction so you can easily calculate the radius of the circle.
I already wrote an algorithm for that purpose but as it's a bit complicated (lots of distinction of cases) I was wondering if there is an easyer way. Besides of that I'm facing an issue with my algo which I don't know how to solve.
In the following I'm going to show you the idea of my algo for the anticklockwise animation. The clockwise animation works the same, the only difference is that the angles run from zero to negative values.
My idea was to devide the circle into 4 segments. Given the center point of the circle I distinguish in which segment is my starting point and my endpoint. So for the clockwise animation I have 4 cases for the starting point and additional 4 cases for each of the starting points dealing with the endpoint. E.g. Starting point in 1st Segment: endpoint in 1st, endpoint in 2nd, endpoint in 3rd, endpoint in 4th segment.
Here is a part of my code for the starting point beeing in the 1st segment and the endpoint being in the 1st and 2nd segment. I saved the points in a struct called s in case you are wondering what s is. PlotCircle does the animation with the given points.
i = s(n).parameter(1);
j = s(n).parameter(2);
p1 = s(n-1).koordinaten;
p2 = s(n).koordinaten;
M = [p1(1) + i, p1(2) + j];
r = round(sqrt(i^2 + j^2),2);
if p1(1) > M(1) && p1(2) >= M(2) && p2(1) >= M(1) && p2(2) > M(2)
alpha1 = round (acos(abs(i)/r),2);
alpha2 = round(acos(abs(p2(2) - M(2))/r),2);
alpha = round((pi/2 - alpha2),2);
t = linspace(alpha1,alpha,50);
x = r * cos(t) + M(1);
y = r * sin(t) + M(2);
plotCircle(app,x,y);
end
if p1(1) > M(1) && p1(2) >= M(2) && p2(1) < M(1) && p2(2) >= M(2)
alpha1 = round (acos(abs(i)/r),2);
alpha2 = round(acos(abs(p2(2) - M(2))/r),2) + pi/2;
t = linspace(alpha1,alpha2,50);
x = r * cos(t) + M(1);
y = r * sin(t) + M(2);
plotCircle(app,x,y);
end
function plotCircle (app,x,y)
for m = 1:length(x)
plot2 = plot(app.UIAxes,x(m),y(m),'ro','LineWidth',1.5,'MarkerSize',5);
plot3 = plot(app.UIAxes,x(1:m),y(1:m),'r-','LineWidth',1.5,'MarkerSize',5);
drawnow
if m ~= length(x)
delete(plot2)
delete(plot3)
end
if m == length(x)
delete(plot2)
app.plot_array = [app.plot_array; plot3];
end
end
end
As you can see this is a lot of work for all cases existing. Anyway I took the time to implement all these cases for clockwise and anticlockwise animation. Still I would like to know if there is an easyer way.
The issue I was talking about earlier is kind of an optimization problem I guess. As the User of the GUI has to type in the staring point, endpoint, i and j manually there can be deviation of the radius of the starting point and endpoint. When I calculate alpha2 with acos (abs(....)/r) the radius r relates to the radius of staring point (p1) . This can cause inprecision in the calculation of the angles. For example when the User types in an endpoint that hasn't got approximately the same radius like the one calculated from i and j for the starting point.
I would be happy if I can overcome this problem with the algo I was developing myself because I spent so much time with it so far. Also I would like if my algo is a "good solution" to achieve clockwise and anticlockwise animations of a circle or if you recommend to solve it differently.
Best Tim :)
0 Comments
Accepted Answer
darova
on 12 Mar 2021
Here is another approach:
clc,clear
r0 = 2;
a = r0*[cosd(45) sind(45)]; % start
b = r0*[cosd(360+20) sind(360+20)]; % end
t0 = 1; % anti-clockwise
R = [cosd(t0) -sind(t0); sind(t0) cosd(t0)];% rotation matrix
p = nan(360,2);
i = 1;
p(i,:) = R*a';
while norm(p(i,:)-b) > r0*pi/180 % end condition
p(i+1,:) = R*p(i,:)';
i = i+1;
end
plot(a(1),a(2),'or')
hold on
plot(b(1),b(2),'or')
plot(p(:,1),p(:,2))
hold off
axis equal
13 Comments
More Answers (4)
William
on 9 Mar 2021
Tim,
I think you could avoid all the special cases by making use of the atan2() function. This function is defined for points in all four quadrants and it returns an angle in the range of -pi to pi. If you want to go counterclockwise, you can add 2*pi to the negative angles to get angles that go smoothly from 0 to 2*pi. Likewise, if you want to go clockwise, you can subtract 2*pi from the positive angles to get values that go smoothly from 0 to -2*pi. In either case, you can then simply interpolate from the starting angle to the ending angle without worrying about what quadrant you are in.
William
on 10 Mar 2021
Hi Tim,
I don't think there is any problem with the cases you describe. The values of sin() and cos() are periodic in their arguments, so if their arguments go from 280 to 450, the values will be continuous and correct. There will be no sudden jump when the angle passes through 360 degrees. The only thing you need to ensure is that the starting and ending angles that you derive from the initial and final coordinates are correct, and I think that is handled properly by atan2() (or by atan2d() if you are using degrees rather than radians).
As for r1 and r2 being different: If they are only different by a small amount, because of the accuracy of the coordinates from which they are derived, then perhaps you could round them each to 2 decimal places with round(r1,2). An alternative might be to replace them each by (r1+r2)/2.
William
on 11 Mar 2021
Hi Tim,
Actually I have been thinking a little more about this, and I believe it is even easier than I suggested. You don't need to worry about adding anything to the values to make the them go continuously from 0:2*pi or 0:-2*pi. Just calculate the starting and ending angles with atan2(). Then if the ending angle is less than the starting angle, add 2*pi to the ending angle. I believe that works whether you are going clockwise or counterclockwise.
... and I don't believe you need to worry about that problem about the exact value 2*pi. That will also be handled correctly by the rule above. Remember that you are not computing the intermediate angle value from the point coordinates. You are just interpolating them between the starting angle and the ending angle.
0 Comments
William
on 11 Mar 2021
Tim,
A correction to the last message. If you want to go counterclockwise, you need to make the final angle bigger than the starting angle. If it is not bigger, then you should add 2*pi. But if you want to go clockwise, you need to make the final angle smaller than the starting angle, and if it is not smaller, then you should substract 2*pi.
See Also
Categories
Find more on Graphics Object Programming in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!