关于C ++:从“三角形汤”中查找唯一顶点

 2020-11-25 

Find unique vertices from a 'triangle-soup'

我正在两个库(Opencascade和DWF Toolkit)的顶部构建一个CAD文件转换器。

但是,我的问题与平台无关:

鉴于:

我已经生成了一个网格,作为通过我的应用程序构建的模型的一系列三角形面的列表。每个三角形是通过三个顶点定义的,三个顶点由三个浮点数(x,y和z坐标)组成。由于三角形形成网格,因此大多数顶点由一个以上的三角形共享。

目标:

我需要找到唯一顶点的列表,并生成一个由该列表中三个索引的元组组成的面数组。

我想做的是这样的:

1
2
3
4
5
6
7
8
9
10
11
//step 1: build a list of unique vertices
for each triangle
   for each vertex in triangle
      if not vertex in listOfVertices
         Add vertex to listOfVertices

//step 2: build a list of faces
for each triangle
   for each vertex in triangle
      Get Vertex Index From listOfvertices
      AddToMap(vertex Index, triangle)

虽然我确实有一个执行此操作的实现,但是step1(唯一顶点列表的生成)的速度确实慢于O(n!),因为将每个顶点与列表中已经存在的所有顶点进行了比较。我以为"嘿,让我们使用std :: map构建我的顶点组件的哈希图,应该加快速度!",却发现从三个浮点值生成唯一键并不是一件容易的事。

在这里,stackoverflow的专家开始发挥作用:我需要某种可在3个浮点数上使用的哈希函数,或任何其他从3d顶点位置生成唯一值的函数。


转储数组中的所有顶点,然后执行unique(sort(array))。这应该是O(k n log(n)),其中k是共享一个顶点的三角形的平均数量,通常为k <7。

我能想到的唯一警告是,您的unique函数应该能够使用指向比较函数的指针,因为如果以下情况,您可能希望认为顶点相等

1
distance(vertex1, vertex2) < threshold

但这似乎还可以。


三种解决方案。当然还有其他

  • 使用哈希图。仅当"相同"的意思完全相同时,这才有效
  • 使用二进制空间分区来划分点
  • 使用常规网格划分点。
  • 在情况2和3中,如果要指定一些公差,则需要搜索树或网格的多个部分。在BSP情况下,这意味着检查您是否在分隔平面的公差范围内,如果是,则递归到两个半部。在网格情况下,这意味着检查所有在公差范围内的相邻单元。两者都不是很难,但是这意味着使用"现成的"解决方案将更加困难。


    获取哈希的常见想法是将浮点数的每个位模式与一个质数相乘,然后将它们加在一起。像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    unsigned int hash_point(float x, float y, float z)
    {
       unsigned int* px = (unsigned int*)&x;
       unsigned int* py = (unsigned int*)&y;
       unsigned int* pz = (unsigned int*)&z;

       return (*px)*PRIME1 + (*py)*PRIME2 + (*pz)*PRIME3;
    }

    您应注意,此处的sizeof(unsigned int)等于sizeof(float)。这里的示例仅用于说明主要思想,您应该根据需要对其进行调整。