在 3D 空间中查找所有相邻的单元格/立方体

Posted

技术标签:

【中文标题】在 3D 空间中查找所有相邻的单元格/立方体【英文标题】:Find all of adjacent cells/cubes in 3D-space 【发布时间】:2016-07-16 10:42:45 【问题描述】:

我将 3D 空间的一部分划分为一系列 1x1x1 的立方体,该部分的体积可能为 100^3 到 1000^3,但是,我真正感兴趣的立方体/单元很少超过 5000 -20000 他们的人数。

我要做的是找到所有满足我标准的单元格/立方体,与所选单元相邻。但是,我不确定哪种算法最适合此类任务。我想到的第一件事是使用常规的洪水填充算法,但出现了以下问题:我必须存储有关工作区域中所有单元格的信息,正如我所说,它可能有多达 1000^3 个元素,但我需要的只有5000-20000。

所以说我的问题是:

    如果我应该使用洪水填充,是否有任何数据结构可以用于我的情况? 如果我不应该使用洪水填充,我应该怎么做?

【问题讨论】:

我猜想最有效的方法将取决于选择包含哪些单元格的实际标准。标准是什么? 嗯...标准是气体密度,但我的具体任务要求我选择与其侧面相邻的单元格。 如果您的标准可以在每个访问的单元格上独立且有效地计算,那么您可以对感兴趣的单元格使用您喜欢的任何结构(例如vector)。但是 - 您是否有任何特定的顺序可以稍后处理感兴趣的细胞?如果是这样 - 您只需要确保从一开始就按预期顺序将感兴趣的单元格加载到容器中 不,顺序根本不重要,是的,我可以独立计算标准。但是,问题是我必须跟踪所有访问过的单元格,以防止再次回到那里。我当前的实现由向量组成,其中每个访问的单元格都已添加,还有一个单元格队列,其相邻单元格尚未添加。起初它工作得很好,但是随着向量中元素数量的增加,性能会随着时间的推移而下降,因此检查队列中附近元素是否已经添加的计算时间也会下降。 您可以将所有访问过的单元格存储在set<pair<int, int> >中,以显着加快检查单元格是否已被访问过。 【参考方案1】:

我将尝试重新表述需求:您想为每个单元格存储一些数据(布尔访问),而对于大多数单元格来说,它将是相同的(也没有访问过),因此您希望节省一些内存。

最近听说OpenVDB:http://www.openvdb.org/documentation/doxygen/

我没用过,但它看起来符合要求——它存储稀疏的体积数据,并声称内存和时间效率很高。

【讨论】:

不幸的是,他们的算法与我的差别不大,但我确实得到了性能提升,因为他们的代码更加优化。我想我必须坚持下去。【参考方案2】:

我认为这应该说明我对如何解决问题的想法。完成初始处理后,您还可以考虑将set 转移到vector(尽管严格来说,两种结构在完全迭代摊销速度方面相似)

set<pair<int, int> > getAllPointsToProcess(const pair<int, int>& initialCell) 
    set<pair<int, int> > activatedCells; // these will be returned
    queue<pair<int, int> > toProcess;
    toProcess.push(initialCell);
    activatedCells.insert(initialCell);
    int adjacentOffsets[][] = 1, 0, -1, 0, 0, 1, 0, -1;
    pair<int, int> currentlyProcessed;
    int neighbourCell;
    while (!toProcess.empty()) 
        currentlyProcessed = toProcess.front();
        toProcess.pop();
        for (int i = 0; i < 4; i++) 
             neighbourCell.first = currentlyProcessed.first + adjacentOffsets[i][0];
             neighbourCell.second = currentlyProcessed.second + adjacentOffsets[i][1];
             if (isActive(neighbourCell) && activatedCells.find(neighbourCell) == activatedCells.end()) 
                 toProcess.push(neighbourCell);
                 activatedCells.insert(neighbourCell);
             
        
    return activatedCells;
 

【讨论】:

【参考方案3】:

正如您所指出的,Flood-Fill algorithm 似乎与此问题有关。您面临的问题是存储有关所有立方体的信息,无论它们是否 访问与否

你有两个选择:

    为每个立方体保留哈希,空格: O(1000^3) 时间 : O(1) : 你不想要的 维护访问的立方体列表,空间:O(10000) 时间:O(100002) : 每次你需要检查这个多维数据集是否被访问时,只需遍历已访问多维数据集的完整列表。

这只是时空权衡

P.S:我希望我正确地解决了您的问题!

【讨论】:

以上是关于在 3D 空间中查找所有相邻的单元格/立方体的主要内容,如果未能解决你的问题,请参考以下文章

在 3D 空间中绘制立方体

在 3D 中查找 X、Y 和 Z 轴的角度 - OpenGL/C++

OpenGL 鼠标在 3D 空间中的位置

稀疏几何的 3d 希尔伯特曲线

Canvas实现3D效果-可旋转的立方体

wpf 空间坐标系下,画一个立方体轮廓