在网格中使用顶点(2D和3D)查找边缘的算法

5

我有一个网格,其中包含某些类型的元素(例如三角形,四面体)。对于每个元素,我知道它的所有顶点,即2D三角形元素将具有3个顶点v1、v2和v3,其x、y、z坐标已知。

问题1

我正在寻找一种算法,可以返回所有的边... 在这种情况下:

edge(v1, v2), edge(v1, v3) , edge(v2, v3). 基于每个元素有多少个顶点,算法应有效地确定边。

问题2

我使用C++,因此,存储上述算法返回的边信息的最有效方式是什么?例如,我感兴趣的仅是一个元组(v1, v2),我想在进行一些计算之后就忘记它。

谢谢

3个回答

7
您可以使用半边数据结构。
基本上,您的网格也有一组边缘,并且每个方向上的每对顶点都有一个边缘结构。这意味着如果您有顶点A和B,则某处存储两个边缘结构,一个用于A->B,另一个用于B->A。每个边缘都有3个指针,一个称为previous,一个称为next,一个称为twin。遵循下一个和上一个指针可以沿着网格中三角形或多边形的边缘行走。调用twin将带您进入相邻多边形或三角形中的相邻边缘。(请看图片中的箭头)这是我知道的最有用和冗长的边缘数据结构。我已经使用它来通过创建新边缘并更新指针来平滑网格。顺便说一下,每个边缘还应该指向一个顶点,以便它知道在空间中的位置。

5
您的问题实际上包含三个部分,而不是两个:
- 应该使用哪些数据结构来表示网格? - 应该使用什么算法从网格数据结构中提取边缘? - 应该如何表示结果集中的边缘?
需要进一步提问才能找到合适的答案。 应该使用哪些数据结构来表示网格? 您需要处理哪些元素类型?
如果您只需要处理多边形(闭合循环)和简单形状(每个节点与元素中的其他节点都相连,例如四面体),则有序节点列表就足够了,因为可以从节点列表中推断出边缘。另一方面,如果您需要处理六面体、棱柱或一般的多面体等元素类型,则需要更多关于元素拓扑的信息。一个简单的边缘映射数组通常就足够了。它只是一个指向元素节点列表中的索引的数组 [][2],告诉您如何连接给定元素类型的节点。
Chris 描述的半边结构在仅限于 2D 时是一个不错的选择。在 3D 中,每个边缘可以连接任意数量的元素,而不仅仅是两个。我认为有一种名为 pinwheel 结构的半边表示的 3D 扩展。
如果您必须支持任意元素类型,我更喜欢使用更完整的数据结构来表示元素拓扑。一个常见的选项是使用边和共边。每对连接节点都有一个边结构,每个使用该边的元素都有一个共边。它类似于 pinwheel 方法,但更加明确。 应该使用什么算法从元素中提取边缘? 速度或内存有多重要?结果是否包括每个元素中的每条边缘,或者无论多少个元素使用它,只包括一次?结果中边缘的顺序是否重要?每个边缘的节点顺序是否重要?
对于任意元素类型,很难设计一个仅访问每个边缘一次的算法。为确保每条边仅出现一次,可以过滤结果,或者可以有点粗糙,对每个边缘保留一个“已访问”位,以确保不会将其两次放入结果中。 应该如何表示结果? 我将如何使用结果的方式有什么关系吗?
如果您要在计算密集型的计算中使用结果,那么一个大的坐标数组可能是最好的选择。您不希望在计算过程中反复获取节点坐标。但是,如果您正在过滤结果以删除重复的边缘,则比较坐标(对于节点对来说有6个双精度浮点数)并不是正确的方法。如果您正在过滤,请先生成指向边缘结构的指针列表,然后过滤掉重复项,然后再生成您的坐标列表。您也可以将此方法用于节点对,但是然后您必须针对每个边缘过滤两个可能的节点顺序,从而将过滤时间加倍。
如果内存比性能更重要,那么边缘指针列表也是一种好方法。但是,您不需要将边缘列表转换为坐标列表,而是在计算过程中查找坐标。这种方式获取节点坐标会比较慢,但是您避免了制作大量坐标列表 - 每个边缘只需存储一个指针而不是每个边缘存储6个双精度浮点数。
许多网格应用程序将所有坐标存储在一个大的全局数组中,每个节点都有一个索引指向该数组。如果是这种情况,那么将边缘列表转换为全局坐标数组的索引列表,而不是转换为坐标数组。性能应该与本地坐标数组差不多,但没有内存和人口过度开销。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接