Home > Software, Web > Calculating the angle between two points on a circle

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

Angle between two points on a circle

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) {
// 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.

Categories: Software, Web Tags: , ,
1. March 27, 2009 at 11:15 am

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

• June 20, 2009 at 5:55 am

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.

2. March 27, 2009 at 12:50 pm

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.

```public double getAngleOfPointOnCircle(double x, double y) { //calculate the circle radius double radius = Math.sqrt(Math.abs(x - centerX) * Math.abs(x - centerX) + Math.abs(y - centerY) * Math.abs(y - centerY)); // calculate the coordinates for the 12-hour point on the circle double p0x = centerX; double p0y = centerY - radius; // calculate and return the angle in degrees in the range 0..360 return (2 * Math.atan2(y - p0y, x - p0x)) * 180 / Math.PI; }```

Tell me if this works.

3. March 30, 2009 at 9:27 pm

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

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() {
xCenterKm = 0;
yCenterKm = 0;

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…

4. March 30, 2009 at 9:27 pm

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

5. March 31, 2009 at 8:42 am

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.

6. April 13, 2009 at 7:21 pm

I can’t see the demo drawing in Firefox 😦

7. April 13, 2009 at 8:31 pm

Fixed. 🙂

8. April 24, 2009 at 10:09 pm

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() {
xCenterKm = 0;
yCenterKm = 0;

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 …

9. February 27, 2010 at 6:54 am

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.

• February 27, 2010 at 6:21 pm

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.

• October 3, 2010 at 12:36 pm

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.

• October 3, 2010 at 3:16 pm

The JS function should be the following:

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

• October 3, 2010 at 11:09 pm

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.

• October 4, 2010 at 12:24 am

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

• October 4, 2010 at 1:16 am

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

10. October 6, 2010 at 11:07 pm

I’m in love with you.
Really saved my day.

11. November 3, 2010 at 5:57 pm

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

• November 3, 2010 at 8:55 pm

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.

12. November 26, 2010 at 3:32 am

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!

13. December 3, 2010 at 4:49 pm

was a long post to read…

just wanted to confirm if its this

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

14. February 14, 2012 at 12:47 am

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

15. May 9, 2016 at 8:37 pm

I created a math drawing program at http://www.ptrone.com/
Using the formula
cos(point)*120
it draws a cicle
but I really want formula for a triangle can you help please?

16. March 7, 2018 at 3:50 pm

Thanks for this calculator! We use it to draw markers on a google map in order of a circle, around a city. It works, except for the fact that our markers are drawn together as an oval, not as a nice round circle??

We use the getPointAt() function you describe, with a static center and radius, the only difference is the angle, which we increment by a loop like this: 45 + (45 * n) (n for every marker).
Both the radius and the angle seem to differ per marker so it places them in an oval, not a circle. Changing the radius to 30 degrees for example also creates an oval so that makes no difference.

Can you help us out? Thanks!

• March 12, 2018 at 3:57 pm

You cannot change the radius to 30 degrees, the radius is not calculated in degrees. The radius will be how far the markers are from the city center.
The coordinates of your markers will be getPointAt(center, radius, toRadians(45 * i)), where center represents the coordinates of the city center, radius is how far from the city center the markers will be displayed and i=1,7 (there are only 8 markers at a 45 degrees increment 45*8 = 360 and the first one is at 12’o clock). And toRadians function is implemented below.

return degrees * Math.PI / 180;
};

• March 23, 2018 at 12:56 pm

Thank you for your reply! And sorry, I made a mistake in my comment, with that 30 degrees radius I meant the angle of course. I think the parameters in our function work kind of the same way, we already convert the angle but it creates an oval like described. Here is the specific part of our script:

Here is the function from your page above we use to create the markers coordinates:

angle *= Math.PI / 180;

var thisLat = center.x + Math.sin(Math.PI – angle) * radius;
var thisLng = center.y + Math.cos(Math.PI – angle) * radius;

var circle_coords = {lat:thisLat, lng:thisLng};

return circle_coords;
}

And in a loop we actually execute the function, push the coordinates in an array and we use nthLatLng to put the coordinates to the properties of the marker itself:

for(…) {
coords_last = coords_array.length – 1;

coords_next = getPointAt({x:coords_array[0].lat, y:coords_array[0].lng}, 0.03, 45 + (45 * n));

coords_array.push(coords_next);

nthLatLng = new google.maps.LatLng(coords_array[coords_last + 1].lat, coords_array[coords_last + 1].lng);
}

So this works, except our markers create a weird oval shape together. Can you have a second look at it? Thanks for your time!

• March 27, 2018 at 3:47 pm

I did not used lately google maps API, but otherwise this looks good. If the oval shape is almost round it could be because of the float precision.

1. December 7, 2014 at 6:49 pm