using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using CaeMesh; using CaeGlobals; namespace FileInOut.Input { static public class StlFileReader { public static FeMesh Read(string fileName) { if (File.Exists(fileName)) { QuantumConcepts.Formats.StereoLithography.STLDocument stlFile = null; // System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); // using (Stream stream = File.OpenRead(fileName)) { watch.Start(); stlFile = QuantumConcepts.Formats.StereoLithography.STLDocument.Read(stream, true); watch.Stop(); } // FeNode node; int[] nodeIds; LinearTriangleElement element; Dictionary nodes = new Dictionary(); Dictionary elements = new Dictionary(); // CompareFeNodeCoods comparer = new CompareFeNodeCoods(); Dictionary nodeMap = new Dictionary(stlFile.Facets.Count, comparer); BoundingBox box = new BoundingBox(); int nodeId; int localCount; // foreach (var facet in stlFile.Facets) { localCount = 0; nodeIds = new int[3]; foreach (var v in facet.Vertices) { node = new FeNode(nodes.Count + 1, v.X, v.Y, v.Z); box.IncludeNode(node); // if (nodeMap.TryGetValue(node, out nodeId)) { node.Id = nodeId; } else { nodes.Add(node.Id, node); nodeMap.Add(node, node.Id); } nodeIds[localCount++] = node.Id; } element = new LinearTriangleElement(elements.Count + 1, nodeIds); elements.Add(element.Id, element); } // double epsilon = 1E-6; double max = box.GetDiagonal(); // MergeNodes(nodes, elements, epsilon * max); // FeMesh mesh = new FeMesh(nodes, elements, MeshRepresentation.Geometry, ImportOptions.ImportStlParts); // //string namePrefix = Path.GetFileNameWithoutExtension(fileName).Replace(' ', '_'); //FeMesh mesh = new FeMesh(nodes, elements, MeshRepresentation.Geometry, namePrefix); // //if (mesh.Parts.Count == 1) //{ // GeometryPart part = mesh.Parts.Values.First() as GeometryPart; // mesh.Parts.Clear(); // part.Name = namePrefix; // mesh.Parts.Add(part.Name, part); //} return mesh; } // return null; } private static void MergeNodes(Dictionary nodes, Dictionary elements, double epsilon) { int count = 0; FeNode[] sortedNodes = new FeNode[nodes.Count]; // sort the nodes by x foreach (var entry in nodes) { sortedNodes[count++] = entry.Value; } IComparer comparerByX = new CompareFeNodeByX(); Array.Sort(sortedNodes, comparerByX); // create a map of node ids to be merged to another node id Dictionary mergeMap = new Dictionary(); for (int i = 0; i < sortedNodes.Length - 1; i++) { if (mergeMap.ContainsKey(sortedNodes[i].Id)) continue; // this node was merged and does not exist anymore for (int j = i + 1; j < sortedNodes.Length; j++) { if (mergeMap.ContainsKey(sortedNodes[j].Id)) continue; // this node was merged and does not exist anymore if (Math.Abs(sortedNodes[i].X - sortedNodes[j].X) < epsilon) { if (Math.Abs(sortedNodes[i].Y - sortedNodes[j].Y) < epsilon) { if (Math.Abs(sortedNodes[i].Z - sortedNodes[j].Z) < epsilon) { mergeMap.Add(sortedNodes[j].Id, sortedNodes[i].Id); } } } else { break; } } } // apply the map to the elements int newId; HashSet nodeIds = new HashSet(); List elementIdsToRemove = new List(); foreach (var entry in elements) { nodeIds.Clear(); for (int i = 0; i < entry.Value.NodeIds.Length; i++) { if (mergeMap.TryGetValue(entry.Value.NodeIds[i], out newId)) entry.Value.NodeIds[i] = newId; nodeIds.Add(entry.Value.NodeIds[i]); } if (nodeIds.Count != entry.Value.NodeIds.Length) elementIdsToRemove.Add(entry.Key); } // remove collapsed elements foreach (var elementId in elementIdsToRemove) { elements.Remove(elementId); // might be also necessary to remove some nodes ? } // remove unused nodes foreach (var entry in mergeMap) { nodes.Remove(entry.Key); } } } }