Reputation: 589
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
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
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
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
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
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