Dave
Dave

Reputation: 589

Get angle between point and origin

This might have been answered before, sorry if it has. I basically need to get the angle from origin to point. So lets say Origin is (0, 0) and my target point is (3, 0).

3 O'clock = 90 degrees

6 O'clock = 180 degrees

9 O'clock = 270 degrees

12 O'clock = 0 degrees


Somehow, I gotta do some math magic, and find out that the angle is 90 degrees (Top is 0). The origin can vary, so I need a method with two parameters, Origin, and TargetPoint, which returns double Angle in Degrees.

Yea, I realize this looks short and nonconstructive, but I made the question as simple and understandable as possible. All the other questions were closed -.-

Thanks

Upvotes: 10

Views: 43143

Answers (5)

Jesse Williams
Jesse Williams

Reputation: 662

For whatever its worth to anyone who might still come to this post (it was toward the top of Google for me), I used Sebastian's Atan2 for my solution and it worked quite well. In my case, I'm programmatically generating parameterized primitives in Unity, so the origin point is always (0, 0, 0), whether the primitive is 2D or 3D (for the sake of Mesh vertices). So for a sphere, I needed to order all of the vertices in a specific way so that regardless of the parameters, an int[] could be properly built for the triangles needed for the mesh.

My sorting is done using:

this.vertices = vertList.OrderByDescending(o => o.y)
                        .ThenBy(o => Utilities.GetAngle(o)).ToArray();

And the GetAngle() method looks like this:

public static float GetAngle(Vector3 v)
{
    return Mathf.Atan2(0, 0) - Mathf.Atan2(v.z, v.x);
}

It works to sort the list of vertices from top to bottom (so a 1 unit sphere would have a "top" point at (0f, 0.5f, 0f), and that would be the first vertex), and then ordered by the resulting float from the angular calculation along the X- and Z-planes. This sorting works wonderfully and surprisingly quickly for Linq.

One additional note: because it ignores the Y-plane, it doesn't matter that each layer/level/band of vertices is at different points on the Y - it basically calculates each as if they were just at y = 0. If you were trying to sort across X/Y or Y/Z, you could do the same thing just omitting the plane you want to ignore.

This would likely not work in more complex situations, or where your origin is not (0, 0, 0), but worked at least for my case.

Upvotes: 0

Elolawyn
Elolawyn

Reputation: 173

Actually there is no way to find out the angle between point and origin due to the fact that the origin is (0,0). We can calculate the angle between 2 points beacuse they are treated like vectors and as such they have a direction, but the origin has no direction. For that reason, if you want to find the angle using the example of a clock you can calculate the angle between the point and (1,0) for example being that point at 0 degrees.

I'm sorry I'm not versed in C# but you can have a look at this java code which is similar:

double getAngle2PointsRad(double p1_x, double p1_y, double p2_x, double p2_y) {
  return Math.acos((((p1_x * p2_x) + (p1_y * p2_y)) / (Math.sqrt(Math.pow(p1_x, 2) + Math.pow(p1_y, 2)) * Math.sqrt(Math.pow(p2_x, 2) + Math.pow(p2_y, 2)))));
}

double getAngle2PointsDeg(double p1_x, double p1_y, double p2_x, double p2_y) {
  return Math.acos((((p1_x * p2_x) + (p1_y * p2_y)) / (Math.sqrt(Math.pow(p1_x, 2) + Math.pow(p1_y, 2)) * Math.sqrt(Math.pow(p2_x, 2) + Math.pow(p2_y, 2))))) * 180 / Math.PI;
}

If you try to calculate using (0,0) you will get NaN beacuse it tries to divide by zero.

Upvotes: 0

mirabilos
mirabilos

Reputation: 5346

Assuming x is positive, something like this:

angle = Math.Atan(y / x) * 180 / Math.PI + 90

Edited to allow for negative x values:

If it can be negative, just do it by case. Something like this:

if (x < 0) {
    angle = 270 - (Math.Atan(y / -x) * 180 / Math.PI);
} else {
    angle = 90 + (Math.Atan(y / x) * 180 / Math.PI);
}

Upvotes: 4

Ahmed KRAIEM
Ahmed KRAIEM

Reputation: 10427

public static double GetAngleDegree(Point origin, Point target) {
    var n = 270 - (Math.Atan2(origin.Y - target.Y, origin.X - target.X)) * 180 / Math.PI;
    return n % 360;
}

static void Main(string[] args)
{
    Console.WriteLine(GetAngleDegree(new Point(0, 0), new Point(0, 3)));//0
    Console.WriteLine(GetAngleDegree(new Point(0, 0), new Point(3, 0)));//90
    Console.WriteLine(GetAngleDegree(new Point(0, 0), new Point(0, -3)));//180
    Console.WriteLine(GetAngleDegree(new Point(0, 0), new Point(-3, 0)));//270 
}

Upvotes: 0

Sebastian Negraszus
Sebastian Negraszus

Reputation: 12205

The vector between two points A and B is B-A = (B.x-A.x, B.y-A.y). The angle between two vectors can be calculated with the dot product or atan2.

var vector2 = Target - Origin;
var vector1 = new Point(0, 1) // 12 o'clock == 0°, assuming that y goes from bottom to top

double angleInRadians = Math.Atan2(vector2.Y, vector2.X) - Math.Atan2(vector1.Y, vector1.X);

See also Finding Signed Angle Between Vectors

Upvotes: 21

Related Questions