internal static Edge[] BuildEdges(int vertexCount, int[] triangleArray) { int maxEdgeCount = triangleArray.Length; int[] firstEdge = new int[vertexCount + maxEdgeCount]; int nextEdge = vertexCount; int triangleCount = triangleArray.Length / 3; for (int a = 0; a < vertexCount; a++) firstEdge[a] = -1; // First pass over all triangles. This finds all the edges satisfying the // condition that the first vertex index is less than the second vertex index // when the direction from the first vertex to the second vertex represents // a counterclockwise winding around the triangle to which the edge belongs. // For each edge found, the edge index is stored in a linked list of edges // belonging to the lower-numbered vertex index i. This allows us to quickly // find an edge in the second pass whose higher-numbered vertex index is i. Edge[] edgeArray = new Edge[maxEdgeCount]; int edgeCount = 0; for (int a = 0; a < triangleCount; a++) { int i1 = triangleArray[a * 3 + 2]; for (int b = 0; b < 3; b++) { int i2 = triangleArray[a * 3 + b]; if (i1 < i2) { Edge newEdge = new Edge(); newEdge.vertexIndex[0] = i1; newEdge.vertexIndex[1] = i2; newEdge.faceIndex[0] = a; newEdge.faceIndex[1] = a; edgeArray[edgeCount] = newEdge; int edgeIndex = firstEdge[i1]; if (edgeIndex == -1) { firstEdge[i1] = edgeCount; } else { while (true) { int index = firstEdge[nextEdge + edgeIndex]; if (index == -1) { firstEdge[nextEdge + edgeIndex] = edgeCount; break; } edgeIndex = index; } } firstEdge[nextEdge + edgeCount] = -1; edgeCount++; } i1 = i2; } } // Second pass over all triangles. This finds all the edges satisfying the // condition that the first vertex index is greater than the second vertex index // when the direction from the first vertex to the second vertex represents // a counterclockwise winding around the triangle to which the edge belongs. // For each of these edges, the same edge should have already been found in // the first pass for a different triangle. Of course we might have edges with only one triangle // in that case we just add the edge here // So we search the list of edges // for the higher-numbered vertex index for the matching edge and fill in the // second triangle index. The maximum number of comparisons in this search for // any vertex is the number of edges having that vertex as an endpoint. for (int a = 0; a < triangleCount; a++) { int i1 = triangleArray[a * 3 + 2]; for (int b = 0; b < 3; b++) { int i2 = triangleArray[a * 3 + b]; if (i1 > i2) { bool foundEdge = false; for (int edgeIndex = firstEdge[i2]; edgeIndex != -1; edgeIndex = firstEdge[nextEdge + edgeIndex]) { Edge edge = edgeArray[edgeIndex]; if ((edge.vertexIndex[1] == i1) && (edge.faceIndex[0] == edge.faceIndex[1])) { edgeArray[edgeIndex].faceIndex[1] = a; foundEdge = true; break; } } if (!foundEdge) { Edge newEdge = new Edge(); newEdge.vertexIndex[0] = i1; newEdge.vertexIndex[1] = i2; newEdge.faceIndex[0] = a; newEdge.faceIndex[1] = a; edgeArray[edgeCount] = newEdge; edgeCount++; } } i1 = i2; } } Edge[] compactedEdges = new Edge[edgeCount]; for (int e = 0; e < edgeCount; e++) compactedEdges[e] = edgeArray[e]; return compactedEdges; }
internal static EdgeLoop[] BuildEdgeLoops(Edge[] manifoldEdges) { List<EdgeLoop> loops = new List<EdgeLoop>(); if (manifoldEdges.Length == 0) return loops.ToArray(); List<Edge> Stock = new List<Edge>(manifoldEdges); List<int> Loop = new List<int>(); int nextVI; Loop.Add(Stock[0].vertexIndex[0]); Loop.Add(Stock[0].vertexIndex[1]); int curVI = Stock[0].vertexIndex[1]; Stock.RemoveAt(0); while (Stock.Count > 0) { // find edge that connects to curVI Edge E = getNextEdge(curVI, ref Stock, out nextVI); if (E == null) return new EdgeLoop[0]; // Open Loop Loop.Add(nextVI); curVI = nextVI; Stock.Remove(E); if (curVI == Loop[0]) { loops.Add(new EdgeLoop(Loop)); Loop.Clear(); if (Stock.Count > 0) { Loop.Add(Stock[0].vertexIndex[0]); Loop.Add(Stock[0].vertexIndex[1]); curVI = Stock[0].vertexIndex[1]; Stock.RemoveAt(0); } } } if (Loop.Count > 0) loops.Add(new EdgeLoop(Loop)); return loops.ToArray(); }