找到比一组点中的给定距离(接近度)更近的对

时间:2014-07-25 22:23:27

标签: node.js algorithm indexing nearest-neighbor

我正在使用node.js开发多人游戏。每一秒我都得到每个玩家的坐标(X,Y,Z)。对于每个玩家,我如何能够获得距离他一定距离更近的所有玩家的列表?

是否有任何想法避免O(n²)计算?

3 个答案:

答案 0 :(得分:1)

您不是在寻找群集算法。

相反,您正在寻找支持半径查询的数据库索引

示例:

  • R * -tree
  • kd树
  • M-树
  • Gridfile
  • 八叉树(3d,四叉树,2d)

任何这些都应该成功,理论上会产生O(n log n)性能。在实践中,它并不像这样容易。如果你的所有物体都非常接近,那么#34;比给定的坐标更接近"可以指每个对象,即O(n ^ 2)。

答案 1 :(得分:1)

您正在寻找的是3维的四叉树,即八叉树。八叉树基本上与二叉树相同,但每个节点不是两个子节点,每个节点有2 ^ D = 2 ^ 3 = 8个子节点,其中D是维度。

例如,想象一个立方体。为了创建根的下一级,实际上每个节点都代表多维数据集中的8个子多维数据集,依此类推。

此树将产生快速查找,但请注意不要将其用于更多维度。我已经构建了一个多态四叉树,并且不会超过8-10维,因为它变得太平了。

另一种方法是 kd-tree ,实际上你在每一步都将数据集(玩家)减半。

您可以使用提供最近邻搜索的库。

答案 2 :(得分:1)

我回答了我自己的问题,因为我现在有了答案。感谢G. Samaras和Anony-Mousse: 我使用kd-tree算法:

  • 首先,我与所有玩家一起构建树
  • 然后,对于每个玩家,我计算该玩家
  • 范围内给定范围内所有玩家的列表

使用npm模块kdtree:https://www.npmjs.org/package/kdtree

,这非常快速和简单
var kd = require('kdtree');
var tree = new kd.KDTree(3); // A new tree for 3-dimensional points
var players = loadPlayersPosition(); // players is an array containing all the positions
for (var p in players){ //let's build the tree
    tree.insert(players[p].x, players[p].y, players[p].z, players[p].username);
}

nearest = [];    
for (var p in players){ //let's look for neighboors
    var RANGE = 1000; //1km range
    close = tree.nearestRange(players[p].x, players[p].y, players[p].z, RANGE);
    nearest.push(close);
}

它返回nearest,这是一个包含1000m范围内每个玩家所有邻居的阵列。我在PC上用100,000个模拟玩家进行了一些测试。构建树只需要500毫秒,另外500毫秒可以找到最近的neigboors对。对于这么多玩家来说,我发现它非常快。

奖励:如果你需要用纬度和经度而不是x,y,z来做这个,只需将lat,lon转换为笛卡尔x,yz,因为短距离球面上的弦距离〜大圆距离