我正在使用node.js开发多人游戏。每一秒我都得到每个玩家的坐标(X,Y,Z)。对于每个玩家,我如何能够获得距离他一定距离更近的所有玩家的列表?
是否有任何想法避免O(n²)计算?
答案 0 :(得分:1)
您不是在寻找群集算法。
相反,您正在寻找支持半径查询的数据库索引。
示例:
任何这些都应该成功,理论上会产生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,因为短距离球面上的弦距离〜大圆距离