Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate the angle between a line and the horizontal axis?

In a programming language (Python, C#, etc) I need to determine how to calculate the angle between a line and the horizontal axis?

I think an image describes best what I want:

no words can describe this

Given (P1x,P1y) and (P2x,P2y) what is the best way to calculate this angle? The origin is in the topleft and only the positive quadrant is used.

like image 960
orlp Avatar asked Sep 28 '11 15:09

orlp


People also ask

How do you find the angle between a line and a plane?

To calculate the angle between a line and a plane a normal is drawn perpendicular to the plane at the point of contact with the line. The angle between the line and the plane is calculated as the complement of the angle between the line and the normal drawn to the plane.

What is the formula of angle between the lines?

Formulas for Angle Between Two Lines The angle between two lines, of which one of the line is y = mx + c and the other line is the x-axis, is θ = Tan-1m.


1 Answers

First find the difference between the start point and the end point (here, this is more of a directed line segment, not a "line", since lines extend infinitely and don't start at a particular point).

deltaY = P2_y - P1_y deltaX = P2_x - P1_x 

Then calculate the angle (which runs from the positive X axis at P1 to the positive Y axis at P1).

angleInDegrees = arctan(deltaY / deltaX) * 180 / PI 

But arctan may not be ideal, because dividing the differences this way will erase the distinction needed to distinguish which quadrant the angle is in (see below). Use the following instead if your language includes an atan2 function:

angleInDegrees = atan2(deltaY, deltaX) * 180 / PI 

EDIT (Feb. 22, 2017): In general, however, calling atan2(deltaY,deltaX) just to get the proper angle for cos and sin may be inelegant. In those cases, you can often do the following instead:

  1. Treat (deltaX, deltaY) as a vector.
  2. Normalize that vector to a unit vector. To do so, divide deltaX and deltaY by the vector's length (sqrt(deltaX*deltaX+deltaY*deltaY)), unless the length is 0.
  3. After that, deltaX will now be the cosine of the angle between the vector and the horizontal axis (in the direction from the positive X to the positive Y axis at P1).
  4. And deltaY will now be the sine of that angle.
  5. If the vector's length is 0, it won't have an angle between it and the horizontal axis (so it won't have a meaningful sine and cosine).

EDIT (Feb. 28, 2017): Even without normalizing (deltaX, deltaY):

  • The sign of deltaX will tell you whether the cosine described in step 3 is positive or negative.
  • The sign of deltaY will tell you whether the sine described in step 4 is positive or negative.
  • The signs of deltaX and deltaY will tell you which quadrant the angle is in, in relation to the positive X axis at P1:
    • +deltaX, +deltaY: 0 to 90 degrees.
    • -deltaX, +deltaY: 90 to 180 degrees.
    • -deltaX, -deltaY: 180 to 270 degrees (-180 to -90 degrees).
    • +deltaX, -deltaY: 270 to 360 degrees (-90 to 0 degrees).

An implementation in Python using radians (provided on July 19, 2015 by Eric Leschinski, who edited my answer):

from math import * def angle_trunc(a):     while a < 0.0:         a += pi * 2     return a  def getAngleBetweenPoints(x_orig, y_orig, x_landmark, y_landmark):     deltaY = y_landmark - y_orig     deltaX = x_landmark - x_orig     return angle_trunc(atan2(deltaY, deltaX))  angle = getAngleBetweenPoints(5, 2, 1,4) assert angle >= 0, "angle must be >= 0" angle = getAngleBetweenPoints(1, 1, 2, 1) assert angle == 0, "expecting angle to be 0" angle = getAngleBetweenPoints(2, 1, 1, 1) assert abs(pi - angle) <= 0.01, "expecting angle to be pi, it is: " + str(angle) angle = getAngleBetweenPoints(2, 1, 2, 3) assert abs(angle - pi/2) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle) angle = getAngleBetweenPoints(2, 1, 2, 0) assert abs(angle - (pi+pi/2)) <= 0.01, "expecting angle to be pi+pi/2, it is: " + str(angle) angle = getAngleBetweenPoints(1, 1, 2, 2) assert abs(angle - (pi/4)) <= 0.01, "expecting angle to be pi/4, it is: " + str(angle) angle = getAngleBetweenPoints(-1, -1, -2, -2) assert abs(angle - (pi+pi/4)) <= 0.01, "expecting angle to be pi+pi/4, it is: " + str(angle) angle = getAngleBetweenPoints(-1, -1, -1, 2) assert abs(angle - (pi/2)) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle) 

All tests pass. See https://en.wikipedia.org/wiki/Unit_circle

like image 162
Peter O. Avatar answered Sep 22 '22 17:09

Peter O.