Пример #1
0
        /// <summary>
        /// Populates |EditVertex.AdjacentVertices|.
        /// </summary>
        private void ComputeAdjacentVertices()
        {
            // Put all vertices into a KDTree.
            try
            {
                KDTree <EditVertex> tree = new KDTree <EditVertex>(3);
                foreach (var face in Faces)
                {
                    foreach (var vert in face.Vertices)
                    {
                        var pos = vert.Position;
                        tree.AddPoint(new double[] { pos.X, pos.Y, pos.Z }, vert);
                    }
                }
                // For each vertices, retrieve adjacent/identical vertices by looking
                // up neighbors within a very small (epsilon'ish) radius.
                Faces.ParallelDo(
                    face =>
                {
                    foreach (var vert in face.Vertices)
                    {
                        var pos       = vert.Position;
                        var neighbors = tree.NearestNeighbors(new double[] { pos.X, pos.Y, pos.Z },
                                                              new SquareEuclideanDistanceFunction(),
                                                              int.MaxValue, 1e-5f);
                        foreach (var neighbor in neighbors)
                        {
                            vert.AdjacentVertices.Add(neighbor);
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                // TODO: Log.
                // Unfortunately, KDTree rarely crashes.
                // Long-term: fix KDTree.
                // Short-term: O(n^2) brute force workaround.
                Faces.ParallelDo(
                    face =>
                {
                    foreach (var vert in face.Vertices)
                    {
                        var pos = vert.Position;
                        foreach (var otherVert in Vertices)
                        {
                            if (vert.IsApproximatelySamePosition(otherVert))
                            {
                                vert.AdjacentVertices.Add(otherVert);
                            }
                        }
                    }
                });
            }
            // Vertices being adjacent should be a transitive relation, yet this is
            // not guaranteed if implemented through a search radius.
            HashSet <EditVertex> seen = new HashSet <EditVertex>();

            foreach (var face in Faces)
            {
                foreach (var vert in face.Vertices)
                {
                    if (seen.Contains(vert))
                    {
                        continue;
                    }
                    foreach (var adjacentVert in vert.AdjacentVertices)
                    {
                        vert.AdjacentVertices.UnionWith(vert.AdjacentVertices);
                    }
                    foreach (var adjacentVert in vert.AdjacentVertices)
                    {
                        adjacentVert.AdjacentVertices = vert.AdjacentVertices;
                        seen.Add(adjacentVert);
                    }
                }
            }
        }