首页 文章

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

提问于
浏览
242

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

我认为图像描述的最符合我的要求:

no words can describe this

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

8 回答

  • 1

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

    from math import atan2,degrees
    
    def GetAngleOfLineBetweenTwoPoints(p1, p2):
        return degrees(atan2(p2 - p1, 1))
    
    print GetAngleOfLineBetweenTwoPoints(1,3)
    
  • 0

    基于参考“Peter O”..这是java版本

    private static final float angleBetweenPoints(PointF a, PointF b) {
    float deltaY = b.y - a.y;
    float deltaX = b.x - a.x;
    return (float) (Math.atan2(deltaY, deltaX)); }
    
  • 1

    对不起,但我很确定彼得的回答是错的 . 请注意,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)));
    

    45.0
    -45.0
    135.0
    -135.0
    

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

  • 0

    matlab功能:

    function [lineAngle] = getLineAngle(x1, y1, x2, y2) 
        deltaY = y2 - y1;
        deltaX = x2 - x1;
    
        lineAngle = rad2deg(atan2(deltaY, deltaX));
    
        if deltaY < 0
            lineAngle = lineAngle + 360;
        end
    end
    
  • 0

    角度从0到2pi的公式 .

    有x = x2-x1和y = y2-y1 . 该公式适用于

    x和y的任何值 . 对于x = y = 0,结果是未定义的 .

    f(x,y)= pi() - pi()/ 2 (1符号(x))(1符号(y ^ 2))

    -pi()/4*(2+sign(x))*sign(y)
    
         -sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
    
  • 0
    deltaY = Math.Abs(P2.y - P1.y);
    deltaX = Math.Abs(P2.x - P1.x);
    
    angleInDegrees = Math.atan2(deltaY, deltaX) * 180 / PI
    
    if(p2.y > p1.y) // Second point is lower than first, angle goes down (180-360)
    {
      if(p2.x < p1.x)//Second point is to the left of first (180-270)
        angleInDegrees += 180;
      else (270-360)
        angleInDegrees += 270;
    }
    else if (p2.x < p1.x) //Second point is top left of first (90-180)
      angleInDegrees += 90;
    
  • 49

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

    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) 只是为了获得 cossin 的正确角度可能是不优雅的 . 在这些情况下,您通常可以执行以下操作:

    • (deltaX, deltaY) 视为向量 .

    • 将该向量标准化为单位向量 . 为此,除非长度为0,否则将 deltaXdeltaY 除以向量的长度( sqrt(deltaX*deltaX+deltaY*deltaY) ) .

    • 之后, deltaX 现在将是矢量和水平轴之间角度的余弦(在 P1 处从正X到正Y轴的方向) .

    • deltaY 现在将成为那个角度的正弦 .

    • 如果向量's length is 0, it won' t与它的横轴之间有一个角度(因此它没有有意义的正弦和余弦) .

    编辑(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度) .


    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)
    

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

  • 379

    考虑到确切的问题,将我们置于“特殊”坐标系统中,其中正轴意味着向下移动(如屏幕或界面视图),您需要像这样调整此函数,并使Y坐标为负:

    Example in Swift 2.0

    func angle_between_two_points(pa:CGPoint,pb:CGPoint)->Double{
        let deltaY:Double = (Double(-pb.y) - Double(-pa.y))
        let deltaX:Double = (Double(pb.x) - Double(pa.x))
        var a = atan2(deltaY,deltaX)
        while a < 0.0 {
            a = a + M_PI*2
        }
        return a
    }
    

    此功能可以正确回答问题 . 答案是以弧度为单位,因此以度为单位查看角度的用法是:

    let p1 = CGPoint(x: 1.5, y: 2) //estimated coords of p1 in question
    let p2 = CGPoint(x: 2, y : 3) //estimated coords of p2 in question
    
    print(angle_between_two_points(p1, pb: p2) / (M_PI/180))
    //returns 296.56
    

相关问题