从地平线获取一条直线的角度

8

我想知道如何从水平轴X获取线段A-B的角度。SO上的其他问题只涉及两条直线之间的角度。我知道我可以始终画第二条线段A-C并进行计算,但我想知道是否有更快的方法。

编辑:我非常确定我没有做过早的优化。


2
小心过早优化。你对代码进行了分析吗? - Charlie Salts
1
@VOX - 发布您的分析结果。向自己证明您需要更快的解决方案。 - Charlie Salts
1
“想要尽可能地让它快速”是问题所在。首先,您应该希望让它正常工作。然后,如果它的性能不令人满意,您可以找出问题所在并加以修复。 - Cogwheel
3
我相信这是一个合理的问题。答案如此简单易懂,没有理由不使用它。这并不是那种过早优化会让事情更难理解或更复杂的情况。实际上,这使事情更简单了。 - Justin L.
1
最近有人问我这个问题,结果发现他们后来所做的唯一事情就是计算角度的三角函数,比如sinecosine。如果在这种情况下是真的,并且你关心性能,那么你可能不应该实际计算角度。但是只有根据你打算用角度做什么才能做出建议。 - sigfpe
显示剩余3条评论
6个回答

12
你可以使用atan来实现此功能。
angle = atan((By-Ay)/(Bx-Ax))

11
    private double Angulo(int x1, int y1, int x2, int y2)
    {
        double degrees;

        // Avoid divide by zero run values.
        if (x2 - x1 == 0)
        {
            if (y2 > y1)
                degrees = 90;
            else
                degrees = 270;
        }
        else
        {
            // Calculate angle from offset.
            double riseoverrun = (double)(y2 - y1) / (double)(x2 - x1);
            double radians = Math.Atan(riseoverrun);
            degrees = radians * ((double)180 / Math.PI);

            // Handle quadrant specific transformations.       
            if ((x2 - x1) < 0 || (y2 - y1) < 0)
                degrees += 180;
            if ((x2 - x1) > 0 && (y2 - y1) < 0)
                degrees -= 180;
            if (degrees < 0)
                degrees += 360;
        }
        return degrees;
    }

2
如果你需要所有四个象限,Atan2比Atan更适合。
public static int GetAngleBetweenPoints(PointF pt1, PointF pt2)
{
    float dx = pt2.X - pt1.X;
    float dy = pt2.Y - pt1.Y;

    int deg = Convert.ToInt32(Math.Atan2(dy, dx) * (180 / Math.PI));
    if (deg < 0) { deg += 360; }

    return deg;
}

1

如果您的线条是以[r_x,r_y]的形式表示,其中r_x表示x方向的变化,r_y表示y方向的变化,您也可以使用arccosine函数。

angle = arccos( r_x/( r_x*r_x + r_y*r_y ) )

这个说法有点晦涩,但基本上是点积定理:

angle = arccos (r . v)

rv都是单位向量(长度为1的向量)。在我们的情况下,v是向量[1,0],而r

[r_x,r_y] / (r_x^2+r_y^2)

为了将其变成单位向量。

1

如果

  1. 角度很小,
  2. 可以容忍一些误差,并且
  3. 可以使用弧度而不是度数来表示角度,

那么就有一个快速的解决方案:在这些条件下,你可以假设 tan(a) = a = atan(a),因此可以省略掉 atan() 方法的调用。


"tan(a) = a = atan(a)" 嗯...什么意思? - Bart van Heukelom
@Bart van Heukelom: 是的,正如我所写的那样,这不是精确值,但对于小角度来说是一个很好的近似值。例如,tan(0.1)= 0.1003,tan(0.2)= 0.203因此,对于这个范围内的角度,如果您不需要绝对精度,可以节省一些计算量。 - Frank
是的,这似乎是真的。不过一旦角度大于约10度,不准确性就会变得太大了。我认为,如果你处理的是小角度,通常都需要最高的精度。 - Bart van Heukelom
@Bart:正如原帖中所提到的,对于有限资源下的性能表现非常重要,我只是想让他意识到这种优化可能性,这可能是问题的解决方案,因为他并没有提到角度的典型或最坏情况大小。 - Frank

0

横轴实际上是一条方程为

y = 0

的直线,因此您可以使用已有的解决方案。


我正在寻找更快(CPU 占用更少)的方法,如果有的话。 - VOX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接