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

How to efficiently calculate the angle between two points?

本文关键字:之间 两点 有效地 计算      更新时间:2023-10-16

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

[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, y1) 和 (x 2, y2) 以及"从"点 (xa) 的面向。我想计算代理 x 需要转动的角度(相对于其当前面向)以面对代理 y。

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

正如评论中提到的,可能有高级方法来减少计算负载。

但是对于手头的问题,你可以只使用点积关系:

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

其中ab是向量,.表示"点积",|| ||表示"向量幅度"。

从本质上讲,这会将你的 { sqrtcossinatan2 } 替换为 { sqrtacos }。

我还建议在所有内部计算中坚持使用弧度,只在人类可读的 I/O 中转换度数和从度数转换。

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

很简单:如果 A 和 B 之间的角度小于 90 度,则点积A·B为>0;如果角度正好为 90 度,则为 0;如果角度超过 90 度,则为 <0。计算这需要 3 次乘法和 2 次加法。

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

尝试

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

)))

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

A = 朝向方向。B = 代理 Y 与代理 X 的方向

计算点是简单的乘法和加法。由此你就有了角度的余弦。

对于初学者来说,您应该意识到有一些简化可以稍微减少计算:

  1. 你不需要计算从代理到它本身的角度,
  2. 如果你有从代理 i 到代理 j 的角度,你已经知道从代理 j 回到代理 i 的角度。

不得不问:"特工我转向面对特工J"是什么意思? 如果两个表面正视对方,您是否必须进行计算? 你对"直视对方"有什么容忍度?

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