c# - 如何计算直线与水平轴之间的角度?

标签 c# python trigonometry

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

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

no words can describe this

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

最佳答案

首先找出起点和终点之间的差异(这里,这更像是一条有向线段,而不是一条“线”,因为线无限延伸并且不从特定点开始)。

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 日):但是,通常调用 atan2(deltaY,deltaX) 只是为了获得 cos 的正确角度sin 可能不优雅。在这些情况下,您通常可以改为执行以下操作:

  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

关于c# - 如何计算直线与水平轴之间的角度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7586063/

相关文章:

c# - Byte[] 作为 Json 中的参数

c# - 使用 Dapper 获取 nvarchar(max) 返回一个被修剪为 4000 个字符的字符串。这种行为可以改变吗?

python - 在 Networkx (Python) 中绘制节点值?

c# - Pushsharp 支持 Apple Push Notification Authentication Key

c# - PredicateBuilder.New 与 PredicateBuilder.True

python - 我的代码抛出有关 NoneType 的错误,但应该定义它

python - 将 python 列表列表转换为 rpy2 中的 R 向量列表

java - 如何获得 Cos 和 Tan 函数的用户友好值?

javascript - 如何计算垂直于矢量的圆?

ios - 在 Objective-C 中创建方波、锯齿波和三角波