我正在尝试在我的实验中优化模拟功能,这样我就可以在一次运行更多的人工脑控制代理。我分析了我的代码并发现我的代码中的大瓶颈是计算每个代理与每个代理的相对角度,即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度),如果这会影响任何事情。
答案 0 :(得分:6)
正如评论中所提到的,可能存在降低计算负荷的高级方法。
但是对于手头的问题,你可以使用dot-product relationship:
theta = acos ( a . b / ||a|| ||b|| )
其中a
和b
是您的向量,.
表示“点积”,|| ||
表示“向量幅度”。
基本上,这会将{sqrt
,cos
,sin
,atan2
}替换为{sqrt
,acos
}。< / 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)
答案 4 :(得分:0)
首先,您应该意识到有一些简化可以减少计算:
我不得不问:“代理人转向面对代理人j”是什么意思?如果两个表面看起来正确,你是否需要进行计算?你对“看对方”有什么宽容?
如果你不再专注于数学并更全面地描述问题,那么建议做什么会更容易。