如何有效地计算两点之间的角度?

时间:2012-06-10 18:08:09

标签: c++ math optimization game-physics

我正在尝试在我的实验中优化模拟功能,这样我就可以在一次运行更多的人工脑控制代理。我分析了我的代码并发现我的代码中的大瓶颈是计算每个代理与每个代理的相对角度,即O(n 2 ),减去我做过的一些小优化。这是我用于计算角度的当前代码片段:

[C++]
double calcAngle(double fromX, double fromY, double fromAngle, double toX, double toY)
{
    double d = 0.0;
    double Ux = 0.0, Uy = 0.0, Vx = 0.0, Vy = 0.0;

    d = sqrt( calcDistanceSquared(fromX, fromY, toX, toY) );

    Ux = (toX - fromX) / d;

    Uy = (toY - fromY) / d;

    Vx = cos(fromAngle * (cPI / 180.0));
    Vy = sin(fromAngle * (cPI / 180.0));

    return atan2(((Ux * Vy) - (Uy * Vx)), ((Ux * Vx) + (Uy * Vy))) * 180.0 / cPI;
}

我有两个2D点(x 1 ,y 1 )和(x 2 ,y 2 )和“从”点(x a )的面对。我想计算代理x需要转动的角度(相对于它当前面向的)到面向代理y。

根据剖析器,最昂贵的部分是 atan2 。我用谷歌搜索了几个小时,上面的解决方案是我能找到的最佳解决方案。有谁知道一种更有效的方法来计算两点之间的角度?我愿意为速度牺牲一点精度(+/- 1-2度),如果这会影响任何事情。

5 个答案:

答案 0 :(得分:6)

正如评论中所提到的,可能存在降低计算负荷的高级方法。

但是对于手头的问题,你可以使用dot-product relationship

theta = acos ( a . b / ||a|| ||b|| )

其中ab是您的向量,.表示“点积”,|| ||表示“向量幅度”。

基本上,这会将{sqrtcossinatan2}替换为{sqrtacos}。< / p>

我还建议坚持使用弧度进行所有内部计算,只能转换为人类可读I / O的度数。

答案 1 :(得分:1)

你的评论说明了很多:&#34;我正在模拟每个代理人的180度额叶视网膜,所以我需要角度&#34;。不,你不是。您只需要知道位置矢量和视觉矢量之间的角度是大于还是小于90度。

非常容易:如果A和B之间的角度小于90度,则点积A·B> 0;如果角度精确地为90度,则为0;如果角度大于90度,则为<0。计算这需要3次乘法和2次加法。

答案 2 :(得分:0)

我认为这更像是一个数学问题:

abs(arctan((y1-yfrom)/(x1-xfrom)) - arctan(1 /((y2-yfrom2)/(x2-xfrom2))))

答案 3 :(得分:0)

使用这两个向量的dot product,最坏的情况是你需要做反余弦:

A =面向方向。 B =来自代理X的代理Y的方向

计算点是简单的乘法和加法。从那你就有角度的余弦。

答案 4 :(得分:0)

首先,您应该意识到有一些简化可以减少计算:

  1. 您无需计算从代理到自身的角度,
  2. 如果你有从代理i到代理j的角度,你已经知道了从代理j回到代理i的角度。
  3. 我不得不问:“代理人转向面对代理人j”是什么意思?如果两个表面看起来正确,你是否需要进行计算?你对“看对方”有什么宽容?

    如果你不再专注于数学并更全面地描述问题,那么建议做什么会更容易。