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

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

About these ads
Categories: Software, Web Tags: , ,
  1. markus
    March 27, 2009 at 11:15 am | #1

    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

    • Anonymous
      June 20, 2009 at 5:55 am | #2

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

    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. markus
    March 30, 2009 at 9:27 pm | #4

    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…

  4. markus
    March 30, 2009 at 9:27 pm | #5

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

    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. behindblueeyez
    April 13, 2009 at 7:21 pm | #7

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

  7. April 13, 2009 at 8:31 pm | #8

    Fixed. :)

  8. markus
    April 24, 2009 at 10:09 pm | #9

    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 …

  9. itguy
    February 27, 2010 at 6:54 am | #10

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

      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.

      • Mr Figg
        October 3, 2010 at 12:36 pm | #12

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

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

          • Mr Figg
            October 3, 2010 at 11:09 pm | #14

            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.

            • Mr Figg
              October 4, 2010 at 12:24 am | #15

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

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

  10. Anonymous
    October 6, 2010 at 11:07 pm | #17

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

  11. Anonymous
    November 3, 2010 at 5:57 pm | #18

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

      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. DRock
    November 26, 2010 at 3:32 am | #20

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

    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

  14. Thomas Konrad
    February 14, 2012 at 12:47 am | #22

    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

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: