Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find angle of point on circle

Imagine I have drawn a circle with center coordinates (cx,cy) on the screen and a random point (A) is selected on the circle.

trigonometric circle

By having the the coordinates of point A, I need to find the angle of (a).

Update:

I have tried using the following formula:

Math.toDegrees(Math.asin(((x - cx) / radius).toDouble()))

which is actually the reverse of (the circle is created by feeding angles to this one):

x = radius * Math.sin(Math.toRadians(angle.toDouble())) + cx
y = radius * Math.cos(Math.toRadians(angle.toDouble())) + cy

But since the y coordinate is not present in the formula the answer could be wrong.

like image 841
2hamed Avatar asked Sep 24 '17 07:09

2hamed


4 Answers

If you know the cartesian coordinates of the point A(x,y), then you can find the angle theta by converting it into polar coordinates as below:

double theta = Math.toDegrees(Math.atan2(y - cy, x - cx));

This formula works if your X axis is in 0 degrees, otherwise you need to consider the offset.

like image 198
Nabin Bhandari Avatar answered Nov 14 '22 12:11

Nabin Bhandari


I think the method you are looking for i Math.atan2 which computes the angle to an x and y cordinate. I have now modified the code to adjust for putting 0 degrees downwards. I have also flipped the y-axis to put 0, 0 cordinate in the upper left corner (screen coordinates), and adjusted degrees above 180 to be reported as negative degrees:

public double theta(int cx, int cy, int x, int y)
{
    double angle = Math.toDegrees(Math.atan2(cy - y, x - cx)) + 90;
    return angle <= 180? angle: angle - 360;
}

A small test to verify some angles...

@Test
public void test()
{
    assertThat(theta(50, 50, 60, 50), is(90.0));
    assertThat(theta(50, 50, 50, 60), is(0.0));
    assertThat(theta(50, 50, 40, 50), is(-90.0));
    assertThat(theta(50, 50, 50, 40), is(180.0));
}
like image 3
Per Huss Avatar answered Nov 14 '22 13:11

Per Huss


You can find the tangent angles and add to 90 or substruct from 270 that angle and find the result, I believe. I design the code like your drawing. You can make it more generic, I guess. You have 4 area:

  1. 0 degree to 90 degree
  2. 90 degree to 180 degree
  3. 90 degree to -90(270) degree
  4. -90(270) degree to 0(360) degree

Code:

public static double findAngle(double x,  double y,
                               double cx, double cy, double radius){
    double beta, alfa;

    double distanceX = Math.abs(Math.abs(x) - Math.abs(cx));
    double distanceY = Math.abs(Math.abs(y) - Math.abs(cy));

    // check the point is on the circle or not
    // with euchlid
    if (radius != Math.sqrt(x * x + y * y)) {
        return -1;
    }

    if (x >= cx && y <= cy) {
        // find tangent
        beta = Math.atan(distanceY / distanceX);
        alfa = 90 - beta;
        return alfa;
    }
    // 90-180 -> second area
    else if (x >= cx && y >= cy) {
        beta = Math.atan(distanceY / distanceX);
        alfa = 90 + beta;
        return alfa;
    }
    // 180 - -90 -> third area
    else if (x <= cx && y >= cy) {
        beta = Math.atan(distanceY / distanceX);
        alfa = 270 - beta;
        return alfa;
    }
    // -90 - 0 -> forth area
    else if (x <= cx && y <= cy) {
        beta = Math.atan(distanceY / distanceX);
        alfa = 270 + beta;
        if (alfa == 360) {
            alfa = 0;
        }
        return alfa;    
    } 
    else {
        return -1;
    }
}
like image 3
Oguz Avatar answered Nov 14 '22 13:11

Oguz


The main catch with Atan2 is the center point. If your center is offset (Cx, Cy) and not at the origin and you want to find the arc angle between (X1, Y1) and (X2, Y2) then I would suggest this approach:

double startAngle = Math.Atan2(Y1-Cy, X1-Cx);
double endAngle = Math.Atan2(Y2-Cy, X2-Cx);
double ArcAngle = endangle - startAngle;
like image 1
Abhijit Dorage Avatar answered Nov 14 '22 13:11

Abhijit Dorage