orl*_*rlp 246 c# python trigonometry
在编程语言(Python,C#等)中,我需要确定如何计算直线和水平轴之间的角度?
我认为图像描述的最符合我的要求:

给定(P1 x,P1 y)和(P2 x,P2 y)计算此角度的最佳方法是什么?原点在于topleft,只使用正象限.
Pet*_* O. 383
首先找到起点和终点之间的差异(这里,这更像是有向线段,而不是"线",因为线无限延伸而不是从特定点开始).
deltaY = P2_y - P1_y
deltaX = P2_x - P1_x
Run Code Online (Sandbox Code Playgroud)
然后计算角度(从正X轴P1到正Y轴P1).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
Run Code Online (Sandbox Code Playgroud)
但arctan可能并不理想,因为以这种方式划分差异将消除区分角度所在的象限所需的区别(见下文).如果您的语言包含以下atan2功能,请使用以下内容:
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
Run Code Online (Sandbox Code Playgroud)
编辑(2017年2月22日):然而,一般来说,atan2(deltaY,deltaX)只是为了获得适当的角度cos而且sin可能是不优雅的.在这些情况下,您通常可以执行以下操作:
(deltaX, deltaY)作为矢量对待.deltaX和deltaY由向量的长度(sqrt(deltaX*deltaX+deltaY*deltaY)),除非长度为0.deltaX现在将是矢量和水平轴之间角度的余弦(在从正X到正Y轴的方向上P1).deltaY现在将是角度的正弦值.编辑(2017年2月28日):即使没有正常化(deltaX, deltaY):
deltaX将告诉您步骤3中描述的余弦是正还是负.deltaY将告诉您步骤4中描述的正弦是正还是负.deltaX和deltaY将告诉您角度所在的象限,相对于正X轴P1:
+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)
Run Code Online (Sandbox Code Playgroud)
所有测试都通过.请参阅https://en.wikipedia.org/wiki/Unit_circle
小智 50
对不起,但我很确定彼得的回答是错的.请注意,y轴沿着页面向下(图形中常见).因此,deltaY计算必须反转,否则你会得到错误的答案.
考虑:
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)));
Run Code Online (Sandbox Code Playgroud)
给
45.0
-45.0
135.0
-135.0
Run Code Online (Sandbox Code Playgroud)
因此,如果在上面的例子中,P1是(1,1)而P2是(2,2)[因为Y向下增加页面],上面的代码将给出所示示例的45.0度,这是错误的.更改deltaY计算的顺序,它可以正常工作.