2024-04-19 16:13:27 发布
网友
在编程语言(Python,C#等)中,我需要确定如何计算直线与水平轴之间的夹角?
我认为一张图片最能描述我想要的东西:
给定(P1x,P1y)和(P2x,P2y)计算此角度的最佳方法是什么?原点在左上角,仅使用正象限。
首先找出起点和终点之间的区别(这里,这更多的是一条有向线段,而不是“直线”,因为直线无限延伸,而不是从某个特定点开始)。
deltaY = P2_y - P1_y deltaX = P2_x - P1_x
然后计算角度(从P1的正X轴到P1的正Y轴)。
P1
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
但是arctan可能并不理想,因为这样划分差异将消除区分角度所在象限所需的区别(见下文)。如果您的语言包含一个atan2函数,请使用以下内容:
arctan
atan2
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
编辑(2017年2月22日):然而,一般来说,仅仅为了获得cos和sin的正确角度而调用atan2(deltaY,deltaX)可能是不雅的。在这些情况下,您通常可以执行以下操作:
cos
sin
atan2(deltaY,deltaX)
(deltaX, deltaY)
deltaX
deltaY
sqrt(deltaX*deltaX+deltaY*deltaY)
编辑(2017年2月28日):即使没有规范化(deltaX, deltaY):
+deltaX
+deltaY
-deltaX
-deltaY
使用弧度的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计算的顺序并使其正常工作。
首先找出起点和终点之间的区别(这里,这更多的是一条有向线段,而不是“直线”,因为直线无限延伸,而不是从某个特定点开始)。
然后计算角度(从
P1
的正X轴到P1
的正Y轴)。但是
arctan
可能并不理想,因为这样划分差异将消除区分角度所在象限所需的区别(见下文)。如果您的语言包含一个atan2
函数,请使用以下内容:编辑(2017年2月22日):然而,一般来说,仅仅为了获得
cos
和sin
的正确角度而调用atan2(deltaY,deltaX)
可能是不雅的。在这些情况下,您通常可以执行以下操作:(deltaX, deltaY)
视为向量。deltaX
和deltaY
除以向量的长度(sqrt(deltaX*deltaX+deltaY*deltaY)
),除非长度为0。deltaX
将是向量和水平轴之间的夹角的余弦(在P1
处从正X轴到正Y轴的方向)。deltaY
就是这个角度的正弦。编辑(2017年2月28日):即使没有规范化
(deltaX, deltaY)
:deltaX
将告诉您步骤3中描述的余弦是正的还是负的。deltaY
将告诉您步骤4中描述的正弦是正的还是负的。deltaX
和deltaY
将告诉您相对于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日提供):
所有测试都通过了。见https://en.wikipedia.org/wiki/Unit_circle
我在Python中找到了一个运行良好的解决方案!
对不起,但我敢肯定彼得的回答是错的。请注意,y轴向下移动(在图形中很常见)。因此,德尔泰的计算必须颠倒,否则你会得到错误的答案。
考虑:
给予
因此,如果在上面的例子中,P1是(1,1),P2是(2,2)[因为Y在页面上增加],上面的代码将给出所示例子的45.0度,这是错误的。更改deltaY计算的顺序并使其正常工作。
相关问题 更多 >
编程相关推荐