【问题标题】:Performance of positioning voxels in an octree/quadtree在八叉树/四叉树中定位体素的性能
【发布时间】:2012-04-10 09:29:09
【问题描述】:

这是我过去几个小时一直在思考的问题。这是一种思维练习。

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

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

免责声明:首先,我将在 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}

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

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

【问题讨论】:

    标签: c++ performance algorithm quadtree octree


    【解决方案1】:

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

    【讨论】:

    • 您能详细说明一下吗?听起来您说“降低维度复杂性”是将其转换为一维字段/数组。那肯定会减少内存操作。我的第二种情况的实现不会使用带键的哈希来引用吗?从左到右、从上到下的算法不与 z 曲线或希尔伯特曲线相同吗?我的问题是可视化曲线如何穿过不同深度的分支。如果我向四叉树/八叉树添加新数据怎么办?我是否必须重新计算或移动整个曲线以适应?
    • 从左到右,从上到下的算法就像深度优先遍历。当您递归地将每个四边形分配给一条曲线时,z 曲线是一条递归曲线。您还可以分配数字(索引)并重新排序树。 z曲线和希尔伯特曲线是不一样的。它更复杂,尤其是希尔伯特曲线。你可以看看 L-System 是如何工作的。
    【解决方案2】:

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

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

    【讨论】:

    • 啊,我明白你的意思,但为了简单起见,我想清楚地形象化。我实际实现的可能会略有不同。即“指针和/或值的集合”
    猜你喜欢
    • 2017-01-09
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    相关资源
    最近更新 更多