Calculating point on a circle, given an offset?

I have what seemed like a very simple issue, but I just cannot figure it out. I have the following circles around a common point:

enter image description here

The Green and Blue circles represent circles that orbit the center point. I have been able to calculate the distance/radius from the point to the individual circles, but I am unable to plot the next point on either circle, given an angle from the center point. Presently, my calculation looks like the following:

The coordinates of one of my circles is:

y1 = 152
x1 = 140.5

And my calculation for the next point, 1 degree from the starting point (140.5,152) is:

distance = SQRT((160-x1)^2 + (240-y1)^2) = 90.13
new x = 160 - (distance x COS(1 degree x (PI / 180)))
new y = 240 - (distance x SIN(1 degree x (PI / 180)))

My new x and y give me crazy results, nothing even close to my circle.

I can’t figure out how to calculate the new position, given the offset of 160, 240 being my center, and what I want to rotate around. Where am I going wrong?


I have implemented what I believe to be the correct formula, but I’m only getting a half circle, e.g.

x1 = starting x coordinate, or updated coordinate
y1 = starting y coordinate, or updated y coordinate    
cx = 100 (horizontal center)
cy = 100 (vertical center)

radius = SQRT((cx - x1)^2 + (cy - y1)^2)
arc = ATAN((y1 - cy) / (x1 - cx))
newX = cx + radius * COS(arc - PI - (PI / 180.0))
newY = cy + radius * SIN(arc - PI - (PI / 180.0))

Set the values so next iteration of drawing, x1 and y1 will be the new
base for the calculation.
x1 = newX
y1 = newY

enter image description here

The circle begins to draw at the correct coordinates, but once it hits 180 degrees, it jumps back up to zero degrees. The dot represents the starting point. Also, the coordinates are going counterclockwise, when they need to go clockwise. Any ideas?

Solutions Collecting From Web of "Calculating point on a circle, given an offset?"

Update 2: Here is the graph I got for $(x_{1},y_{1})=( 78. 965,12. 354)$, for the parametric circle $(x(t),y(t))$ centered at $(100,100)$

$$x=100+90.135\cos \left( 1.3527+\pi -t\frac{\pi }{180}\right) ,$$

$$y=100+90.135\sin \left( 1.3527+\pi -t\frac{\pi }{180}\right) .$$

together with the 4 points $(x(t),y(t))$ for $t=0,90,180,270$


enter image description here

You might use the following equations in a for loop with $k=0$ to $k=359$, step $1$:

$$x=100+90.135\cos \left( 1.3527+\pi -k\frac{\pi }{180}\right) ,$$

$$y=100+90.135\sin \left( 1.3527+\pi -k\frac{\pi }{180}\right) .$$

to draw the “orbit” with a 1 degree interval.

Update: corrected coordinates of $(x_{1},y_{1})=(140.5,152)$.

You need to consider the new angle and not only the $1{{}^\circ}$ change. The argument of $\cos$ and $\sin$ is this new angle and not $1{{}^\circ}$.

Let $(x_{c},y_{c})=(160,240)$ be the center of the set of circles and $(x_{1},y_{1})=(140.5,152)$. The radius $r$ is

r &=&\sqrt{\left( x_{c}-x_{1}\right) ^{2}+\left( y_{c}-y_{1}\right) ^{2}} \\
&=&\sqrt{\left( 160-140.5\right) ^{2}+\left( 240-152\right) ^{2}} \\

Call $(x,y)$ the new coordinates of $(x_{1},y_{1})$ rotated by an angle of $-1{{}^\circ}=-\dfrac{\pi }{180}$ around $(x_{c},y_{c})$ with a radius $r$. The new angle is $\theta’=\theta -\frac{\pi }{180}$, $\theta $ being the initial angle. Then

x &=&x_{c}+r\cos \left( \theta -\frac{\pi }{180}\right), \\
y &=&y_{c}+r\sin \left( \theta -\frac{\pi }{180}\right),
where $\theta $ is the angle $\theta =\arctan \dfrac{y_{1}-y_{c}}{x_{1}-x_{c}}:$

\theta &=&\arctan \frac{152-240}{140.5-160}=1.3527+\pi \text{ rad.}\\
&=&\frac{1.3527\times 180{{}^\circ}}{\pi }+180{{}^\circ}=257. 5{{}^\circ}\end{eqnarray*}$$
x &=&160+90.135\cos \left( 1.3527+\pi -\frac{\pi }{180}\right)=
138. 96 \\y &=&240+90.135\sin \left( 1.3527+\pi -\frac{\pi }{180}\right) = 152. 35

enter image description here

How about:
$$ \begin{matrix} x_{green} = x_{center} + r_{green} \cos \theta \\ y_{green} = y_{center} + r_{green} \sin \theta \end{matrix} $$

then then just increment your angle $\theta$ by 1 degree. Make sure you convert degrees to radians before using the sin() and cos() functions.

Similarly for the blue dot.

A look at the calculation reveals the basic issue. The calculation of new $x$ and new $y$ pays no attention to the old $x$ and old $y$. It is therefore not surprising that the new point is nowhere near the old point.

The center and radius are known. For the sake of plotting, we presumably need to keep track of $(x,y)$. From this we can compute the angle, which we might as well compute from the the usual reference half-line, the positive $x$-axis. There is a slight complication that the rotation seems to be clockwise. So, if we follow the usual mathematical conventions, soon the angle will be negative.

We now have a problem. Shall we have negative angles built into the code, or shall we change the usual convention about signs of angles. Each choice has built-in problems. Negative angles are intuitively unpleasant, but changing from the usual convention means that we may have to adjust standard formulas. I will choose to use the ordinary convention that counterclockwise is positive. But you probably shouldn’t.

It is a nuisance to recompute the angle each time from the current $x$ and $y$. (In the old days, it was also excessively computationally costly). So my feeling is that it is best to keep track of of the angle.

In changing the angle by $1^\circ$, we need to decrement the angle by $\pi/180$ radians. Let $R$ be the radius. We want
$$\theta_{\rm new}=\theta_{\rm old} -\frac{\pi}{180}$$
$$x_{\rm new}=160+R\cos(\theta_{\rm new})$$
$$y_{\rm new}=240+R\sin(\theta_{\rm new})$$
Recall that angles will be negative most of the time. One can work with the positive version by incrementing, and using $-R\sin(\theta_{\rm new})$. The $+$ sign in front of the $R\cos$ term would remain unchanged.

An alternative way of doing things is to look up how to carry out rotations by multiplying by an appropriate matrix. You will probably need the idea sometime in the future, so might as well test both ways now. In that case, you don’t need to keep track of angle. All that one does is multiply the vector $(x_{\rm old}, y_{\rm old})$ by the appropriate matrix that does rotation by $1^\circ$ to get
$(x_{\rm new}, y_{\rm new})$ . The matrix is precomputed, so the calculations are blazing fast.

It is not quite as simple as that! Fairly quickly, because of accumulating roundoff errors, there will be degradation of quality: the spinning circle will make a lousy clock. So adjustment steps have to be built in, if long-term accuracy is desired.

The matrix approach is faster. The one I discussed at some length is essentially what you chose to do, adjusted to make things work. What to do?

Code both. At some time or other, you will have need of each idea.

We can modify 6312’s suggestion a bit to reduce the trigonometric effort. The key idea is that the trigonometric functions satisfy a recurrence relation when integer multiples of angles are considered.

In particular, we have the relations



where $\mu=2\sin^2\frac{\epsilon}{2}$ and $\nu=\sin\,\epsilon$. (These are easily derived through complex exponentials…)

In any event, since you’re moving by constant increments of $1^\circ$; you merely have to cache the values of $\mu=2\sin^2\frac{\pi}{360}\approx 1.523048436087608\times10^{-4}$ and $\nu=\sin\frac{\pi}{180}\approx 1.745240643728351\times 10^{-2}$ and apply the updating formulae I gave, where your starting point is $\cos\,\phi=\frac{140.5-160}{\sqrt{(140.5-160) ^2+(152-240)^2}}\approx-0.2163430618226664$ and $\sin\,\phi=\frac{152-240}{\sqrt{(140.5-160) ^2+(152-240)^2}}\approx-0.9763174071997252$

George, instead of subtracting for the offset, try adding, i.e.

distance = SQRT((160-x_{1})^2 + (240-y_{1})^2) = 90.13 
new x = 160 + (distance x COS(1 degree x (PI / 180))) 
new y = 240 + (distance x SIN(1 degree x (PI / 180))) 

The part,
$x_{new}=(distance)(cos(pi/180))$ is assuming the distance is from the origin (0,0). Since you are starting your x value from positive 160, you need to add that, i.e.
$x_{new}=x_{center} + (distance)(cos(pi/180))$
$x_{new}=160 + (distance)(cos(pi/180))$
And similarly for the new y value.