【问题标题】:Find the regions containing given coordinates查找包含给定坐标的区域
【发布时间】:2016-09-11 09:01:46
【问题描述】:

上下文:我正在为 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. 如果不是,则从阵列中删除该区域。如果为真,则转到 2。检查 Z 坐标,然后检查 Y。

此解决方案似乎适用于少数地区(不超过 20 个),但由于这将用于每秒可触发多次的事件,因此我希望能够使用更好的解决方案来做到这一点,它可以处理更多区域并更快完成。

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

你有什么想法吗?

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

【问题讨论】:

  • kd-tree 可能是一个不错的选择。查看this SO question
  • @NicoSchertler 您如何将它用于重叠区域?
  • @ValentinLorentz 与您将它用于任何类型的扩展对象的方式相同。如果平面与其相交,则拆分它们或将该区域放在两个子树中。
  • 我找到了解决方案:我使用了 R-Trees。我要写一个答案。

标签: java algorithm data-structures 3d


【解决方案1】:

我通过R-tree找到了解决方案

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

我测试了 2 个实现:

虽然 JSI 实现起来非常简单,但通过一个完整的示例,它需要添加 3 个 API 才能正常工作而不会出现错误/警告,并且仅适用于二维(仍然有用,因为 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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 2021-11-30
    • 1970-01-01
    相关资源
    最近更新 更多