【问题标题】:Neighbor Polygons from List of Polygon Indices多边形索引列表中的相邻多边形
【发布时间】:2012-02-09 09:59:23
【问题描述】:

我有一个类似this 的网格。 最后有一个代表每个多边形的索引列表。我需要为每个多边形生成一个相邻多边形的列表,并且想知道是否有人知道执行此操作的有效算法?

想到的最简单的方法是针对每个多边形,检查每个其他多边形是否有两个匹配的索引 - 但这看起来涉及一些嵌套循环。我不介意使用它,性能在这里不是一个大问题,但是我只是在寻找替代品。

每个多边形的最大索引/顶点数没有任何限制,但为简单起见,我们假设它为 3(即三角形多边形)。

感谢您的帮助! :)

【问题讨论】:

  • 感谢您的回答,我很怀疑 ;)

标签: 3d polygon mesh


【解决方案1】:

哎呀,XML 网格 :)。

我实际上已经很好地查看了这个,我的第一个答案很懒惰。你可以写得更好(如上所述),而且没那么复杂,我不会为此花 40 美元买一篇期刊文章。这是一个应该适合您的伪代码解决方案。

注意:当我说表格时,我的意思是“查找表”。

假设每个三角形都有编号,由顶点 v1、v2、v3 组成,它们是唯一编号的,可以使用

我们需要两个查找表:

  • 名为 edge_triangles 的边->(三角形列表)表。
  • 一个名为 triangle_edges 的三角形->(边列表)表。

一个表格告诉我们哪些三角形使用给定的边,另一个表格告诉我们给定三角形由哪些边组成。我们按如下方式构建这些列表:

for t = next triangle
    // Determine the ordering of vertices.
    min_vertex = min(t.v1, t.v2, t.v3);
    mid_vertex = median(p.v1, t.v2, t.v3);
    max_vertex = max(t.v1, t.v2, t.v3);

    // Register which edges this triangle uses.
    edge_triangles[min_vertex][mid_vertex].append(t);
    edge_triangles[mid_vertex][max_vertex].append(t);
    edge_triangles[min_vertex][max_vertex].append(t);

    // Set the edges that make up this triangle.
    triangle_edges[t].append({min_vertex, mid_vertex});
    triangle_edges[t].append({mid_vertex, max_vertex});
    triangle_edges[t].append({min_vertex, max_vertex});
for next t

使用这些列表,我们可以获取给定三角形中的边,将它们用作边表的键,并查看哪些多边形共享该边。因此,相邻的三角形。所以对于三角形 t,我们可以这样做:

adjacent = edge_faces[face_edges[t][0]];

这是“相邻等于共享三角形 t 的第 0 条边的三角形列表”的伪代码,其中第 0 条只是第一个。

我们使用最小值、中值和最大值来确保相同边没有不同的条目:例如 {v1, v2} 和 {v2, v1},其中 v1 和 v2 是两个顶点。我们实际上可以忽略这一点并添加一个“紧凑”步骤,在该步骤中我们连接对应于边列表中不同条目但实际上对应于同一边的列表。

另一个可能的问题是,如果您有两条重合但不共享公共顶点的边。在这种情况下,您可以将任一边简化为参数方程,比较它们是否重合,并形成一个查找表,告诉您对于给定边,哪些边是重合的,因此映射:

  • edge->(edges list) 表称为 edge_coincident_edges。

我们使用另一个查找表,因为我们无法连接 edge->faces 表。如果边 e1 和 e2 相邻,则考虑 e2 和 e3,但 e1 和 e3 不相邻。如果我们在 edge->face 列表中连接 e1、e2 和 e3 条目,你最终会得到一些非常不正确的数据。这可能比你想做的要多,但这是我今天早上必须解决的问题:)。

在每条边最多只能对应2个三角形的情况下,我们可以去掉传统意义上可以追加的'list',使用大小为2的固定大小的数组。这样可以减少您的内存开销并提高内存效率。所以我们的边缘表会更类似于:

  • 名为 edge_triangles 的边->(第一个三角形,第二个三角形)表。

无论如何,基本算法可以扩展到具有任意数量边的任意数量的多边形(所有多边形之间不一定相同),并且相对于三角形(或一般的多边形)的数量是 O(N) 时间案子)。空间复杂度为 O(E + N),其中 E 是边,N 是多边形的数量。假设您有良好的散列算法,查找时间应该接近 O(1)。

【讨论】:

  • 感谢利亚姆!它肯定会帮助很多人,包括我。它现在有点令人难以置信,但我会重新阅读它几次,直到我完全理解所涉及的过程。
  • 你的边集应该是 {min_vertex, mid_vertex}, {mid_vertex, max_vertex}, {max_vertex, min_vertex}。在构建边列表时,保持三角形中给出的顺序很重要。
【解决方案2】:

如果您只对三角网格(或 n-D 中的任何单纯形)感兴趣,那么实际上有更快的解决方案!您提出的建议的时间复杂度为 O(k^2),其中 k 是三角形的数量。这意味着对于大量三角形,计算邻居所需的时间是二次方的,这在大多数情况下计算量很大。

我建议您阅读 Ueng 和 Sikorski 的文章(“关于构建 3D FEA 数据邻接图的线性时间算法的说明”,视觉计算机 12:第 445-450 页,1996)。作者解释了用于在四面体网格中查找邻居的线性时间算法 O(k),从中您可以轻松推导出三角网格的类似算法。也许您也可以将其扩展到一般多边形!

让我知道这是否适合你!

【讨论】:

  • 感谢您的回答,这看起来很激烈!当我到了需要提高性能的阶段时,我一定会尝试一下。
  • 不客气!我一直在研究一个类似的问题,并且确实很少有关于这个特定问题的信息可以找到(至少对于我使用的关键字)......无论如何,很乐意提供帮助!
  • @HopsC 我也遇到过同样的问题,请参阅下面我的帖子,了解可以同时处理顶点邻接和真正几何邻接(需要额外步骤)的 O(N) 解决方案。
  • @Aralox 我添加了一个不那么糟糕的答案,让我知道您的想法 - 我认为它应该满足您对速度的需求:)。
  • @Liam 干得好 :) 这与 Ueng 和 Sikorski 的工作类似。但是,我有一个问题。在您提到“......我们可以获取给定三角形中的边,将其用作边列表中的键,并查看哪些多边形共享该边”,您的意思是对于每个三角形边您搜索一个查找表找到相邻的三重奏?因为这意味着如果您对多个多边形执行这样的例程,您仍然具有 O(N^2) 复杂性(当您遍历 N 行列表 N 次以查找邻居时)。 ...极品飞车:太好了! :)
【解决方案3】:

如果没有预先计算的数据,就不可能比遍历所有面孔更快。

对于预先计算的数据,每个顶点保存一个使用它的面列表就足够了。查找邻居是通过 2 个顶点的相交面列表完成的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-07
    • 2013-07-23
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-17
    相关资源
    最近更新 更多