迄今为止关于设计决策的一些背景......我开发了一种可以存储点的八叉树结构。我选择基于某个基本体素大小限制“世代”的递归。只有在将点添加到该节点时才会创建子节点。这是不是动态图形应用程序 - 这个八叉树及其中的对象是静态的,因此不需要考虑提高性能的预处理。
现在,我想在我的八叉树中添加“形状” - 特别是由三角形组成的表面网格。这些三角形的顶点不对应于存储在八叉树中的点。如何在八叉树中存储这些形状?我看到两个选择......
灰色节点“空”,因为它们没有形状。在备选方案1中,形状存储在它们相交的每个节点中 - 即,节点1a包含shape1和4c& 4d共享shape2。在备选方案2中,形状仅存储在它们相交的最小节点中 - 即,节点1a包含shape1,节点4包含shape2。
我见过的八角树上的大多数帖子都假设为Alt1,但它们从未解释过原因。 Alt2对我来说更有意义,只会为那些驻留在节点边界上的形状创建额外的工作。为什么Alt1更受欢迎?
编辑:为了澄清,我使用的实现语言是C ++,所以我更喜欢该语言的示例实现,但问题是与语言无关。对不起,如果标签使用不正确。
Edit2:虽然与形状存储问题没有直接关系,但this link对问题背后的八叉树遍历进行了很好的讨论。我认为这可能有助于任何有兴趣研究这个问题的人。
更新:四年后,Alt2最终变得更容易实现但速度非常慢,因为存储在更高八叉树级别的大三角形在八叉树的每次遍历中都经过测试 - 在我的情况下,这意味着数百到数千次不必要的测试。我最后修改了我的代码以使用R*-Tree variant代替,这很容易实现并且速度更快。
答案 0 :(得分:4)
ALT1是正确的。假设您要限制节点中对象(三角形)的最大数量,则需要细分包含许多三角形的节点。这不可避免地导致在多个节点中具有单个三角形,除非您想要细分三角形以使它们完全适合八叉树节点(这取决于您的应用,我通常不建议这样做,例如对于光线追踪,它确实通常不会完成)
作为一个反例,想象ALT2包含斯坦福兔子的详细模型,站在一个大三角形上。大三角形可以防止将根节点细分为子节点,因此你的八叉树就像你没有八叉树一样好。
或者,您必须将大三角形保留在根节点中,并将其细分为包含其余较小兔子三角形的子节点。不仅在叶节点中而且在其他节点中具有三角形可能使八叉树遍历变得复杂(但这也取决于您的应用)。如果我们坚持使用光线追踪场景,要找到光线和三角形的最近交点,就必须检查节点和所有子节点,以便找到最近的交叉点,你必须跟踪光线到下一个节点的移动,同时在所有树级上。另一方面,如果您的几何体仅在叶子中,则按照光线访问它们的顺序测试叶子中的三角形(同时跟踪已经测试过的三角形以避免测试相同的三角形两次)。
答案 1 :(得分:0)
这更多地参考了我更熟悉的quadtrees,但它们是八叉树的二维等价物;所以它可能适用。
插入的一般方法:四叉树的每个内部节点的容量是四叉树象限可以容纳的最大“对象”数。如果达到容量,则细分,然后将所有“对象”插入到相应的子象限中。您还将有一个细分,一个或多个“对象”跨越多个子象限;插入/查询时要小心这种情况。通常,选择节点容量以便更快地插入或查询。
因此,考虑到这一点,我发现您呈现的ALT2图像没有任何问题。但是我对你为什么总是看到ALT1图像的假设是插入未占用的单元格时的默认方法是细分然后插入。
答案 2 :(得分:0)
我有一个简单的C ++八叉树实现。该实现将节点细分为八个子节点,就像该特定节点中存在多个点一样。现在,我想对表面网格数据使用相同的八叉树,这意味着我想在八叉树数据结构中存储完整的几何信息。除此之外,我还有从.stl文件中提取的三角形信息。
我的问题几乎与几年前Phlucious的要求相似,但我不理解他的问题的完整讨论。