/// <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."); } }
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); }