上下文:我正在为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]
我现在正在做的是:
这个解决方案对于一些地区(不超过20个)似乎是可行的,但由于这将用于可以每秒触发多次的事件,我希望能够通过更好的解决方案做到这一点,处理更多区域并更快地完成。
我看了Data structures that can map a range of values to a key?,但我的地区可以重叠,所以我不能这样用。
你有什么想法吗?
我不想使用Worldedit / Worldguard API,但“通用”Java API很好。
答案 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]