在八叉树/四叉树中定位体素的性能

时间:2012-04-10 09:29:10

标签: c++ performance algorithm quadtree octree

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

所以我学到了八卦今天!很有意思!我一直在思考如何实现一个解析为体素的八叉树。

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

免责声明:首先,我将在2D平面中使用四叉树来可视化我的问题。其次,我不明白这里的正确术语,我将假设八叉树中的任何细分是父母是一个“分支”,任何只是一个孩子的细分(在这种情况下它解析为体素)是一片树叶”。第三,我将从四个树的一个分支中从左到右从上到下对每个空间进行编号{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}

虽然现在你可以直接访问数据,但是你已经失去了四叉树的内存紧凑性,你仍然可以执行许多逻辑操作。如果您有大的0区域和1s的小分组,那么IMO只能很好地工作。

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

enter image description here

2 个答案:

答案 0 :(得分:1)

您可以计算一个四核,然后散列每个体素。这个想法是降低尺寸复杂性。您可以查看哈密尔顿路径或z曲线或希尔伯特曲线的示例。这条路径完全穿过飞机,但技术上仍然是一条曲线。

答案 1 :(得分: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)中,这些插图可以直接实现和操作。在许多语言中,您将四叉树实现为指针和/或值的集合。