/// <summary>
            /// Searches for an indexed face by iterating.
            /// </summary>
            /// <param name="index">The index of the face to return.</param>
            /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="index"/> is negative or too large.</exception>
            /// <returns>The specified face.</returns>
            public Face GetFace(Int32 index)
            {
                if (index < 0)
                {
                    throw new ArgumentOutOfRangeException("index", index, "The given index cannot be negative.");
                }

                try
                {
                    return(Faces.Skip(index).First());
                }
                catch (InvalidOperationException)
                {
                    throw new ArgumentOutOfRangeException("index", index, "The given index is too large.");
                }
            }
Ejemplo n.º 2
0
        public List <int[]> Edges()
        {
            var edgeConnectivities = new List <int[]>();

            // Get face connectivities and close loop
            var faceConnnectivities = new List <int[]>();

            for (var i = 0; i < Faces.Count(); i++)
            {
                var numVertices = Faces[i] + 3;
                i++;
                faceConnnectivities.Add(Faces.Skip(i).Take(numVertices).Concat(Faces.Skip(i).Take(1)).ToArray());
                i += numVertices - 1;
            }

            // Get distinct edges
            var edges = new List <Tuple <int, int, string, string, double> >();

            foreach (var conn in faceConnnectivities)
            {
                for (var i = 0; i < conn.Length - 1; i++)
                {
                    var c1     = string.Join(",", Vertices.Skip(conn[i] * 3).Take(3).Select(x => Math.Round(x, 4).ToString()));
                    var c2     = string.Join(",", Vertices.Skip(conn[i + 1] * 3).Take(3).Select(x => Math.Round(x, 4).ToString()));
                    var length = Math.Pow(Vertices.Skip(conn[i] * 3).Take(1).First() - Vertices.Skip(conn[i + 1] * 3).Take(1).First(), 2) +
                                 Math.Pow(Vertices.Skip(conn[i] * 3 + 1).Take(1).First() - Vertices.Skip(conn[i + 1] * 3 + 1).Take(1).First(), 2) +
                                 Math.Pow(Vertices.Skip(conn[i] * 3 + 2).Take(1).First() - Vertices.Skip(conn[i + 1] * 3 + 2).Take(1).First(), 2);
                    length = Math.Sqrt(length);

                    if (edges.Any(e => (e.Item3 == c1 && e.Item4 == c2) |
                                  (e.Item3 == c2 && e.Item4 == c1)))
                    {
                        edges.RemoveAll(x => (x.Item3 == c1 && x.Item4 == c2) || (x.Item3 == c2 && x.Item4 == c1));
                    }
                    else
                    {
                        if (conn[i] < conn[i + 1])
                        {
                            edges.Add(new Tuple <int, int, string, string, double>(conn[i], conn[i + 1], c1, c2, length));
                        }
                        else
                        {
                            edges.Add(new Tuple <int, int, string, string, double>(conn[i + 1], conn[i], c2, c1, length));
                        }
                    }
                }
            }

            // Reorder the edges
            var    lengthsOfEdges = new List <double>();
            double currentLength  = 0;

            var currentLoop = new List <int>();
            var flatCoor    = new List <string>();

            currentLoop.Add(edges[0].Item1);
            currentLoop.Add(edges[0].Item2);
            flatCoor.Add(edges[0].Item3);
            flatCoor.Add(edges[0].Item4);

            edges.RemoveAt(0);

            while (edges.Count > 0)
            {
                var commonVertex = flatCoor.Last();

                var nextEdge = edges.Where(e => e.Item3 == commonVertex | e.Item4 == commonVertex).ToList();

                if (nextEdge.Count > 0)
                {
                    currentLoop.Add(nextEdge[0].Item3 == commonVertex ? nextEdge[0].Item2 : nextEdge[0].Item1);
                    flatCoor.Add(nextEdge[0].Item3 == commonVertex ? nextEdge[0].Item4 : nextEdge[0].Item3);
                    edges.Remove(nextEdge[0]);
                    currentLength += nextEdge[0].Item5;
                }
                else
                {
                    // Next edge not found. Stop looking for more
                    break;
                }

                if (currentLoop[0] == currentLoop.Last())
                {
                    currentLoop.RemoveAt(0);

                    edgeConnectivities.Add(currentLoop.ToArray());
                    lengthsOfEdges.Add(currentLength);

                    currentLength       = 0;
                    currentLoop         = new List <int>();
                    faceConnnectivities = new List <int[]>();

                    if (edges.Count > 0)
                    {
                        currentLoop.Add(edges[0].Item1);
                        currentLoop.Add(edges[0].Item2);
                        flatCoor.Add(edges[0].Item3);
                        flatCoor.Add(edges[0].Item4);

                        edges.RemoveAt(0);
                    }
                }
            }

            // Sort based on length
            var ordered = lengthsOfEdges
                          .Select((x, i) => new KeyValuePair <double, int>(x, i))
                          .OrderBy(x => x.Key)
                          .Select(x => x.Value)
                          .Reverse();

            var sortedEdgeConnectivities = new List <int[]>();

            foreach (var i in ordered)
            {
                sortedEdgeConnectivities.Add(edgeConnectivities[i]);
            }

            return(sortedEdgeConnectivities);
        }