如何在Point3DCollection中搜索值?

时间:2015-02-24 12:53:04

标签: c# wpf collections 3d

基本上我使用MeshGeometry3D从STL文件加载点,位置和法线。 STL文件格式重复点,所以我想在添加新读取点之前首先搜索MeshGeometry3D.Positions重复。

Mesh.Positions.IndexOf(somePoint3D)不起作用,因为它基于对象引用而不是Point3D的X,Y,Z值进行比较。这就是为什么我要迭代整个Collection来手动查找重复项:

//triangle is a custom class containing three vertices of type Point3D
//for each 3 points read from STL the triangle object is reinitialized

vertex1DuplicateIndex = -1;
vertex2DuplicateIndex = -1;
vertex3DuplicateIndex = -1;

for (int q = tempMesh.Positions.Count - 1; q >= 0; q--)
{
    if (vertex1DuplicateIndex != -1)
        if (tempMesh.Positions[q] == triangle.Vertex1)
            vertex1DuplicateIndex = q;

    if (vertex2DuplicateIndex != -1)
        if (tempMesh.Positions[q] == triangle.Vertex2)
            vertex2DuplicateIndex = q;

    if (vertex3DuplicateIndex != -1)
        if (tempMesh.Positions[q] == triangle.Vertex3)
            vertex3DuplicateIndex = q;

    if (vertex1DuplicateIndex != -1 && vertex2DuplicateIndex != -1 && vertex3DuplicateIndex != -1)
        break;
}

当找到重复项时,此代码实际上非常有效,但是当没有重复时,集合将完全迭代,对于具有超过一百万个位置的大网格来说非常慢。

搜索还有其他方法吗?

有没有办法强制Mesh.Positions.IndexOf(newPoint3D)根据Mesh.Positions[index]==(somePoint3D)之类的值进行比较,而不是现在正在进行的参考比较?

2 个答案:

答案 0 :(得分:1)

我不知道内置的方法,但您可以使用哈希映射来缓存3D矢量的索引。 根据向量的哈希函数的质量,您将拥有一种''常量查找(没有碰撞是不可能的,但它应该比迭代每个新三角形点的所有顶点数据更快。)

答案 1 :(得分:0)

使用hakononakani的想法我使用HashSetDictionary的组合设法加快了速度。以下是我的代码的简化版本:

class CustomTriangle
{
    private Vector3D normal;
    private Point3D vertex1, vertex2, vertex3;
}

private void loadMesh()
{
    CustomTriangle triangle;
    MeshGeometry3D tempMesh = new MeshGeometry3D();
    HashSet<string> meshPositionsHashSet = new HashSet<string>();
    Dictionary<string, int> meshPositionsDict = new Dictionary<string, int>();
    int vertex1DuplicateIndex, vertex2DuplicateIndex, vertex3DuplicateIndex;
    int numberOfTriangles = GetNumberOfTriangles();

    for (int i = 0, j = 0; i < numberOfTriangles; i++)
    {
        triangle = ReadTriangleDataFromSTLFile();

        vertex1DuplicateIndex = -1;

        if (meshPositionsHashSet.Add(triangle.Vertex1.ToString()))
        {
            tempMesh.Positions.Add(triangle.Vertex1);
            meshPositionsDict.Add(triangle.Vertex1.ToString(), tempMesh.Positions.IndexOf(triangle.Vertex1));

            tempMesh.Normals.Add(triangle.Normal);
            tempMesh.TriangleIndices.Add(j++);
        }
        else
        {
            vertex1DuplicateIndex = meshPositionsDict[triangle.Vertex1.ToString()];
            tempMesh.TriangleIndices.Add(vertex1DuplicateIndex);
            tempMesh.Normals[vertex1DuplicateIndex] += triangle.Normal;
        }

        //Do the same for vertex2 and vertex3
    }
}

最后tempMesh只有唯一的点数。您所要做的就是将所有Normals标准化,然后您就可以进行可视化了。

只有Dictionary使用:

才能实现同样的效果
if (!meshPositionsDict.Keys.Contains(triangle.Vertex1.ToString()))

我只是喜欢使用HashSet,因为使用它很有趣:) 在这两种情况下,最终结果是 ~60倍算法比以前更快!