这可能看起来像一个简单的问题,但我现在看不到其他路线了。没有太多不必要的细节,一般概念如下:
我在一个包含的三维空间内有一个实体(想想粒子)的很多实例。初始实例的数量可以从所述粒子的10到1000变化,每个粒子用它的识别号初始化,并且它是自己的x,y和z坐标。粒子可以随时移动,因此这里的目标是能够尽可能快地检查任何两个粒子是否在彼此的预设接近距离内(在任何方向上)。我能想到的最简单但不幸的不优雅/慢速方法是嵌入循环,如下所示:
for(int i = 0; i < upper; i++)
{
for(int j = 0; j < upper; j++)
{
//If within proximity
if(sqrt( ((entity1.x[i] - entity2.x[j])*(entity1.x[i] - entity2.x[j])) + ((entity1.y[i] - entity2.y[j])*(entity1.y[i] - entity2.y[j])) + ((entity1.z[i] - entity2.z[j])*(entity1.z[i] - entity2.z[j])) ) <= proximity )
{
//Perform function
}
}
}
这是我在代码中的实际循环。我正在使用3维度中的距离公式,看看所述距离是否小于预定的接近度。如果它们在那个距离内,那么我执行一个功能。目前我的功能实际上什么都不做,所以我可以只看循环本身的时间,而不用担心里面的算法。我知道每个系统的时间会有所不同,但我的系统至少是高于平均水平,如果不是更好,这个循环大约需要5秒才能完成,而且这个上限设置为100个循环。有没有更快的算法来做到这一点?或者我在这个循环中做了一些非常低效的事情?我能做得越快越好。
感谢您的帮助, DevenJ
答案 0 :(得分:3)
这里要说的一件事是,如果速度很重要,你不应该使用平方根进行计算。更好的方法是平方接近值并移除平方根。
您还需要确保不重复计算。例如,考虑下面的方法
for(int i = 0; i < upper; i++)
{
for(int j = 0; j < upper; j++)
{
if(i < j)
{
//do stuff
}
}
}
但二进制八叉树是一种更好的解决方案,尽管它们需要更高的算法知识。
答案 1 :(得分:2)
您可以通过设置
删除在循环中使用sqrt()的需要proximity = proximity * proximity;
在循环之前。
答案 2 :(得分:1)
将实体存储在分隔空间的数据结构中,可以消除包含接近区域的分区中未包含的任何粒子。二进制空间分区,四叉树和八叉树对此非常有用。
答案 3 :(得分:1)
对于正值,如果是a <= b
,则为a^2 <= b^2
。
平方根操作保留了两个值之间的顺序。因此,只需在循环前将您的接近度平方以匹配平方幅度。