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

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

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?

I don’t know exactly how your program works, so it will be kind of hard to figure it out. But if you’re asking for a formula for triangle you can check this out: http://math.stackexchange.com/questions/544559/is-there-any-equation-for-triangle

Hi Adrian,

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!

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.

toRadians = function(degrees) {

return degrees * Math.PI / 180;

};

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:

function getPointAt(center, radius, angle) {

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!

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.