Animate creation of a circle clockwise and anticlokwise for different staringpoints

7 views (last 30 days)
Tim Felix Liesching on 9 Mar 2021
Commented: darova on 14 Mar 2021
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 :)

darova on 12 Mar 2021
Here is another approach:
• iterate from starting point until reaching the end
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 darova on 14 Mar 2021
Maybe excel? There is usefull online program like MATLAB: LINK
I used it now (don't have MATLAB on this computer)

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.
Tim Felix Liesching on 10 Mar 2021
Hey I don't see how to avoid the special cases with the atan2 function. For example if I want to animate clockwise from 180° to 450° (see picture) I couldn't use atan2 without distinguishing the starting and enpoint. I understand that you can calculate +/- 2pi to the positive or negative values for clockwise or counterclockwise animation. But does it realy go from 0 to 2pi or 0 to -2pi then? I don't think that you can get to 2pi or -2pi as atan2(0,+x) = 0. So if you want to go e.g. counterclockwise from 0 to 2pi the starting and endpoint will be the same and for both cases atan2(0,+x) will yield 0.
Do you have an idea how to guarantee that r1 (radius from startingpoint to center) and r2 (radius from endpoint to center) will have the same value?

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.
Tim Felix Liesching on 10 Mar 2021
Hey,
you are right with what you are saying. What I actually tried to mention is that also with the atan2() function I have to distinguish different cases for starting and endpoints. Like in the example above where the animation is supposed to go from 180 to 450. There I would need a case that adds the ending angle (90° in the example) to 360° so I get the right ending angle of 450° for my animation, because atan2 only goes from 0:2pi or 0:-2pi. I assume thats what you meant with "derive the starting and ending angles from the inital angles"that you calculated with atan2().
The other thing I was talking about concerns calculating +/- 2pi to go smooth from 0:2pi/-2pi. I don't understand how to get the exact value of 2pi or -2pi. E.g. for counterclockiwse animation I would add 2pi to the negative values. But when I get to zero coming from the negative half of the circle atan2(0,x) would be zero again and as zero is not a negative value I needed a special case like when the endpoint angle is zero for counterclockwise animation the derived angle has to be 2pi and not zero.
I hope you understand what I try to says.Please correct me if I'm wrong.
Best
Tim

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.

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.
Tim Felix Liesching on 12 Mar 2021
Hey William, thank you for all your help. I decided to stick with the algo that I have been writing already.
Best
Tim