如何计算直线与水平轴的夹角?

2024-04-19 16:13:27 发布

您现在位置:Python中文网/ 问答频道 /正文

在编程语言(Python,C#等)中,我需要确定如何计算直线与水平轴之间的夹角?

我认为一张图片最能描述我想要的东西:

no words can describe this

给定(P1x,P1y)和(P2x,P2y)计算此角度的最佳方法是什么?原点在左上角,仅使用正象限。


Tags: 方法水平图片编程语言直线角度象限原点
3条回答

首先找出起点和终点之间的区别(这里,这更多的是一条有向线段,而不是“直线”,因为直线无限延伸,而不是从某个特定点开始)。

deltaY = P2_y - P1_y
deltaX = P2_x - P1_x

然后计算角度(从P1的正X轴到P1的正Y轴)。

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

但是arctan可能并不理想,因为这样划分差异将消除区分角度所在象限所需的区别(见下文)。如果您的语言包含一个atan2函数,请使用以下内容:

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

编辑(2017年2月22日):然而,一般来说,仅仅为了获得cossin的正确角度而调用atan2(deltaY,deltaX)可能是不雅的。在这些情况下,您通常可以执行以下操作:

  1. (deltaX, deltaY)视为向量。
  2. 将该向量规格化为单位向量。为此,将deltaXdeltaY除以向量的长度(sqrt(deltaX*deltaX+deltaY*deltaY)),除非长度为0。
  3. 之后,deltaX将是向量和水平轴之间的夹角的余弦(在P1处从正X轴到正Y轴的方向)。
  4. 现在deltaY就是这个角度的正弦。
  5. 如果向量的长度为0,它与水平轴之间就没有夹角(因此它就没有有意义的正弦和余弦)。

编辑(2017年2月28日):即使没有规范化(deltaX, deltaY)

  • 符号deltaX将告诉您步骤3中描述的余弦是正的还是负的。
  • 符号deltaY将告诉您步骤4中描述的正弦是正的还是负的。
  • 符号deltaXdeltaY将告诉您相对于P1处的正X轴,角度在哪个象限中:
    • +deltaX+deltaY:0到90度。
    • -deltaX+deltaY:90到180度。
    • -deltaX-deltaY:180到270度(-180到-90度)。
    • +deltaX-deltaY:270到360度(-90到0度)。

使用弧度的Python实现(由编辑我的答案的Eric Leschinski于2015年7月19日提供):

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)

所有测试都通过了。见https://en.wikipedia.org/wiki/Unit_circle

我在Python中找到了一个运行良好的解决方案!

from math import atan2,degrees

def GetAngleOfLineBetweenTwoPoints(p1, p2):
    return degrees(atan2(p2 - p1, 1))

print GetAngleOfLineBetweenTwoPoints(1,3)

对不起,但我敢肯定彼得的回答是错的。请注意,y轴向下移动(在图形中很常见)。因此,德尔泰的计算必须颠倒,否则你会得到错误的答案。

考虑:

System.out.println (Math.toDegrees(Math.atan2(1,1)));
System.out.println (Math.toDegrees(Math.atan2(-1,1)));
System.out.println (Math.toDegrees(Math.atan2(1,-1)));
System.out.println (Math.toDegrees(Math.atan2(-1,-1)));

给予

45.0
-45.0
135.0
-135.0

因此,如果在上面的例子中,P1是(1,1),P2是(2,2)[因为Y在页面上增加],上面的代码将给出所示例子的45.0度,这是错误的。更改deltaY计算的顺序并使其正常工作。

相关问题 更多 >