查找包含给定坐标

时间:2016-05-15 14:06:24

标签: java algorithm data-structures 3d

上下文:我正在为Spigot(Minecraft服务器插件)开发一个插件。

我想为多种目的定义几个区域。我将它们存储在这样的配置文件中(YAML):

Regions
  Region1:
    P1:
      X: 0
      Y: 0
      Z: 0
    P2:
      X: 1
      Y: 1
      Z: 1
  Region2:
    P1:
      X: -1
      Y: -1
      Z: -1
    P2:
      X: 2
      Y: 2
      Z: 2

如您所见,我正在存储具有2个相反坐标的区域。

我试图提出一种算法,而不是在数组中存储包含给定坐标的所有区域。

例如,(0,0,0) => [Region1, Region2](2,2,2) => [Region1]

我现在正在做的是:

  1. 对包含所有区域的数组进行人口统计
  2. 检查X坐标是否在定义区域的2 X坐标之间
  3. 如果没有,请从阵列中删除该区域。如果为true,则转到2.并检查Z坐标,然后选择Y。
  4. 这个解决方案对于一些地区(不超过20个)似乎是可行的,但由于这将用于可以每秒触发多次的事件,我希望能够通过更好的解决方案做到这一点,处理更多区域并更快地完成。

    我看了Data structures that can map a range of values to a key?,但我的地区可以重叠,所以我不能这样用。

    你有什么想法吗?

    我不想使用Worldedit / Worldguard API,但“通用”Java API很好。

1 个答案:

答案 0 :(得分:1)

我使用R-tree

找到了解决方案
  

R树是用于空间访问方法的树数据结构,即用于索引诸如地理坐标,矩形或多边形的多维信息。

我测试了2个实现:

虽然JSI实现起来非常简单,但有一个完整的例子,它需要添加3个API才能正常工作,没有错误/警告,并且仅适用于2个维度(仍然有用,因为Y坐标对我的使用并不相关在我的Minecraft插件中。)

所以我使用了第二个实现,因为它可以处理多个维度,使用任何对象作为条目,并且只使用一个类。

这是我的代码(用于搜索包含点的所有区域的小测试):

private static final float[] ZEROES = { 0.0f, 0.0f, 0.0f };
private static final float[] POINT_FIVES = { 0.5f, 0.5f, 0.5f };
private static final float[] ONE_FIVES = { 1.5f, 1.5f, 1.5f };
private static final float[] ONES = { 1.0f, 1.0f, 1.0f };

public static void main(String[] args) {
    RTree<Object> rt = new RTree<Object>(50, 2, 3);
    rt.insert(ZEROES, ONES, "Region1");
    rt.insert(ONES, ONES, "Region2");

    System.out.println(rt.search(POINT_FIVES, ZEROES));

}

输出结果为:

  

[区域1]