1

这是我过去几个小时一直在考虑的事情。这是一个头脑练习。

所以我今天知道了八叉树是什么!很有意思!我一直在考虑如何实现一个解析为体素的八叉树。

我现在无法解决的最大问题是引用八叉树中的位置。

免责声明:首先,我将在二维平面中使用四叉树来可视化我的问题。其次,我在这里不理解正确的术语,我将假设八叉树中作为父级的任何细分都是“分支”,而任何只有子级的细分(在这种情况下它解析为体素)是一片树叶”。第三,我要对四叉树的一个分支中的每个空间进行编号,从左到右从上到下 {1,2,3,4}

假设我有一个定义 16x16 单位空间的四叉树。在位置 [16,16] 我存储了一个体素。

4->4->4->4

现在假设我们将一个体素添加到位置 [4,4]。(注意,我们从零开始)

1->4->1->1
4->4->4->4

现在假设我想检查 [16,8] 以查看是否存储了体素。使用前面的方法,我们将在技术上遍历这些分支:

4->1->1->1

但是 4->1 没有分配任何数据,所以它是空的。(它没有细分,因为它没有在使用中)。

我的问题变成了这个,我怎样才能快速遍历四叉树找到体素?

我的第一个也是最简单的方法是以我上面使用的格式沿着分支向下移动。

// Pseudo-code
Class Quadtree {
Quadtree Parent;
Quadtree c[4]; // children
};

Quadtree test1;
test1.c[4].c[4].c[4].c[4];
Quadtree test2;
test2.c[1].c[4].c[1].c[1];

这里的问题是 voxelArray[16][16]、voxelArray[4][4] 或 voxelArray[16][8] 要快得多。使用更大的四叉树 (256x256) 会增加深度(从 4 到 8)。嵌套数组仍然是 2 个内存操作。(注意,对于四叉树,实际上我们将使用访问器的东西并检查以确保孩子存在条件逻辑)

我的第二个想法是将四叉树本身存储为体素。例如,假设我们有一个 2x2 数组,空它看起来像

{0, 0, 0, 0}

在位置 [1,1] 我们将添加一个体素,它会变成

{0, 0, 0, 1}

如果我们要存储四叉树,它看起来像这样

{1/*q*/, 0, 0, 0, 1}

把它带到一个 4x4 和

{0/*q*/, 0, 0, 0, 
 0/*q*/, 0, 0, 0, 
 0/*q*/, 0, 0, 0, 
 1/*q*/, 0, 0, 1}

尽管现在您可以直接访问数据,但您已经失去了四叉树的内存紧凑性,您仍然可以执行许多逻辑操作。IMO 仅当您有大面积的 0 和小范围的 1 时,这才会有效。

通过将体素存储在四叉树/八叉树中,您可以在循环遍历所有体素时获得性能,但在直接访问它们时会损失性能。

在此处输入图像描述

4

2 回答 2

1

您可以计算一个四键,然后散列每个体素。这个想法是降低维度的复杂性。例如,您可以寻找哈密顿路径或 z 曲线或希尔伯特曲线。这条路径完全穿过平面,但从技术上讲它仍然是一条曲线。

于 2012-04-10T09:59:32.963 回答
1

这更像是一个扩展的评论而不是一个答案。不过可能对你有帮助。或者它可能不会。你的例子:

{0, 0, 0, 0}

没有说明一个空的四叉树,它说明了一个四叉树,其中所有 4 个象限在第一(也是唯一的)级别都具有值 0。这个:

{}

说明了一个空的四叉树。这个:

{0, 0, 0, {1,0,1,0}}

说明了一个四叉树,其中 3 个象限都是 0,第四个是棋盘(虽然很小)。这个:

{{1,{1,0,0,0},0,{1,1,1,{0,0,0,1}}}, 0, 0, {1,0,1,0}}

开始变得棘手,但你现在明白我的意思了。

在某些语言(例如 Lisp、Matlab、Mathematica)中,这些插图可以直接实现和操作。在许多语言中,您会将四叉树实现为指针和/或值的集合。

于 2012-04-10T10:31:12.650 回答