# 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:

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?

Update:

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
````

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?

-
And by circle you mean dot? From the diagram I see two circles (orbits) and three dots. Is this correct? – ja72 Jul 12 '11 at 21:49
@George: I comment here because I received the message "Please avoid extended discussions in comments.". 1) the behavior you describe in your comment below is caused most likely by the values of $y=\arctan x$, which are usually $−\pi/2<y<\pi/2$. If the current value is $y=-\pi/2$ the next value instead of being $-\pi/2-\pi/180$ is $\pi/2+\pi/180$. 2) I think you should use COS(arc + PI - (PI / 180.0)) and SIN(arc + PI - (PI / 180.0)) instead of COS(arc - PI - (PI / 180.0)) and SIN(arc - PI - (PI / 180.0)). (see my formulas). – Américo Tavares Jul 13 '11 at 20:53
... 3) But I have no explanation for the counterclokwise movement. Since the point $(x_1-x_c,y_1-y_c)=(140.5-160,152-240)$ is in the 3rd quadrant I added $\pi$ to 1.3527. – Américo Tavares Jul 13 '11 at 20:55

2
ATAN has no information on which quadrant your angle is in and so puts it in 2 fixed quadrants. Most languages provide a function ATAN2 that takes 2 arguments to fix this problem. ATAN2(y, x) = ATAN(y/x) normally. Using ATAN2 should fix your semicircle problem. – gereeter Jul 13 '11 at 22:05
@George: I updated the answer with a plot of a new circle centered at $(100,100)$, where the movement of the point is clockwise as $t$ increases. – Américo Tavares Jul 13 '11 at 22:09
show 1 more comment

## 5 Answers

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$

$$(x_{1},y_{1})=(x(0),y(0)),(x(90),y(90)),(x(180),y(180)),(x(270),y(270)).$$

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

$$\begin{eqnarray*} 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}} \\ &=&90.135 \end{eqnarray*}$$

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

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

$$\begin{eqnarray*} \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*}$$ Thus $$\begin{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 \end{eqnarray*}$$

-
I'm not seeing where the 1 degree rotation is coming into effect in your last equation. Can you clarify? :) – George Jul 12 '11 at 23:06
@George: it enters in the subtraction of the angle $\dfrac{\pi}{180}$ from $\theta=1.4906+\pi$. (1 degree=$\pi/180$ rad) – Américo Tavares Jul 12 '11 at 23:46
@George: It is not the same in terms of the changes in the coordinates to have a change of 1 degree starting at an angle of e.g. 265.41 degrees (to 264.41 degrees) or the same 1 degree change but starting at let's say 0 degrees (to -1 degrees). – Américo Tavares Jul 13 '11 at 0:07
@George: I corrected the coordinates of $(x_1,y_1)=(140.5,152)$, which corresponds to an angle $\theta=257.5$ degrees. The rotated point makes an angle of $257.5-1=256.5$ degrees with the line $y_c$. My point is that you need to consider the new angle and not only the 1 degree change. The argument of $\cos$ and $\sin$ is this new angle and not 1 degree. – Américo Tavares Jul 13 '11 at 0:39

1
Wow, thank you for the in-depth answer. I never expected that much! I'd upvote you 10x if I could! – George Jul 13 '11 at 2:41
show 2 more comments

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.

-

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.

-

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.

-

Using "compass" coordinates with zero at north and positive angles in the clockwise direction is just as consistent as "math" coordinates with zero to the right and positive angles in the counter clockwise direction. All the same identities hold. – phv3773 Jul 13 '11 at 14:40
@phv3773: The internal consistency could never be an issue. And interchanging roles of $x$ and $y$ turns one to the other. The only possible difficulty is with mechanical "borrowing" of formulas. – André Nicolas Jul 13 '11 at 17:37
In order to account for the rounding issues, I assume it would be as simple as grabbing the starting point, and after 360 degrees of rotation, reset to the starting point.  Do you think that would be a viable option, or would the circle degrade within the initial 360 degree rotation, to the point where it would be noticable by the human eye? – George Jul 13 '11 at 20:17
@George: A very practical solution, which I am sure would be plenty good enough! – André Nicolas Jul 13 '11 at 21:18

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

$$\cos(\phi-\epsilon)=\cos\,\phi-(\mu\cos\,\phi-\nu\sin\,\phi)$$

$$\sin(\phi-\epsilon)=\sin\,\phi-(\mu\sin\,\phi+\nu\cos\,\phi)$$

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$

-
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 73, "mathjax_display_tex": 15, "mathjax_asciimath": 0, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "github"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "english_confidence": 0.9087531566619873, "perplexity_flag": "middle"}