## Calculating the angle between two points on a circle

I needed to calculate the angle between two points on the same circle. Don’t ask why, totally a new more complicated discussion.

So I had to remember a little trigonometry from the old days. Actually, this is done surprisingly easy, by simply using the `atan2`

method. Fortunately, this is available in `JavaScript`

in the `Math`

library.

In my problem, I had the center of the circle, one of the coordinates point(p1) and I had to find out the angle between the point (p0) at the 12-hour (imagine the circle as a clock) and the given one.

First of all the coordinates of the point at 12-hour is

p0(x,y) = (center.x, center.y - radius)

where radius is the circle radius and is calculated (according to Pythagorean theorem) as

radius = sqrt(|center.x - p1.x|<sup>2</sup> * |center.y - p1.y|<sup>2</sup>)

Now let’s calculate the angle:

angle = atan2(p1.y - p0.y, p1.x - p0.x)

This will return the angle in radians. If you want to translate it into the interval [0,2 π] then simply multiply by two. If you want to transform it to degrees use `angle * 180 / π`

.

Below you have a JavaScript function that receives as arguments the coordinates of the center and second point and returns the angle in degrees in the interval (0°, 360°) between the 12-hour point and the second point

function angle(center, p1) { var p0 = {x: center.x, y: center.y - Math.sqrt(Math.abs(p1.x - center.x) * Math.abs(p1.x - center.x) + Math.abs(p1.y - center.y) * Math.abs(p1.y - center.y))}; return (2 * Math.atan2(p1.y - p0.y, p1.x - p0.x)) * 180 / Math.PI; }

I also wrote a small demo.

*Later update:*

As I had this question in the comments, in case you have the center coordinates, radius, angle and you want to calculate the second point coordinates, below is the JavaScript function. The first point is considered to be at 12’o clock.

function getPointAt(center, radius, angle) { // Please note that the angle is given in radians; // if given in degrees uncomment the line below //angle *= Math.PI / 180; return {x: center.x + Math.sin(Math.PI - angle) * radius, y: center.y + Math.cos(Math.PI - angle) * radius}; }

All the coordinates are relative to the top left corner.

Hi Adrian,

Thanks for your blog entry. I’m trying to solve exactly this problem. My was this:

public double getAngleOfPointOnCircle(double x_Point_km, double y_Point_km) {

return Math.atan((y_Point_km-center_Y_km)/(x_Point_km-center_X_km));

}

It works until 180 degrees, but for 270 degrees it returns 90.

I unfortunately don’t understand the construction you are using for var p0= {x: center.x, y: center.y – Math.sqrt(Math.abs(p1.x – center.x) * Math.abs(p1.x – center.x)

+ Math.abs(p1.y – center.y) * Math.abs(p1.y – center.y))};

I ignore the construction you are using like {x:…,y:…)

Would you mind to rewrite this line in a “conventional” way?

Thanks a lot for help

Markus

Thanks for this. Difference in subtracting rather than adding radius to y is probably due to fact that math classes graph higher y’s higher on the chalk board and computers put higher y’s on the bottom of the screen.

I wrote this in JavaScript, as I needed it. The construction {x: …, y: …} is practically used to encapsulate the point coordinates into an object, something like using

`Point2D.Double`

instead of two double’s for specifying the point.So you want this in Java.

Tell me if this works.

Hi Adrian,

Thanks a lot for your help. I tried your formula, but it didn’t give me yet the results as I expected.

I didnt understand 2 points in your calculation:

why is the y-coordinate for 12 oclock

(centerY – radius),

I expected (centerY + radius)

I also didn’t find the reason, why you multiply by 2 (in your formulat 2 * Math.atan2(…))

I searched for details about the atan2 form and found a good description http://en.wikipedia.org/wiki/Atan2

I then wrote a function using just the plain atan2 function (radiants are fine for me, I don’t need degrees) like

public double getAngleTo3Oclock(double x_Point_km, double y_Point_km) {

return Math.atan2(y_Point_km, x_Point_km );

}

I then wrote a test that works with the function:

public void testGetAngleTo3Oclock() {

radius_km =1;

xCenterKm = 0;

yCenterKm = 0;

new CircleTrack(radius_km, xCenterKm, yCenterKm);

double x_CircleEntrance_km = 1;

double y_CircleEntrance_km = 0;

assertEquals(0, circleTrack.getAngleTo3Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.0000000000001);

x_CircleEntrance_km = 0;

y_CircleEntrance_km = -1;

assertEquals(-Math.PI/2, circleTrack.getAngleTo3Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.0000000000001);

x_CircleEntrance_km = -1;

y_CircleEntrance_km = 0;

assertEquals(Math.PI, circleTrack.getAngleTo3Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.0000000000001);

x_CircleEntrance_km = 0;

y_CircleEntrance_km = 1;

assertEquals(Math.PI/2, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.0000000000001);

}

However, I found the result a bit disappointing. I’m looking for an angle from 0 to 2*pi and I don’t want to make that cumbersome 4 case decision. So I guess I have to investigate some more. Currently I’m thinking of going back to use the cosinus-function, where I have to distinguish just 2 cases (http://en.wikipedia.org/wiki/Polar_coordinate_system; the english version only shows the arctan, whereas the german version shows in the chapter Berechnung des Winkels im Intervall (−π, π] the calculation just below the arctan calculus.)

Well, I guess I have to do some more home work…

sorry, I forgot to give the link to the last remark: http://de.wikipedia.org/wiki/Polarkoordinate

The link that you found for describing the atan2 function is also in my article, right at the beginning.

The y-coordinate for 12 oclock is (centerY – radius) because the origin is at top left. If it would have been bottom left, then indeed it will be (centerY + radius).

Have you tried the demo to see if my example gives you what you try to calculate?

PS You gave the right link, in the first place, much more people are speaking English than German.

I can’t see the demo drawing in Firefox :(

Fixed. :)

Hi Adrian,

After a deep long breath I came back to this and it is driving me crazy.

I tried your demo, it is convincing indeed.

So I decided to implement your method step by step like this:

// the radius is passed to the object, so it doesn’t has to be calculated

double p0x = center_X_km;

double p0y = center_Y_km – radiusInKm;

// calculate and return the angle in degrees in the range 0..360

//return ( Math.atan2(y_Point_km – p0y, x_Point_km – p0x));

return (2 * Math.atan2(y_Point_km – p0y, x_Point_km – p0x)) * 180 / Math.PI;

Then I wrote a test using the unit circle, and checked the values with the wikipedia article, they should be right:

public void testGetAngleTo12Oclock() {

radius_km = 1;

xCenterKm = 0;

yCenterKm = 0;

new CircleTrack(radius_km, xCenterKm, yCenterKm);

double x_CircleEntrance_km = 0;

double y_CircleEntrance_km = 1;

// //assertEquals(Math.PI/2, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.01);

assertEquals(0, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.01);

x_CircleEntrance_km = 1;

y_CircleEntrance_km = 0;

//assertEquals(Math.PI/2, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.01);

assertEquals(90, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.01);

x_CircleEntrance_km = 0;

y_CircleEntrance_km = -1;

//assertEquals(Math.PI/2, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.0000000000001);

assertEquals(180, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.01);

x_CircleEntrance_km = -1;

y_CircleEntrance_km = 0;

//assertEquals(3/2*Math.PI, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.0000000000001);

assertEquals(270, circleTrack.getAngleTo12Oclock(x_CircleEntrance_km, y_CircleEntrance_km), 0.01);

The test for 90 and 270 degrees work, but for expected 0 it returns 180 and for 180 it returns 0. I thought it might be because of the negative numbers and shifted the center by (1,1), but same result.

You do calculate the angle to the top of the circle (12 o’clock), right?

I just can’t find what’s wrong …

I was wondering if you’ve written a js function to return a point when given a center point, radius(in pixels), and the angle?

It’s been years since I’ve done this kind of math and it’s driving me crazy.

In my problem I had the center, p0, p1 and I calculated the angle. If you have the center and radius you know what is p0. Then having center, p0 and angle you can calculate p1 using the same formula.

Would you possible be willing to write an example of this? This is exactly what I need for my project but I’m having way to much trouble figuring it out.

The JS function should be the following:

Wouldn’t that example use a p0 that is 3 o’clock of the center? The part I couldn’t figure out was how to make the p0 be 12 o’clock like in your initial code.

Also, thanks for responding so fast.

Never mind. I had a problem with updating my x,y cords. Works great. Thanks a ton for your excellent code snippet.

I also modified the demo to calculate the coordinates of the second point.

I’m in love with you.

Really saved my day.

Hi Adrian, what if i have 3 points on the circle, (XY plane), and I need to get the coordinates of the center, and the angle. That is, between the center and the last point. Any idea on how to get this?

Regards

That’s actually very easy. Calculate the angle between the first point and the 12 hour point and the angle between the second point and the 12 hour point and then simply subtract them and you have your result.

Perhaps I’m just missing this, but how can I get the 360 degree angle between two points in the XY plane rather than three? This seems to be just an extension of what you’ve already written, but I can’t quite wrap my head around it. Thanks!

was a long post to read…

just wanted to confirm if its this

Theta=2*sin-1(d/2*R)

http://manojky.net/?p=5

Hey!

Thanks for that post – it saved me a lot of time. There is, however, a little error in the formula that calculates the radius:

radius = sqrt(|center.x – p1.x|2 + |center.y – p1.y|2)

There should be an addition (+) between the two parts inside the square root, not a multiplication (*).

Cheers

Tom