XamDev89
XamDev89

Reputation: 203

Calculate degrees of angle using x, y coordinates

My goal is to calculate the drag of a users finger around a center point of a scren and I've tried a few bad attempts using Math.Atan2(). FYI I am using SkiaSharp in Xamarin applications but to keep things simple I just need help with the below scenario.

Using the below screenshot could someone tell me the best way to produce the below results?

A = 0 degrees

B = 90 degrees

C = 180 degrees

D = 270 degrees

enter image description here

Upvotes: 5

Views: 5203

Answers (1)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112259

Showing us the code returning the wrong result would reveal us where the problem is and allow us to give you more specific advice.

  1. Since you want the angle relative to the center, you must subtract the center coordinates from your points.

  2. Math.Atan2 yields radians. Convert them to degrees with degrees = radians * 180 / pi.

  3. Your zero angle is not as usual on the x-axis, but on the y-axis. Add 90 degrees to make the correction.

Using a vector type makes things easier. Here I will be using the System.Numerics.Vector2 struct.

As Patrick McDonald pointed out, Atan2 might yield negative results in some cases. By adding 450 degrees (360 + our 90 degrees correction) to the result and taking this modulo 360 degrees, you always get a value between 0 and 360.

public static float GetAngle(Vector2 point, Vector2 center)
{
    Vector2 relPoint = point - center;
    return (ToDegrees(MathF.Atan2(relPoint.Y, relPoint.X)) + 450f) % 360f;
}

public static float ToDegrees(float radians) => radians * 180f / MathF.PI;

The test

var a = new Vector2(7, 3);
var b = new Vector2(20, 7);
var c = new Vector2(7, 10);
var d = new Vector2(3, 7);
var e = new Vector2(6.9f, 3); // Test for more than 270 deg.
var f = new Vector2(7.1f, 3); // Test for small angle.

var center = new Vector2(7, 7);

PrintAngle(a); // ==>   0
PrintAngle(b); // ==>  90
PrintAngle(c); // ==> 180
PrintAngle(d); // ==> 270
PrintAngle(e); // ==> 358.5679
PrintAngle(f); // ==>   1.432098


void PrintAngle(Vector2 point)
{
    Console.WriteLine(GetAngle(point, center));
}

Upvotes: 10

Related Questions