//------------------------------------------------ public void SimplifyMesh(double threshold, TraceListener log, bool verbose) { var edgePoints = EdgeIndices.Select(p => Vertices[p]).ToArray(); double fudgeSq = double.MaxValue; for (int i = 1; i < edgePoints.Length; i++) { var d = edgePoints[i].DeltaSq(ref edgePoints[i - 1]); if (d > 1.0E-10) { fudgeSq = Math.Min(fudgeSq, d); } } fudgeSq /= 100.0; var mdFinal = new SimplifyMesh(log, Vertices, TriangleIndices, EdgeIndices, verbose); mdFinal.SimplifyMeshByThreshold(threshold); Vertices = mdFinal.GetVertices(); TriangleIndices = mdFinal.GetIndices(); VertexNormals = mdFinal.GetVertexNormals(); EdgeIndices = mdFinal.GetEdgeIndices(); mdFinal = null; VertexToImage = new Vector2d[Vertices.Length]; GeoPolar3d buffGeoPolar = new GeoPolar3d(); for (int i = 0; i < VertexToImage.Length; i++) { InvertTo(ref Vertices[i], ref VertexToImage[i], ref buffGeoPolar); } }
public ComplexMesh(Vector3d[][] grid, TraceListener log, double threshold = 0.0001) { this.log = log; var reducedPositions = new List <Vector3d>(); var reducedTriangleIndices = new List <int>(); var reducedExternalIndices = new List <int>(); var max = grid.Length; // The min distance between vertices is at the corners var cornerDists = new double[] { grid[0][0].DeltaSq(ref grid[0][1]), grid[0][0].DeltaSq(ref grid[1][0]), grid[max - 1][0].DeltaSq(ref grid[max - 1][1]), grid[max - 1][0].DeltaSq(ref grid[max - 2][0]), grid[0][max - 1].DeltaSq(ref grid[0][max - 2]), grid[0][max - 1].DeltaSq(ref grid[1][max - 1]), grid[max - 1][max - 1].DeltaSq(ref grid[max - 1][max - 2]), grid[max - 1][max - 1].DeltaSq(ref grid[max - 2][max - 1]), }; double fudgeSq = cornerDists.Min() / 100.0; int numChunks = 9; int chunkMax = max / numChunks; bool verbose = false; List <int> chunkIs = new List <int>(); List <int> chunkJs = new List <int>(); for (int i = 0; i < numChunks; i++) { chunkIs.Add(i); chunkJs.Add(i); } var chunkInfos = new ChunkInfo[chunkIs.Count][]; foreach (int chunkI in chunkIs) { chunkInfos[chunkI - chunkIs.Min()] = new ChunkInfo[chunkJs.Count]; int iMin = chunkI * chunkMax; int iMax = (chunkI < numChunks - 1 ? chunkMax * (chunkI + 1) + 1 : max); int iCount = iMax - iMin; foreach (int chunkJ in chunkJs) { log?.WriteLine(DateTime.Now + "\tWorking on chunk (" + (chunkI - chunkIs.Min()) + "," + (chunkJ - chunkJs.Min()) + ") " + "(" + (((chunkI - chunkIs.Min()) * chunkJs.Count) + (chunkJ - chunkJs.Min())) + "/" + (chunkIs.Count * chunkJs.Count) + ")"); int jMin = chunkJ * chunkMax; int jMax = (chunkJ < numChunks - 1 ? chunkMax * (chunkJ + 1) + 1 : max); int jCount = jMax - jMin; int vid = 0; Vector3d[] positions = new Vector3d[iCount * jCount]; List <int> edgeIndices = new List <int>(); List <Vector3d> edges = new List <Vector3d>(); List <Vector3d> exteriors = new List <Vector3d>(); for (int i = iMin; i < iMax; i++) { for (int j = jMin; j < jMax; j++) { int iPrime = (max - 1 - i) * grid.Length / max; int jPrime = (j) * grid[0].Length / max; var v = grid[jPrime][iPrime]; if (i == iMin || i == (iMax - 1) || j == jMin || j == (jMax - 1)) { edgeIndices.Add(vid); edges.Add(v); } if ((chunkI == chunkIs.Min() && i == iMin) || (chunkI == chunkIs.Max() && i == iMax - 1) || (chunkJ == chunkJs.Min() && j == jMin) || (chunkJ == chunkJs.Max() && j == jMax - 1)) { exteriors.Add(v); } positions[vid++] = v; } } // Create a collection of triangle indices int tid = 0; int[] triangleIncides = new int[(iCount - 1) * (jCount - 1) * 6]; for (int i = 0; i < iCount - 1; i++) { for (int j = 0; j < jCount - 1; j++) { triangleIncides[tid++] = (i + 0) * jCount + (j + 0); triangleIncides[tid++] = (i + 1) * jCount + (j + 0); triangleIncides[tid++] = (i + 0) * jCount + (j + 1); triangleIncides[tid++] = (i + 1) * jCount + (j + 1); triangleIncides[tid++] = (i + 0) * jCount + (j + 1); triangleIncides[tid++] = (i + 1) * jCount + (j + 0); } } var md = new SimplifyMesh(log, positions.ToArray(), triangleIncides.ToArray(), edgeIndices.ToArray(), verbose); positions = null; triangleIncides = null; ChunkInfo chunkInfo = new ChunkInfo() { I = chunkI - chunkIs.Min(), J = chunkJ - chunkJs.Min() }; md.SimplifyMeshByThreshold(threshold); var startIndex = reducedPositions.Count; var vertices = md.GetVertices(); reducedPositions.AddRange(vertices); chunkInfo.EdgeIndices.AddRange(GetVertexIndices(vertices, edges, fudgeSq).Select(ei => ei + startIndex)); reducedExternalIndices.AddRange(GetVertexIndices(vertices, exteriors, fudgeSq).Select(exti => exti + startIndex)); reducedTriangleIndices.AddRange(md.GetIndices().Select(ti => ti + startIndex)); vertices = null; edges = null; exteriors = null; md = null; chunkInfos[chunkI - chunkIs.Min()][chunkJ - chunkJs.Min()] = chunkInfo; // Clear out unused objects GC.Collect(); } } var reducedPositionsArray = reducedPositions.ToArray(); reducedPositions = null; var reducedTriangleIndicesArray = reducedTriangleIndices.ToArray(); reducedTriangleIndices = null; var edgePoints = reducedExternalIndices.Select(p => reducedPositionsArray[p]).ToArray(); GlueChunks(reducedPositionsArray, reducedTriangleIndicesArray, chunkInfos, fudgeSq); var mdFinal = new SimplifyMesh(log, reducedPositionsArray, reducedTriangleIndicesArray, reducedExternalIndices.ToArray(), verbose); reducedPositionsArray = null; reducedTriangleIndicesArray = null; mdFinal.SimplifyMeshByThreshold(threshold); Vertices = mdFinal.GetVertices(); TriangleIndices = mdFinal.GetIndices(); EdgeIndices = GetVertexIndices(Vertices, edgePoints, fudgeSq).ToArray(); VertexNormals = mdFinal.GetVertexNormals(); mdFinal = null; }