我正在进行植绒boids模拟,只是为了好玩,我想稍微优化一下。 需要工作的区域是在给定的boid附近找到boids。我认为要做到这一点,某种适合任务的空间数据结构将是我最好的选择(参见here并向下滚动一下。)。
无论我采用什么,我都会从头开始用Java实现自己。这样我就可以学到更多关于我选择的数据结构的知识,而不是我刚刚调用了一堆库函数。
我知道R-Trees,k-d trees和Quadtrees。在我看来,它们都是可行的选择。但我对这些数据结构没有任何经验,我不完全确定最适合我的目的。 我this scale上不需要任何东西 - 我说的可能只有几百个,也许最多只有一千个,而不是一百万个,但请记住,我最终可能最终会在Android手机上运行它。
请为此推荐一个数据结构(当然不限于上述内容),并给我一个很好的理由选择它。
是的,我见过this question。不,我对答案不满意 - 根本没有任何理由。
哦,另外一件事 - 就像标题所说的那样,这仅仅是针对两个维度的。
答案 0 :(得分:0)
老实说,我会从一个未经优化的版本开始,看看你能走多远(多少个boid)。之后,尝试不同的方法并衡量它们之间的差异。我认为这是最好的学习方式。
答案 1 :(得分:0)
四叉树是一种非常标准的数据结构,用于视频游戏中的命中检测。我认为这非常适合您的目标。
答案 2 :(得分:0)
九年太晚了,无法帮助 Iskar Jarak 但我会插话,因为其他人可能会在搜索中找到这个老问题。
关键在于,几乎任何事情都比查看每对 boid 的朴素 O(n²) 方法要好。所以正如 Iskar 所说,任何一种基于树的空间数据结构都是一个巨大的改进,基本上是 O(n log n)。也就是说:每个 n 类都需要查找它的邻居,每个类都是 O(log n)。
需要注意的是,Desmond Vehar 提到的“命中检测”是一个稍微不同的问题,它询问“这个查询位置是否在我的数据结构中的任何‘对象’中?”在多代理模拟中,我们希望找到多个邻居。有时“最近的 N 个邻居”或“查询位置给定半径内的所有邻居”。通常将一个 boid 描述为其中心点并通过点之间的距离进行过滤,从而产生一个“查询球体”就足够了。
在他的算法课程中,Tim Roughgarden 不断问“我们能做得更好吗?”事实上——虽然 O(log n) 在查找邻居方面比 O(n) 更好——但最好的是恒定时间查找,O(1)。这里的哈希表(又名未排序映射)是我们的朋友。
多邻居和散列这两个想法导致了一种加速多代理模拟的好方法:空间散列到体素(/boxes/lattices)。每个体素包含一组 boids/agents。代理的连续空间位置(通常是 2 或 3 个浮点数)被转换为体素坐标(2 或 3 个整数,通过缩放的“地板”操作),它们被散列在一起以产生一个“体素 ID”,用作体素哈希表中的键。因此,在 O(1) 恒定时间内,就像数组引用一样,您可以查找包含当前在同一体素中的所有代理的集合的体素。 “查询球体”通常会重叠多个体素。这些可以通过将查询点偏移体素间距距离的倍数来找到。这几个体素的内容合并在一起形成潜在邻居的集合,然后按距离过滤。当 agent/boid 移动时,他们会比较他们的新旧“体素 ID”,如果不相等,他们将自己从数据结构中移除,然后在新位置重新插入。
资源:
大约有无数种“空间数据结构”/“空间数据库”。有关调查,请参阅此维基百科文章:Spatial database。另请参阅 Hanan Samet 的早期论文:1989 年的 Hierarchical Spatial Data Structures 和 1995 年的 Spatial Data Structures。
在 2000 年代初期我自己的工作中,我使用了固定大小的体素集合,以 i,j,k 坐标表示: Interaction with Groups of Autonomous Characters 于 2000 年,Big Fast Crowds on PS3 于 2006 年。后来,我转而使用“空间散列到体素”的方法,这种方法不需要先验规范 3d 体素网格维度,并且零开销用于具有许多空体素的稀疏代理分布。