public static List<Mesh> SplitConnectedIntoMeshes(MeshGroup meshGroupToSplit, ReportProgressRatio reportProgress) { List<Mesh> discreteMeshes = new List<Mesh>(); double ratioPerDiscreetMesh = 1.0 / meshGroupToSplit.Meshes.Count; double currentRatioDone = 0; foreach (Mesh mesh in meshGroupToSplit.Meshes) { List<Mesh> discreteVolumes = SplitVolumesIntoMeshes(mesh, (double progress0To1, string processingState, out bool continueProcessing) => { if (reportProgress != null) { double progress = (currentRatioDone + ratioPerDiscreetMesh * progress0To1); reportProgress(progress, "Split Into Meshes", out continueProcessing); } else { continueProcessing = true; } }); discreteMeshes.AddRange(discreteVolumes); currentRatioDone += ratioPerDiscreetMesh; } return discreteMeshes; }
public static List <MeshGroup> Load(string fileName, ReportProgressRatio reportProgress = null) { List <MeshGroup> loadedMesh = null; if (Path.GetExtension(fileName).ToUpper() == ".AMF") { try { if (File.Exists(fileName)) { Stream fileStream = File.OpenRead(fileName); loadedMesh = ParseFileContents(fileStream, reportProgress); } } #if DEBUG catch (IOException e) { Debug.Print(e.Message); BreakInDebugger(); return(null); } #else catch (Exception) { return(null); } #endif } return(loadedMesh); }
public void AddFilesToLibrary(IList <string> files, ReportProgressRatio reportProgress = null) { foreach (string loadedFileName in files) { string extension = Path.GetExtension(loadedFileName).ToUpper(); if ((extension != "" && MeshFileIo.ValidFileExtensions().Contains(extension)) || extension == ".GCODE" || extension == ".ZIP") { if (extension == ".ZIP") { ProjectFileHandler project = new ProjectFileHandler(null); List <PrintItem> partFiles = project.ImportFromProjectArchive(loadedFileName); if (partFiles != null) { foreach (PrintItem part in partFiles) { AddItem(new PrintItemWrapper(part, this.GetProviderLocator())); } } } else { AddItem(new PrintItemWrapper(new PrintItem(Path.GetFileNameWithoutExtension(loadedFileName), loadedFileName), this.GetProviderLocator())); } } } }
internal ProgressData(Stream positionStream, ReportProgressRatio reportProgress) { this.reportProgress = reportProgress; this.positionStream = positionStream; maxProgressReport.Start(); bytesInFile = (long)positionStream.Length; }
public static List <MeshGroup> Load(string meshPathAndFileName, ReportProgressRatio reportProgress = null) { using (Stream stream = File.OpenRead(meshPathAndFileName)) { return(Load(stream, Path.GetExtension(meshPathAndFileName), reportProgress)); } }
// Note: Changing the Load(Stream) return type - this is a breaking change but methods with the same name should return the same type public static Mesh Load(Stream fileStream, ReportProgressRatio reportProgress = null) { try { // Parse STL Mesh loadedMesh = ParseFileContents(fileStream, reportProgress); // TODO: Sync with AMF processing and have ParseFileContents return List<MeshGroup>? // // Return the loaded mesh wrapped in a MeshGroup, wrapped in a List return(loadedMesh); } #if DEBUG catch (IOException e) { Debug.Print(e.Message); BreakInDebugger(); return(null); } #else // TODO: Consider not supressing exceptions like this or at least logging them. Troubleshooting when this // scenario occurs is impossible and likely results in an undiagnosable null reference error catch (Exception) { return(null); } #endif }
public override void AddFilesToLibrary(IList <string> files, ReportProgressRatio reportProgress = null) { string destPath = rootPath; CopyAllFiles(files, destPath); GetFilesAndCollectionsInCurrentDirectory(); }
public void MergeVertices(ReportProgressRatio reportProgress = null, double maxDistanceToConsiderVertexAsSame = 0) { HashSet <Vertex> markedForDeletion = new HashSet <Vertex>(); Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); for (int i = 0; i < Vertices.Count; i++) { Vertex vertexToKeep = Vertices[i]; if (!markedForDeletion.Contains(vertexToKeep)) { List <Vertex> samePosition = Vertices.FindVertices(vertexToKeep.Position, maxDistanceToConsiderVertexAsSame); foreach (Vertex vertexToDelete in samePosition) { if (vertexToDelete != vertexToKeep) { if (!markedForDeletion.Contains(vertexToDelete)) { #if AGRESSIVE_VALIDATING Validate(markedForDeletion); #endif MergeVertices(vertexToKeep, vertexToDelete, false); markedForDeletion.Add(vertexToDelete); #if AGRESSIVE_VALIDATING Validate(markedForDeletion); #endif } } } if (reportProgress != null) { if (maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(i / (double)Vertices.Count, "Merging Vertices", out continueProcessing); if (!continueProcessing) { return; } maxProgressReport.Restart(); } } } } #if AGRESSIVE_VALIDATING Validate(markedForDeletion); #endif if (reportProgress != null) { bool continueProcessing; reportProgress(1, "Deleting Unused Vertices", out continueProcessing); } RemoveVerticesMarkedForDeletion(markedForDeletion); }
public MeshOutputSettings(OutputType outputTypeSetting, string[] metaDataKeyValuePairs = null, ReportProgressRatio reportProgress = null) { this.ReportProgress = reportProgress; this.OutputTypeSetting = outputTypeSetting; if (metaDataKeyValuePairs != null) { for (int i = 0; i < metaDataKeyValuePairs.Length / 2; i++) { MetaDataKeyValue.Add(metaDataKeyValuePairs[i * 2], metaDataKeyValuePairs[i * 2 + 1]); } } }
public MeshOutputSettings(OutputType outputTypeSetting, string[] metaDataKeyValuePairs = null, ReportProgressRatio reportProgress = null) { this.reportProgress = reportProgress; this.OutputTypeSetting = outputTypeSetting; if (metaDataKeyValuePairs != null) { for (int i = 0; i < metaDataKeyValuePairs.Length / 2; i++) { MetaDataKeyValue.Add(metaDataKeyValuePairs[i * 2], metaDataKeyValuePairs[i * 2 + 1]); } } }
public void MergeMeshEdges(ReportProgressRatio reportProgress = null) { HashSet <MeshEdge> markedForDeletion = new HashSet <MeshEdge>(); Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); for (int i = 0; i < MeshEdges.Count; i++) { MeshEdge currentMeshEdge = MeshEdges[i]; if (!markedForDeletion.Contains(currentMeshEdge)) { Vertex vertex0 = currentMeshEdge.VertexOnEnd[0]; Vertex vertex1 = currentMeshEdge.VertexOnEnd[1]; // find out if there is another edge attached to the same vertexes List <MeshEdge> meshEdgesToDelete = FindMeshEdges(vertex0, vertex1); if (meshEdgesToDelete.Count > 1) { foreach (MeshEdge meshEdgeToDelete in meshEdgesToDelete) { if (meshEdgeToDelete != currentMeshEdge) { if (!markedForDeletion.Contains(meshEdgeToDelete)) { MergeMeshEdges(currentMeshEdge, meshEdgeToDelete, false); markedForDeletion.Add(meshEdgeToDelete); } } } } } if (reportProgress != null) { if (maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(i / (double)MeshEdges.Count, "Merging Mesh Edges", out continueProcessing); maxProgressReport.Restart(); if (!continueProcessing) { return; } } } } RemoveMeshEdgesMarkedForDeletion(markedForDeletion); }
public static List <MeshGroup> Load(string meshPathAndFileName, ReportProgressRatio reportProgress = null) { try { using (Stream stream = new FileStream(meshPathAndFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { return(Load(stream, Path.GetExtension(meshPathAndFileName), reportProgress)); } } catch (Exception) { return(null); } }
public static Mesh Load(string fileName, ReportProgressRatio reportProgress = null) { // Early exit if not STL if (Path.GetExtension(fileName).ToUpper() != ".STL") { return(null); } using (Stream fileStream = File.OpenRead(fileName)) { // Call the Load signature taking a stream and file extension return(Load(fileStream, reportProgress)); } }
public void RegisterForProgress(int itemIndex, ReportProgressRatio reportProgress) { if (!itemReportProgressHandlers.ContainsKey(itemIndex)) { itemReportProgressHandlers.Add(itemIndex, new ProgressPlug() { ProgressOutput = reportProgress, }); } else { itemReportProgressHandlers[itemIndex].ProgressOutput = reportProgress; } }
public void LoadFilesIntoLibrary(string[] files, ReportProgressRatio reportProgress = null) { this.fileLoadReportProgress = reportProgress; if (files != null && files.Length > 0) { BackgroundWorker mergeAndSavePartsBackgroundWorker = new BackgroundWorker(); mergeAndSavePartsBackgroundWorker.WorkerReportsProgress = true; mergeAndSavePartsBackgroundWorker.DoWork += new DoWorkEventHandler(mergeAndSavePartsBackgroundWorker_DoWork); mergeAndSavePartsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(mergeAndSavePartsBackgroundWorker_RunWorkerCompleted); mergeAndSavePartsBackgroundWorker.RunWorkerAsync(files); } }
public static List <MeshGroup> Load(Stream fileStream, string fileExtension, ReportProgressRatio reportProgress = null) { switch (fileExtension.ToUpper()) { case ".STL": Mesh loadedMesh = StlProcessing.Load(fileStream, reportProgress); return((loadedMesh == null) ? null : new List <MeshGroup>(new[] { new MeshGroup(loadedMesh) })); case ".AMF": return(AmfProcessing.Load(fileStream, reportProgress)); default: return(null); } }
public static List<MeshGroup> Load(Stream fileStream, string fileExtension, ReportProgressRatio reportProgress = null) { switch (fileExtension.ToUpper()) { case ".STL": Mesh loadedMesh = StlProcessing.Load(fileStream, reportProgress); return (loadedMesh == null) ? null : new List<MeshGroup>(new[] { new MeshGroup(loadedMesh) }); case ".AMF": return AmfProcessing.Load(fileStream, reportProgress); default: return null; } }
public void SortVertices(ReportProgressRatio reportProgress = null) { bool continueProcessing; if (reportProgress != null) { reportProgress(0, "Sorting Vertices", out continueProcessing); } timer.Restart(); Vertices.Sort(); timer.Stop(); Debug.WriteLine(timer.ElapsedMilliseconds); if (reportProgress != null) { reportProgress(1, "Sorting Vertices", out continueProcessing); } }
public override async void AddFilesToLibrary(IList <string> files, ReportProgressRatio reportProgress = null) { if (files != null && files.Count > 0) { // create enough info to show that we have items pending (maybe use names from this file list for them) // refresh the display to show the pending items //LibraryProvider.OnDataReloaded(null); await Task.Run(() => loadFilesIntoLibraryBackgoundWorker_DoWork(files)); if (baseLibraryCollection != null) { LoadLibraryItems(); LibraryProvider.OnDataReloaded(null); } } }
public void LoadFilesIntoLibrary(IList <string> files, ReportProgressRatio reportProgress = null, RunWorkerCompletedEventHandler callback = null) { if (files != null && files.Count > 0) { BackgroundWorker loadFilesIntoLibraryBackgroundWorker = new BackgroundWorker(); loadFilesIntoLibraryBackgroundWorker.WorkerReportsProgress = true; loadFilesIntoLibraryBackgroundWorker.DoWork += new DoWorkEventHandler(loadFilesIntoLibraryBackgoundWorker_DoWork); loadFilesIntoLibraryBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(loadFilesIntoLibraryBackgroundWorker_RunWorkerCompleted); if (callback != null) { loadFilesIntoLibraryBackgroundWorker.RunWorkerCompleted += callback; } loadFilesIntoLibraryBackgroundWorker.RunWorkerAsync(files); } }
public void CleanAndMergMesh(ReportProgressRatio reportProgress = null) { if (reportProgress != null) { #if AGRESSIVE_VALIDATING Validate(); #endif bool keepProcessing = true; SortVertices((double progress0To1, string processingState, out bool continueProcessing) => { reportProgress(progress0To1 * .41, processingState, out continueProcessing); keepProcessing = continueProcessing; #if AGRESSIVE_VALIDATING Validate(); #endif }); if (keepProcessing) { MergeVertices((double progress0To1, string processingState, out bool continueProcessing) => { reportProgress(progress0To1 * .23 + .41, processingState, out continueProcessing); keepProcessing = continueProcessing; }); } if (keepProcessing) { MergeMeshEdges((double progress0To1, string processingState, out bool continueProcessing) => { reportProgress(progress0To1 * .36 + .64, processingState, out continueProcessing); keepProcessing = continueProcessing; }); #if AGRESSIVE_VALIDATING Validate(); #endif } } else { SortVertices(); MergeVertices(); MergeMeshEdges(); } }
public static List <MeshGroup> Load(Stream fileStream, ReportProgressRatio reportProgress = null) { List <MeshGroup> loadedMeshes; try { loadedMeshes = ParseFileContents(fileStream, reportProgress); } #if DEBUG catch (IOException) { return(null); } #else catch (Exception) { return(null); } #endif return(loadedMeshes); }
public async override Task<PrintItemWrapper> GetPrintItemWrapperAsync(int itemIndex, ReportProgressRatio reportProgress = null) { throw new NotImplementedException("Print items are not allowed at the root level"); }
public static Mesh Copy(Mesh meshToCopy, ReportProgressRatio progress = null) { Mesh newMesh = new Mesh(); if (meshToCopy.Vertices.IsSorted) { Dictionary <Vertex, int> vertexIndexDictionary = GetVertexToIndexDictionary(meshToCopy, newMesh); Dictionary <MeshEdge, int> meshEdgeIndexDictionary = GetMeshEdgeToIndexDictionary(meshToCopy, newMesh); for (int faceIndex = 0; faceIndex < meshToCopy.Faces.Count; faceIndex++) { Face faceToCopy = meshToCopy.Faces[faceIndex]; newMesh.Faces.Add(new Face()); } // now set all the data for the new mesh newMesh.Vertices.Capacity = meshToCopy.Vertices.Capacity; for (int vertexIndex = 0; vertexIndex < meshToCopy.Vertices.Count; vertexIndex++) { Vertex vertexToCopy = meshToCopy.Vertices[vertexIndex]; // !!!! ON ERROR !!!!! If this throws an error, you likely need to CleanAndMergMesh the mesh before copying int indexOfFirstMeshEdge = meshEdgeIndexDictionary[vertexToCopy.firstMeshEdge]; Vertex newVertex = newMesh.Vertices[vertexIndex]; newVertex.firstMeshEdge = newMesh.MeshEdges[indexOfFirstMeshEdge]; newVertex.Normal = vertexToCopy.Normal; } newMesh.MeshEdges.Capacity = meshToCopy.MeshEdges.Capacity; for (int meshEdgeIndex = 0; meshEdgeIndex < meshToCopy.MeshEdges.Count; meshEdgeIndex++) { MeshEdge meshEdgeToCopy = meshToCopy.MeshEdges[meshEdgeIndex]; MeshEdge newMeshEdge = newMesh.MeshEdges[meshEdgeIndex]; newMeshEdge.NextMeshEdgeFromEnd[0] = newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeToCopy.NextMeshEdgeFromEnd[0]]]; newMeshEdge.NextMeshEdgeFromEnd[1] = newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeToCopy.NextMeshEdgeFromEnd[1]]]; newMeshEdge.VertexOnEnd[0] = newMesh.Vertices[vertexIndexDictionary[meshEdgeToCopy.VertexOnEnd[0]]]; newMeshEdge.VertexOnEnd[1] = newMesh.Vertices[vertexIndexDictionary[meshEdgeToCopy.VertexOnEnd[1]]]; // This will get hooked up when we create radial loops with the face edges below //newMeshEdge.firstFaceEdge; //newMesh.MeshEdges.Add(newMeshEdge); } newMesh.Faces.Capacity = meshToCopy.Faces.Capacity; for (int faceIndex = 0; faceIndex < meshToCopy.faces.Count; faceIndex++) { Face faceToCopy = meshToCopy.faces[faceIndex]; Face newface = newMesh.faces[faceIndex]; newface.normal = faceToCopy.normal; // hook up the face edges //public FaceEdge firstFaceEdge; List <Vertex> verticesFromCopy = new List <Vertex>(); List <Vertex> verticesForNew = new List <Vertex>(); foreach (Vertex vertex in faceToCopy.Vertices()) { verticesFromCopy.Add(vertex); verticesForNew.Add(newMesh.Vertices[vertexIndexDictionary[vertex]]); } List <MeshEdge> edgesFromCopy = new List <MeshEdge>(); List <MeshEdge> edgesForNew = new List <MeshEdge>(); for (int i = 0; i < verticesForNew.Count - 1; i++) { MeshEdge meshEdgeFromCopy = verticesFromCopy[i].GetMeshEdgeConnectedToVertex(verticesFromCopy[i + 1]); edgesFromCopy.Add(meshEdgeFromCopy); edgesForNew.Add(newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeFromCopy]]); } MeshEdge lastMeshEdgeFromCopy = verticesFromCopy[verticesFromCopy.Count - 1].GetMeshEdgeConnectedToVertex(verticesFromCopy[0]); edgesFromCopy.Add(lastMeshEdgeFromCopy); edgesForNew.Add(newMesh.MeshEdges[meshEdgeIndexDictionary[lastMeshEdgeFromCopy]]); CreateFaceEdges(verticesForNew.ToArray(), edgesForNew, newface); } } else { foreach (Face face in meshToCopy.Faces) { List <Vertex> faceVertices = new List <Vertex>(); foreach (FaceEdge faceEdgeToAdd in face.FaceEdges()) { Vertex newVertex = newMesh.CreateVertex(faceEdgeToAdd.firstVertex.Position, CreateOption.CreateNew, SortOption.WillSortLater); faceVertices.Add(newVertex); } newMesh.CreateFace(faceVertices.ToArray(), CreateOption.CreateNew); } newMesh.CleanAndMergMesh(); } MeshMaterialData materialDataToCopy = MeshMaterialData.Get(meshToCopy); MeshMaterialData newMaterialData = MeshMaterialData.Get(newMesh); newMaterialData.MaterialIndex = materialDataToCopy.MaterialIndex; return(newMesh); }
public static Mesh Load(string fileName, ReportProgressRatio reportProgress = null) { // Early exit if not STL if (Path.GetExtension(fileName).ToUpper() != ".STL") return null; using (Stream fileStream = File.OpenRead(fileName)) { // Call the Load signature taking a stream and file extension return Load(fileStream, reportProgress); } }
// Note: Changing the Load(Stream) return type - this is a breaking change but methods with the same name should return the same type public static Mesh Load(Stream fileStream, ReportProgressRatio reportProgress = null) { try { // Parse STL Mesh loadedMesh = ParseFileContents(fileStream, reportProgress); // TODO: Sync with AMF processing and have ParseFileContents return List<MeshGroup>? // // Return the loaded mesh wrapped in a MeshGroup, wrapped in a List return loadedMesh; } #if DEBUG catch (IOException e) { Debug.Print(e.Message); BreakInDebugger(); return null; } #else // TODO: Consider not supressing exceptions like this or at least logging them. Troubleshooting when this // scenario occurs is impossible and likely results in an undiagnosable null reference error catch (Exception) { return null; } #endif }
public void LoadFilesIntoLibrary(IList<string> files, ReportProgressRatio reportProgress = null, RunWorkerCompletedEventHandler callback = null) { if (files != null && files.Count > 0) { BackgroundWorker loadFilesIntoLibraryBackgroundWorker = new BackgroundWorker(); loadFilesIntoLibraryBackgroundWorker.WorkerReportsProgress = true; loadFilesIntoLibraryBackgroundWorker.DoWork += new DoWorkEventHandler(loadFilesIntoLibraryBackgoundWorker_DoWork); loadFilesIntoLibraryBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(loadFilesIntoLibraryBackgroundWorker_RunWorkerCompleted); if (callback != null) { loadFilesIntoLibraryBackgroundWorker.RunWorkerCompleted += callback; } loadFilesIntoLibraryBackgroundWorker.RunWorkerAsync(files); } }
public static List<MeshGroup> Load(string fileName, ReportProgressRatio reportProgress = null) { List<MeshGroup> loadedMesh = null; if (Path.GetExtension(fileName).ToUpper() == ".AMF") { try { if (File.Exists(fileName)) { Stream fileStream = File.OpenRead(fileName); loadedMesh = ParseFileContents(fileStream, reportProgress); } } #if DEBUG catch (IOException e) { Debug.Print(e.Message); BreakInDebugger(); return null; } #else catch (Exception) { return null; } #endif } return loadedMesh; }
public override void AddFilesToLibrary(IList<string> files, ReportProgressRatio reportProgress = null) { throw new NotImplementedException(); }
public void AddFilesToLibrary(IList<string> files, ReportProgressRatio reportProgress = null) { foreach (string loadedFileName in files) { string extension = Path.GetExtension(loadedFileName).ToUpper(); if ((extension != "" && MeshFileIo.ValidFileExtensions().Contains(extension)) || extension == ".GCODE" || extension == ".ZIP") { if (extension == ".ZIP") { ProjectFileHandler project = new ProjectFileHandler(null); List<PrintItem> partFiles = project.ImportFromProjectArchive(loadedFileName); if (partFiles != null) { foreach (PrintItem part in partFiles) { AddItem(new PrintItemWrapper(part, this.GetProviderLocator())); } } } else { AddItem(new PrintItemWrapper(new PrintItem(Path.GetFileNameWithoutExtension(loadedFileName), loadedFileName), this.GetProviderLocator())); } } } }
public static bool Save(List <MeshGroup> meshGroupsToSave, string meshPathAndFileName, MeshOutputSettings outputInfo = null, ReportProgressRatio reportProgress = null) { try { if (outputInfo == null) { outputInfo = new MeshOutputSettings(); } switch (Path.GetExtension(meshPathAndFileName).ToUpper()) { case ".STL": Mesh mesh = DoMerge(meshGroupsToSave, outputInfo); return(StlProcessing.Save(mesh, meshPathAndFileName, outputInfo)); case ".AMF": outputInfo.ReportProgress = reportProgress; return(AmfProcessing.Save(meshGroupsToSave, meshPathAndFileName, outputInfo)); default: return(false); } } catch (Exception) { return(false); } }
public override async void AddFilesToLibrary(IList<string> files, ReportProgressRatio reportProgress = null) { if (files != null && files.Count > 0) { // create enough info to show that we have items pending (maybe use names from this file list for them) // refresh the display to show the pending items //LibraryProvider.OnDataReloaded(null); await Task.Run(() => loadFilesIntoLibraryBackgoundWorker_DoWork(files)); if (baseLibraryCollection != null) { LoadLibraryItems(); LibraryProvider.OnDataReloaded(null); } } }
public static Mesh ParseFileContents(Stream stlStream, ReportProgressRatio reportProgress) { Stopwatch time = new Stopwatch(); time.Start(); Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; double parsingFileRatio = .5; if (stlStream == null) { return(null); } //MemoryStream stlStream = new MemoryStream(); //stlStreamIn.CopyTo(stlStream); Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); Mesh meshFromStlFile = new Mesh(); //meshFromStlFile.MaxDistanceToConsiderVertexAsSame = .0000005; long bytesInFile = stlStream.Length; if (bytesInFile <= 80) { return(null); } byte[] first160Bytes = new byte[160]; stlStream.Read(first160Bytes, 0, 160); byte[] ByteOredrMark = new byte[] { 0xEF, 0xBB, 0xBF }; int startOfString = 0; if (first160Bytes[0] == ByteOredrMark[0] && first160Bytes[0] == ByteOredrMark[0] && first160Bytes[0] == ByteOredrMark[0]) { startOfString = 3; } string first160BytesOfSTLFile = System.Text.Encoding.UTF8.GetString(first160Bytes, startOfString, first160Bytes.Length - startOfString); if (first160BytesOfSTLFile.StartsWith("solid") && first160BytesOfSTLFile.Contains("facet")) { stlStream.Position = 0; StreamReader stlReader = new StreamReader(stlStream); int vectorIndex = 0; Vector3 vector0 = new Vector3(0, 0, 0); Vector3 vector1 = new Vector3(0, 0, 0); Vector3 vector2 = new Vector3(0, 0, 0); string line = stlReader.ReadLine(); while (line != null) { line = line.Trim(); if (line.StartsWith("vertex")) { vectorIndex++; switch (vectorIndex) { case 1: vector0 = Convert(line); break; case 2: vector1 = Convert(line); break; case 3: vector2 = Convert(line); if (!Vector3.Collinear(vector0, vector1, vector2)) { Vertex vertex1 = meshFromStlFile.CreateVertex(vector0, CreateOption.CreateNew, SortOption.WillSortLater); Vertex vertex2 = meshFromStlFile.CreateVertex(vector1, CreateOption.CreateNew, SortOption.WillSortLater); Vertex vertex3 = meshFromStlFile.CreateVertex(vector2, CreateOption.CreateNew, SortOption.WillSortLater); meshFromStlFile.CreateFace(new Vertex[] { vertex1, vertex2, vertex3 }, CreateOption.CreateNew); } vectorIndex = 0; break; } } line = stlReader.ReadLine(); if (reportProgress != null && maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(stlStream.Position / (double)bytesInFile * parsingFileRatio, "Loading Polygons", out continueProcessing); if (!continueProcessing) { stlStream.Close(); return(null); } maxProgressReport.Restart(); } } } else { // load it as a binary stl // skip the first 80 bytes // read in the number of triangles stlStream.Position = 0; BinaryReader br = new BinaryReader(stlStream); byte[] fileContents = br.ReadBytes((int)stlStream.Length); int currentPosition = 80; uint numTriangles = System.BitConverter.ToUInt32(fileContents, currentPosition); long bytesForNormals = numTriangles * 3 * 4; long bytesForVertices = numTriangles * 3 * 4 * 3; long bytesForAttributs = numTriangles * 2; currentPosition += 4; long numBytesRequiredForVertexData = currentPosition + bytesForNormals + bytesForVertices + bytesForAttributs; if (fileContents.Length < numBytesRequiredForVertexData || numTriangles < 4) { stlStream.Close(); return(null); } Vector3[] vector = new Vector3[3]; for (int i = 0; i < numTriangles; i++) { // skip the normal currentPosition += 3 * 4; for (int j = 0; j < 3; j++) { vector[j] = new Vector3( System.BitConverter.ToSingle(fileContents, currentPosition + 0 * 4), System.BitConverter.ToSingle(fileContents, currentPosition + 1 * 4), System.BitConverter.ToSingle(fileContents, currentPosition + 2 * 4)); currentPosition += 3 * 4; } currentPosition += 2; // skip the attribute if (reportProgress != null && maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(i / (double)numTriangles * parsingFileRatio, "Loading Polygons", out continueProcessing); if (!continueProcessing) { stlStream.Close(); return(null); } maxProgressReport.Restart(); } if (!Vector3.Collinear(vector[0], vector[1], vector[2])) { Vertex vertex1 = meshFromStlFile.CreateVertex(vector[0], CreateOption.CreateNew, SortOption.WillSortLater); Vertex vertex2 = meshFromStlFile.CreateVertex(vector[1], CreateOption.CreateNew, SortOption.WillSortLater); Vertex vertex3 = meshFromStlFile.CreateVertex(vector[2], CreateOption.CreateNew, SortOption.WillSortLater); meshFromStlFile.CreateFace(new Vertex[] { vertex1, vertex2, vertex3 }, CreateOption.CreateNew); } } //uint numTriangles = System.BitConverter.ToSingle(fileContents, 80); } // merge all the vetexes that are in the same place together bool finishedCleanAndMerge = true; meshFromStlFile.CleanAndMergMesh(reportProgress: (double progress0To1, string processingState, out bool continueProcessing) => { if (reportProgress != null) { reportProgress(parsingFileRatio + progress0To1 * (1 - parsingFileRatio), processingState, out continueProcessing); if (!continueProcessing) { finishedCleanAndMerge = false; } } else { continueProcessing = true; } } ); if (!finishedCleanAndMerge) { return(null); } time.Stop(); Debug.WriteLine(string.Format("STL Load in {0:0.00}s", time.Elapsed.TotalSeconds)); stlStream.Close(); return(meshFromStlFile); }
public static List <MeshGroup> ParseFileContents(Stream amfStream, ReportProgressRatio reportProgress) { Stopwatch time = new Stopwatch(); time.Start(); Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; double parsingFileRatio = .5; if (amfStream == null) { return(null); } List <MeshGroup> meshGroups = null; // do the loading try { using (Stream amfCompressedStream = GetCompressedStreamIfRequired(amfStream)) { XmlReader xmlTree = XmlReader.Create(amfCompressedStream); while (xmlTree.Read()) { if (xmlTree.Name == "amf") { break; } } double scale = GetScaling(xmlTree); ProgressData progressData = new ProgressData(amfStream, reportProgress); meshGroups = new List <MeshGroup>(); while (xmlTree.Read()) { if (xmlTree.Name == "object") { using (XmlReader objectTree = xmlTree.ReadSubtree()) { meshGroups.Add(ReadObject(objectTree, scale, progressData)); if (progressData.LoadCanceled) { return(null); } } } } xmlTree.Dispose(); } } catch (Exception e) { Debug.Print(e.Message); BreakInDebugger(); return(null); } #if true // merge all the vetexes that are in the same place together int totalMeshes = 0; foreach (MeshGroup meshGroup in meshGroups) { foreach (Mesh mesh in meshGroup.Meshes) { totalMeshes++; } } double currentMeshProgress = 0; double ratioLeftToUse = 1 - parsingFileRatio; double progressPerMesh = 1.0 / totalMeshes * ratioLeftToUse; foreach (MeshGroup meshGroup in meshGroups) { foreach (Mesh mesh in meshGroup.Meshes) { bool keepProcessing = true; mesh.CleanAndMergMesh( (double progress0To1, string processingState, out bool continueProcessing) => { if (reportProgress != null) { double currentTotalProgress = parsingFileRatio + currentMeshProgress; reportProgress(currentTotalProgress + progress0To1 * progressPerMesh, processingState, out continueProcessing); keepProcessing = continueProcessing; } else { continueProcessing = true; } } ); if (!keepProcessing) { amfStream.Close(); return(null); } currentMeshProgress += progressPerMesh; } } #endif time.Stop(); Debug.WriteLine(string.Format("AMF Load in {0:0.00}s", time.Elapsed.TotalSeconds)); amfStream.Close(); bool hasValidMesh = false; foreach (MeshGroup meshGroup in meshGroups) { foreach (Mesh mesh in meshGroup.Meshes) { if (mesh.Faces.Count > 0) { hasValidMesh = true; } } } if (hasValidMesh) { return(meshGroups); } else { return(null); } }
public static bool Save(List<MeshGroup> meshGroupsToSave, string meshPathAndFileName, MeshOutputSettings outputInfo = null, ReportProgressRatio reportProgress = null) { try { if (outputInfo == null) { outputInfo = new MeshOutputSettings(); } switch (Path.GetExtension(meshPathAndFileName).ToUpper()) { case ".STL": Mesh mesh = DoMerge(meshGroupsToSave, outputInfo); return StlProcessing.Save(mesh, meshPathAndFileName, outputInfo); case ".AMF": outputInfo.ReportProgress = reportProgress; return AmfProcessing.Save(meshGroupsToSave, meshPathAndFileName, outputInfo); default: return false; } } catch (Exception) { return false; } }
public static Mesh ParseFileContents(Stream stlStream, ReportProgressRatio reportProgress) { Stopwatch time = new Stopwatch(); time.Start(); Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; double parsingFileRatio = .5; if (stlStream == null) { return null; } //MemoryStream stlStream = new MemoryStream(); //stlStreamIn.CopyTo(stlStream); Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); Mesh meshFromStlFile = new Mesh(); //meshFromStlFile.MaxDistanceToConsiderVertexAsSame = .0000005; long bytesInFile = stlStream.Length; if (bytesInFile <= 80) { return null; } byte[] first160Bytes = new byte[160]; stlStream.Read(first160Bytes, 0, 160); byte[] ByteOredrMark = new byte[] { 0xEF, 0xBB, 0xBF }; int startOfString = 0; if (first160Bytes[0] == ByteOredrMark[0] && first160Bytes[0] == ByteOredrMark[0] && first160Bytes[0] == ByteOredrMark[0]) { startOfString = 3; } string first160BytesOfSTLFile = System.Text.Encoding.UTF8.GetString(first160Bytes, startOfString, first160Bytes.Length - startOfString); if (first160BytesOfSTLFile.StartsWith("solid") && first160BytesOfSTLFile.Contains("facet")) { stlStream.Position = 0; StreamReader stlReader = new StreamReader(stlStream); int vectorIndex = 0; Vector3 vector0 = new Vector3(0, 0, 0); Vector3 vector1 = new Vector3(0, 0, 0); Vector3 vector2 = new Vector3(0, 0, 0); string line = stlReader.ReadLine(); Regex onlySingleSpaces = new Regex("\\s+", RegexOptions.Compiled); while (line != null) { line = onlySingleSpaces.Replace(line, " "); var parts = line.Trim().Split(' '); if (parts[0].Trim() == "vertex") { vectorIndex++; switch (vectorIndex) { case 1: vector0.x = Convert.ToDouble(parts[1]); vector0.y = Convert.ToDouble(parts[2]); vector0.z = Convert.ToDouble(parts[3]); break; case 2: vector1.x = Convert.ToDouble(parts[1]); vector1.y = Convert.ToDouble(parts[2]); vector1.z = Convert.ToDouble(parts[3]); break; case 3: vector2.x = Convert.ToDouble(parts[1]); vector2.y = Convert.ToDouble(parts[2]); vector2.z = Convert.ToDouble(parts[3]); if (!Vector3.Collinear(vector0, vector1, vector2)) { Vertex vertex1 = meshFromStlFile.CreateVertex(vector0, CreateOption.CreateNew, SortOption.WillSortLater); Vertex vertex2 = meshFromStlFile.CreateVertex(vector1, CreateOption.CreateNew, SortOption.WillSortLater); Vertex vertex3 = meshFromStlFile.CreateVertex(vector2, CreateOption.CreateNew, SortOption.WillSortLater); meshFromStlFile.CreateFace(new Vertex[] { vertex1, vertex2, vertex3 }, CreateOption.CreateNew); } vectorIndex = 0; break; } } line = stlReader.ReadLine(); if (reportProgress != null && maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(stlStream.Position / (double)bytesInFile * parsingFileRatio, "Loading Polygons", out continueProcessing); if (!continueProcessing) { stlStream.Close(); return null; } maxProgressReport.Restart(); } } } else { // load it as a binary stl // skip the first 80 bytes // read in the number of triangles stlStream.Position = 0; BinaryReader br = new BinaryReader(stlStream); byte[] fileContents = br.ReadBytes((int)stlStream.Length); int currentPosition = 80; uint numTriangles = System.BitConverter.ToUInt32(fileContents, currentPosition); long bytesForNormals = numTriangles * 3 * 4; long bytesForVertices = numTriangles * 3 * 4 * 3; long bytesForAttributs = numTriangles * 2; currentPosition += 4; long numBytesRequiredForVertexData = currentPosition + bytesForNormals + bytesForVertices + bytesForAttributs; if (fileContents.Length < numBytesRequiredForVertexData || numTriangles < 4) { stlStream.Close(); return null; } Vector3[] vector = new Vector3[3]; for (int i = 0; i < numTriangles; i++) { // skip the normal currentPosition += 3 * 4; for (int j = 0; j < 3; j++) { vector[j] = new Vector3( System.BitConverter.ToSingle(fileContents, currentPosition + 0 * 4), System.BitConverter.ToSingle(fileContents, currentPosition + 1 * 4), System.BitConverter.ToSingle(fileContents, currentPosition + 2 * 4)); currentPosition += 3 * 4; } currentPosition += 2; // skip the attribute if (reportProgress != null && maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(i / (double)numTriangles * parsingFileRatio, "Loading Polygons", out continueProcessing); if (!continueProcessing) { stlStream.Close(); return null; } maxProgressReport.Restart(); } if (!Vector3.Collinear(vector[0], vector[1], vector[2])) { Vertex vertex1 = meshFromStlFile.CreateVertex(vector[0], CreateOption.CreateNew, SortOption.WillSortLater); Vertex vertex2 = meshFromStlFile.CreateVertex(vector[1], CreateOption.CreateNew, SortOption.WillSortLater); Vertex vertex3 = meshFromStlFile.CreateVertex(vector[2], CreateOption.CreateNew, SortOption.WillSortLater); meshFromStlFile.CreateFace(new Vertex[] { vertex1, vertex2, vertex3 }, CreateOption.CreateNew); } } //uint numTriangles = System.BitConverter.ToSingle(fileContents, 80); } // merge all the vetexes that are in the same place together bool finishedCleanAndMerge = true; meshFromStlFile.CleanAndMergMesh( (double progress0To1, string processingState, out bool continueProcessing) => { if (reportProgress != null) { reportProgress(parsingFileRatio + progress0To1 * (1 - parsingFileRatio), processingState, out continueProcessing); if (!continueProcessing) { finishedCleanAndMerge = false; } } else { continueProcessing = true; } } ); if (!finishedCleanAndMerge) { return null; } time.Stop(); Debug.WriteLine(string.Format("STL Load in {0:0.00}s", time.Elapsed.TotalSeconds)); stlStream.Close(); return meshFromStlFile; }
public static Mesh[] SplitIntoMeshesOnOrthographicZ(Mesh meshToSplit, Vector3 buildVolume, ReportProgressRatio reportProgress) { // check if the part is bigger than the build plate (if it is we need to use that as our size) AxisAlignedBoundingBox partBounds = meshToSplit.GetAxisAlignedBoundingBox(); buildVolume.x = Math.Max(buildVolume.x, partBounds.XSize + 2); buildVolume.y = Math.Max(buildVolume.y, partBounds.YSize + 2); buildVolume.z = Math.Max(buildVolume.z, partBounds.ZSize + 2); // Find all the separate objects that are on the plate // Create a 2D image the size of the printer bed at some scale with the parts draw on it top down double scaleFactor = 5; ImageBuffer partPlate = new ImageBuffer((int)(buildVolume.x * scaleFactor), (int)(buildVolume.y * scaleFactor)); Vector2 renderOffset = new Vector2(buildVolume.x / 2, buildVolume.y / 2) - new Vector2(partBounds.Center.x, partBounds.Center.y); PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partPlate.NewGraphics2D(), meshToSplit, renderOffset, scaleFactor, RGBA_Bytes.White); bool continueProcessin = true; if (reportProgress != null) { reportProgress(.2, "", out continueProcessin); } //ImageIO.SaveImageData("test part plate 0.png", partPlate); // expand the bounds a bit so that we can collect all the vertices and polygons within each bound Dilate.DoDilate3x3Binary(partPlate, 1); //ImageIO.SaveImageData("test part plate 1.png", partPlate); // trace all the bounds of the objects on the plate PolyTree polyTreeForPlate = FindDistictObjectBounds(partPlate); if (polyTreeForPlate == null) { Mesh[] singleMesh = new Mesh[1]; singleMesh[0] = meshToSplit; return(singleMesh); } // get all the discrete areas that are polygons so we can search them Polygons discreteAreas = new Polygons(); GetAreasRecursive(polyTreeForPlate, discreteAreas); if (discreteAreas.Count == 0) { return(null); } else if (discreteAreas.Count == 1) { Mesh[] singleMesh = new Mesh[1]; singleMesh[0] = meshToSplit; return(singleMesh); } Graphics2D graphics2D = partPlate.NewGraphics2D(); graphics2D.Clear(RGBA_Bytes.Black); Random rand = new Random(); foreach (Polygon polygon in discreteAreas) { graphics2D.Render(PlatingHelper.PolygonToPathStorage(polygon), new RGBA_Bytes(rand.Next(128, 255), rand.Next(128, 255), rand.Next(128, 255))); } if (reportProgress != null) { reportProgress(.5, "", out continueProcessin); } //ImageIO.SaveImageData("test part plate 2.png", partPlate); // add each of the separate bounds polygons to new meshes Mesh[] discreteMeshes = new Mesh[discreteAreas.Count]; for (int i = 0; i < discreteAreas.Count; i++) { discreteMeshes[i] = new Mesh(); } foreach (Face face in meshToSplit.Faces) { bool faceDone = false; // figure out which area one or more of the vertices are in add the face to the right new mesh foreach (FaceEdge faceEdge in face.FaceEdges()) { Vector2 position = new Vector2(faceEdge.firstVertex.Position.x, faceEdge.firstVertex.Position.y); position += renderOffset; position *= scaleFactor; for (int areaIndex = discreteAreas.Count - 1; areaIndex >= 0; areaIndex--) { if (PointInPolygon(discreteAreas[areaIndex], new IntPoint((int)position.x, (int)position.y))) { List <Vertex> faceVertices = new List <Vertex>(); foreach (FaceEdge faceEdgeToAdd in face.FaceEdges()) { Vertex newVertex = discreteMeshes[areaIndex].CreateVertex(faceEdgeToAdd.firstVertex.Position); faceVertices.Add(newVertex); } discreteMeshes[areaIndex].CreateFace(faceVertices.ToArray()); faceDone = true; break; } } if (faceDone) { break; } } } if (reportProgress != null) { reportProgress(.8, "", out continueProcessin); } for (int i = 0; i < discreteMeshes.Count(); i++) { Mesh mesh = discreteMeshes[i]; } return(discreteMeshes); }
public async override Task<PrintItemWrapper> GetPrintItemWrapperAsync(int index, ReportProgressRatio reportProgress = null) { throw new NotImplementedException(); //return PrintHistoryData.Instance.GetPrintItemWrapper(index); }
public void MergeVertices(ReportProgressRatio reportProgress = null, double maxDistanceToConsiderVertexAsSame = 0) { HashSet<Vertex> markedForDeletion = new HashSet<Vertex>(); Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); for (int i = 0; i < Vertices.Count; i++) { Vertex vertexToKeep = Vertices[i]; if (!markedForDeletion.Contains(vertexToKeep)) { List<Vertex> samePosition = Vertices.FindVertices(vertexToKeep.Position, maxDistanceToConsiderVertexAsSame); foreach (Vertex vertexToDelete in samePosition) { if (vertexToDelete != vertexToKeep) { if (!markedForDeletion.Contains(vertexToDelete)) { #if AGRESSIVE_VALIDATING Validate(markedForDeletion); #endif MergeVertices(vertexToKeep, vertexToDelete, false); markedForDeletion.Add(vertexToDelete); #if AGRESSIVE_VALIDATING Validate(markedForDeletion); #endif } } } if (reportProgress != null) { if (maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(i / (double)Vertices.Count, "Merging Vertices", out continueProcessing); if (!continueProcessing) { return; } maxProgressReport.Restart(); } } } } #if AGRESSIVE_VALIDATING Validate(markedForDeletion); #endif if (reportProgress != null) { bool continueProcessing; reportProgress(1, "Deleting Unused Vertices", out continueProcessing); } RemoveVerticesMarkedForDeletion(markedForDeletion); }
private void PushMeshGroupDataToAsynchLists(TraceInfoOpperation traceInfoOpperation, ReportProgressRatio reportProgress = null) { UiThread.RunOnIdle(() => { processingProgressControl.ProgressMessage = "Async Copy"; }); asynchMeshGroups.Clear(); asynchMeshGroupTransforms.Clear(); for (int meshGroupIndex = 0; meshGroupIndex < MeshGroups.Count; meshGroupIndex++) { MeshGroup meshGroup = MeshGroups[meshGroupIndex]; MeshGroup newMeshGroup = new MeshGroup(); for (int meshIndex = 0; meshIndex < meshGroup.Meshes.Count; meshIndex++) { Mesh mesh = meshGroup.Meshes[meshIndex]; newMeshGroup.Meshes.Add(Mesh.Copy(mesh)); } asynchMeshGroups.Add(newMeshGroup); asynchMeshGroupTransforms.Add(MeshGroupTransforms[meshGroupIndex]); } asynchPlatingDatas.Clear(); for (int meshGroupIndex = 0; meshGroupIndex < MeshGroupExtraData.Count; meshGroupIndex++) { PlatingMeshGroupData meshData = new PlatingMeshGroupData(); meshData.currentScale = MeshGroupExtraData[meshGroupIndex].currentScale; MeshGroup meshGroup = MeshGroups[meshGroupIndex]; if (traceInfoOpperation == TraceInfoOpperation.DO_COPY) { meshData.meshTraceableData.AddRange(MeshGroupExtraData[meshGroupIndex].meshTraceableData); } asynchPlatingDatas.Add(meshData); } UiThread.RunOnIdle(() => { processingProgressControl.ProgressMessage = ""; }); }
public static Mesh Copy(Mesh meshToCopy, ReportProgressRatio progress = null) { Mesh newMesh = new Mesh(); if (meshToCopy.Vertices.IsSorted) { Dictionary<Vertex, int> vertexIndexDictionary = GetVertexToIndexDictionary(meshToCopy, newMesh); Dictionary<MeshEdge, int> meshEdgeIndexDictionary = GetMeshEdgeToIndexDictionary(meshToCopy, newMesh); for (int faceIndex = 0; faceIndex < meshToCopy.Faces.Count; faceIndex++) { Face faceToCopy = meshToCopy.Faces[faceIndex]; newMesh.Faces.Add(new Face()); } // now set all the data for the new mesh newMesh.Vertices.Capacity = meshToCopy.Vertices.Capacity; for (int vertexIndex = 0; vertexIndex < meshToCopy.Vertices.Count; vertexIndex++) { Vertex vertexToCopy = meshToCopy.Vertices[vertexIndex]; // !!!! ON ERROR !!!!! If this throws an error, you likely need to CleanAndMergMesh the mesh before copying int indexOfFirstMeshEdge = meshEdgeIndexDictionary[vertexToCopy.firstMeshEdge]; Vertex newVertex = newMesh.Vertices[vertexIndex]; newVertex.firstMeshEdge = newMesh.MeshEdges[indexOfFirstMeshEdge]; newVertex.Normal = vertexToCopy.Normal; } newMesh.MeshEdges.Capacity = meshToCopy.MeshEdges.Capacity; for (int meshEdgeIndex = 0; meshEdgeIndex < meshToCopy.MeshEdges.Count; meshEdgeIndex++) { MeshEdge meshEdgeToCopy = meshToCopy.MeshEdges[meshEdgeIndex]; MeshEdge newMeshEdge = newMesh.MeshEdges[meshEdgeIndex]; newMeshEdge.NextMeshEdgeFromEnd[0] = newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeToCopy.NextMeshEdgeFromEnd[0]]]; newMeshEdge.NextMeshEdgeFromEnd[1] = newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeToCopy.NextMeshEdgeFromEnd[1]]]; newMeshEdge.VertexOnEnd[0] = newMesh.Vertices[vertexIndexDictionary[meshEdgeToCopy.VertexOnEnd[0]]]; newMeshEdge.VertexOnEnd[1] = newMesh.Vertices[vertexIndexDictionary[meshEdgeToCopy.VertexOnEnd[1]]]; // This will get hooked up when we create radial loops with the face edges below //newMeshEdge.firstFaceEdge; //newMesh.MeshEdges.Add(newMeshEdge); } newMesh.Faces.Capacity = meshToCopy.Faces.Capacity; for (int faceIndex = 0; faceIndex < meshToCopy.faces.Count; faceIndex++) { Face faceToCopy = meshToCopy.faces[faceIndex]; Face newface = newMesh.faces[faceIndex]; newface.normal = faceToCopy.normal; // hook up the face edges //public FaceEdge firstFaceEdge; List<Vertex> verticesFromCopy = new List<Vertex>(); List<Vertex> verticesForNew = new List<Vertex>(); foreach (Vertex vertex in faceToCopy.Vertices()) { verticesFromCopy.Add(vertex); verticesForNew.Add(newMesh.Vertices[vertexIndexDictionary[vertex]]); } List<MeshEdge> edgesFromCopy = new List<MeshEdge>(); List<MeshEdge> edgesForNew = new List<MeshEdge>(); for (int i = 0; i < verticesForNew.Count - 1; i++) { MeshEdge meshEdgeFromCopy = verticesFromCopy[i].GetMeshEdgeConnectedToVertex(verticesFromCopy[i + 1]); edgesFromCopy.Add(meshEdgeFromCopy); edgesForNew.Add(newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeFromCopy]]); } MeshEdge lastMeshEdgeFromCopy = verticesFromCopy[verticesFromCopy.Count - 1].GetMeshEdgeConnectedToVertex(verticesFromCopy[0]); edgesFromCopy.Add(lastMeshEdgeFromCopy); edgesForNew.Add(newMesh.MeshEdges[meshEdgeIndexDictionary[lastMeshEdgeFromCopy]]); CreateFaceEdges(verticesForNew.ToArray(), edgesForNew, newface); } } else { foreach (Face face in meshToCopy.Faces) { List<Vertex> faceVertices = new List<Vertex>(); foreach (FaceEdge faceEdgeToAdd in face.FaceEdges()) { Vertex newVertex = newMesh.CreateVertex(faceEdgeToAdd.firstVertex.Position, CreateOption.CreateNew, SortOption.WillSortLater); faceVertices.Add(newVertex); } newMesh.CreateFace(faceVertices.ToArray(), CreateOption.CreateNew); } newMesh.CleanAndMergMesh(); } MeshMaterialData materialDataToCopy = MeshMaterialData.Get(meshToCopy); MeshMaterialData newMaterialData = MeshMaterialData.Get(newMesh); newMaterialData.MaterialIndex = materialDataToCopy.MaterialIndex; return newMesh; }
public async override Task<PrintItemWrapper> GetPrintItemWrapperAsync(int index, ReportProgressRatio reportProgress = null) { return QueueData.Instance.GetPrintItemWrapper(index); }
private static List <IPrimitive> AddTraceDataForMesh(Mesh mesh, int totalActionCount, ref int currentAction, ref bool needToUpdateProgressReport, ReportProgressRatio reportProgress) { bool continueProcessing; List <IPrimitive> allPolys = new List <IPrimitive>(); List <Vector3> positions = new List <Vector3>(); foreach (Face face in mesh.Faces) { positions.Clear(); foreach (Vertex vertex in face.Vertices()) { positions.Add(vertex.Position); } // We should use the teselator for this if it is greater than 3. Vector3 next = positions[1]; for (int positionIndex = 2; positionIndex < positions.Count; positionIndex++) { TriangleShape triangel = new TriangleShape(positions[0], next, positions[positionIndex], null); allPolys.Add(triangel); next = positions[positionIndex]; } if (reportProgress != null) { if ((currentAction % 256) == 0 || needToUpdateProgressReport) { reportProgress(currentAction / (double)totalActionCount, "Creating Trace Polygons", out continueProcessing); needToUpdateProgressReport = false; } currentAction++; } } return(allPolys); }
private static List<IPrimitive> AddTraceDataForMesh(Mesh mesh, int totalActionCount, ref int currentAction, ref bool needToUpdateProgressReport, ReportProgressRatio reportProgress) { bool continueProcessing; List<IPrimitive> allPolys = new List<IPrimitive>(); List<Vector3> positions = new List<Vector3>(); foreach (Face face in mesh.Faces) { positions.Clear(); foreach (Vertex vertex in face.Vertices()) { positions.Add(vertex.Position); } // We should use the teselator for this if it is greater than 3. Vector3 next = positions[1]; for (int positionIndex = 2; positionIndex < positions.Count; positionIndex++) { TriangleShape triangel = new TriangleShape(positions[0], next, positions[positionIndex], null); allPolys.Add(triangel); next = positions[positionIndex]; } if (reportProgress != null) { if ((currentAction % 256) == 0 || needToUpdateProgressReport) { reportProgress(currentAction / (double)totalActionCount, "Creating Trace Polygons", out continueProcessing); needToUpdateProgressReport = false; } currentAction++; } } return allPolys; }
public void MergeMeshEdges(ReportProgressRatio reportProgress = null) { HashSet<MeshEdge> markedForDeletion = new HashSet<MeshEdge>(); Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); for (int i = 0; i < MeshEdges.Count; i++) { MeshEdge currentMeshEdge = MeshEdges[i]; if (!markedForDeletion.Contains(currentMeshEdge)) { Vertex vertex0 = currentMeshEdge.VertexOnEnd[0]; Vertex vertex1 = currentMeshEdge.VertexOnEnd[1]; // find out if there is another edge attached to the same vertexes List<MeshEdge> meshEdgesToDelete = FindMeshEdges(vertex0, vertex1); if (meshEdgesToDelete.Count > 1) { foreach (MeshEdge meshEdgeToDelete in meshEdgesToDelete) { if (meshEdgeToDelete != currentMeshEdge) { if (!markedForDeletion.Contains(meshEdgeToDelete)) { MergeMeshEdges(currentMeshEdge, meshEdgeToDelete, false); markedForDeletion.Add(meshEdgeToDelete); } } } } } if (reportProgress != null) { if (maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(i / (double)MeshEdges.Count, "Merging Mesh Edges", out continueProcessing); maxProgressReport.Restart(); if (!continueProcessing) { return; } } } } RemoveMeshEdgesMarkedForDeletion(markedForDeletion); }
public static List<MeshGroup> Load(string meshPathAndFileName, ReportProgressRatio reportProgress = null) { try { using (Stream stream = new FileStream(meshPathAndFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { return Load(stream, Path.GetExtension(meshPathAndFileName), reportProgress); } } catch(Exception e) { Debug.Print(e.Message); return null; } }
public static void CreateITraceableForMeshGroup(List <PlatingMeshGroupData> perMeshGroupInfo, List <MeshGroup> meshGroups, int meshGroupIndex, ReportProgressRatio reportProgress) { if (meshGroups != null) { MeshGroup meshGroup = meshGroups[meshGroupIndex]; perMeshGroupInfo[meshGroupIndex].meshTraceableData.Clear(); int totalActionCount = 0; foreach (Mesh mesh in meshGroup.Meshes) { totalActionCount += mesh.Faces.Count; } int currentAction = 0; bool needUpdateTitle = true; for (int i = 0; i < meshGroup.Meshes.Count; i++) { Mesh mesh = meshGroup.Meshes[i]; List <IRayTraceable> allPolys = new List <IRayTraceable>(); List <Vector3> positions = new List <Vector3>(); bool continueProcessing; foreach (Face face in mesh.Faces) { positions.Clear(); foreach (Vertex vertex in face.Vertices()) { positions.Add(vertex.Position); } // We should use the teselator for this if it is greater than 3. Vector3 next = positions[1]; for (int positionIndex = 2; positionIndex < positions.Count; positionIndex++) { TriangleShape triangel = new TriangleShape(positions[0], next, positions[positionIndex], null); allPolys.Add(triangel); next = positions[positionIndex]; } if (reportProgress != null) { if ((currentAction % 256) == 0 || needUpdateTitle) { reportProgress(currentAction / (double)totalActionCount, "Creating Trace Polygons", out continueProcessing); needUpdateTitle = false; } currentAction++; } } needUpdateTitle = true; if (reportProgress != null) { reportProgress(currentAction / (double)totalActionCount, "Creating Trace Group", out continueProcessing); } #if false // this is to do some timing on creating tracking info Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); #endif perMeshGroupInfo[meshGroupIndex].meshTraceableData.Add(BoundingVolumeHierarchy.CreateNewHierachy(allPolys)); #if false stopWatch.Stop(); using (StreamWriter outputStream = File.AppendText("output.txt")) { outputStream.WriteLine("Plating Helper BoundingVolumeHierarchy.CreateNewHierachy {0:0.00} seconds".FormatWith(stopWatch.Elapsed.TotalSeconds)); } #endif } } }
public static List<MeshGroup> Load(Stream fileStream, ReportProgressRatio reportProgress = null) { List<MeshGroup> loadedMeshes; try { loadedMeshes = ParseFileContents(fileStream, reportProgress); } #if DEBUG catch (IOException e) { Debug.Print(e.Message); BreakInDebugger(); return null; } #else catch (Exception) { return null; } #endif return loadedMeshes; }
public async override Task<PrintItemWrapper> GetPrintItemWrapperAsync(int index, ReportProgressRatio reportProgress = null) { if (index >= 0 && index < printItems.Count) { return printItems[index]; } return null; }
public static List<MeshGroup> ParseFileContents(Stream amfStream, ReportProgressRatio reportProgress) { Stopwatch time = new Stopwatch(); time.Start(); Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; double parsingFileRatio = .5; if (amfStream == null) { return null; } List<MeshGroup> meshGroups = null; // do the loading try { using (Stream amfCompressedStream = GetCompressedStreamIfRequired(amfStream)) { XmlReader xmlTree = XmlReader.Create(amfCompressedStream); while (xmlTree.Read()) { if (xmlTree.Name == "amf") { break; } } double scale = GetScaling(xmlTree); ProgressData progressData = new ProgressData(amfStream, reportProgress); meshGroups = new List<MeshGroup>(); while (xmlTree.Read()) { if (xmlTree.Name == "object") { using (XmlReader objectTree = xmlTree.ReadSubtree()) { meshGroups.Add(ReadObject(objectTree, scale, progressData)); if (progressData.LoadCanceled) { return null; } } } } xmlTree.Dispose(); } } catch (Exception e) { Debug.Print(e.Message); BreakInDebugger(); return null; } #if true // merge all the vetexes that are in the same place together int totalMeshes = 0; foreach (MeshGroup meshGroup in meshGroups) { foreach (Mesh mesh in meshGroup.Meshes) { totalMeshes++; } } double currentMeshProgress = 0; double ratioLeftToUse = 1 - parsingFileRatio; double progressPerMesh = 1.0 / totalMeshes * ratioLeftToUse; foreach (MeshGroup meshGroup in meshGroups) { foreach (Mesh mesh in meshGroup.Meshes) { bool keepProcessing = true; mesh.CleanAndMergMesh( (double progress0To1, string processingState, out bool continueProcessing) => { if (reportProgress != null) { double currentTotalProgress = parsingFileRatio + currentMeshProgress; reportProgress(currentTotalProgress + progress0To1 * progressPerMesh, processingState, out continueProcessing); keepProcessing = continueProcessing; } else { continueProcessing = true; } } ); if (!keepProcessing) { amfStream.Close(); return null; } currentMeshProgress += progressPerMesh; } } #endif time.Stop(); Debug.WriteLine(string.Format("AMF Load in {0:0.00}s", time.Elapsed.TotalSeconds)); amfStream.Close(); bool hasValidMesh = false; foreach (MeshGroup meshGroup in meshGroups) { foreach (Mesh mesh in meshGroup.Meshes) { if (mesh.Faces.Count > 0) { hasValidMesh = true; } } } if (hasValidMesh) { return meshGroups; } else { return null; } }
public static void CreateITraceableForMeshGroup(List <PlatingMeshGroupData> perMeshGroupInfo, List <MeshGroup> meshGroups, int meshGroupIndex, ReportProgressRatio reportProgress) { if (meshGroups != null) { MeshGroup meshGroup = meshGroups[meshGroupIndex]; perMeshGroupInfo[meshGroupIndex].meshTraceableData.Clear(); int totalActionCount = 0; foreach (Mesh mesh in meshGroup.Meshes) { totalActionCount += mesh.Faces.Count; } int currentAction = 0; bool needUpdateTitle = true; for (int i = 0; i < meshGroup.Meshes.Count; i++) { Mesh mesh = meshGroup.Meshes[i]; List <IPrimitive> allPolys = AddTraceDataForMesh(mesh, totalActionCount, ref currentAction, ref needUpdateTitle, reportProgress); needUpdateTitle = true; if (reportProgress != null) { bool continueProcessing; reportProgress(currentAction / (double)totalActionCount, "Creating Trace Group", out continueProcessing); } // only allow limited recusion to speed this up building this data IPrimitive traceData = BoundingVolumeHierarchy.CreateNewHierachy(allPolys, 0); perMeshGroupInfo[meshGroupIndex].meshTraceableData.Add(traceData); } } }
public static List <Mesh> SplitConnectedIntoMeshes(MeshGroup meshGroupToSplit, ReportProgressRatio reportProgress) { List <Mesh> discreteMeshes = new List <Mesh>(); double ratioPerDiscreetMesh = 1.0 / meshGroupToSplit.Meshes.Count; double currentRatioDone = 0; foreach (Mesh mesh in meshGroupToSplit.Meshes) { List <Mesh> discreteVolumes = SplitVolumesIntoMeshes(mesh, (double progress0To1, string processingState, out bool continueProcessing) => { if (reportProgress != null) { double progress = (currentRatioDone + ratioPerDiscreetMesh * progress0To1); reportProgress(progress, "Split Into Meshes", out continueProcessing); } else { continueProcessing = true; } }); discreteMeshes.AddRange(discreteVolumes); currentRatioDone += ratioPerDiscreetMesh; } return(discreteMeshes); }
public static Mesh[] SplitIntoMeshesOnOrthographicZ(Mesh meshToSplit, Vector3 buildVolume, ReportProgressRatio reportProgress) { // check if the part is bigger than the build plate (if it is we need to use that as our size) AxisAlignedBoundingBox partBounds = meshToSplit.GetAxisAlignedBoundingBox(); buildVolume.x = Math.Max(buildVolume.x, partBounds.XSize + 2); buildVolume.y = Math.Max(buildVolume.y, partBounds.YSize + 2); buildVolume.z = Math.Max(buildVolume.z, partBounds.ZSize + 2); // Find all the separate objects that are on the plate // Create a 2D image the size of the printer bed at some scale with the parts draw on it top down double scaleFactor = 5; ImageBuffer partPlate = new ImageBuffer((int)(buildVolume.x * scaleFactor), (int)(buildVolume.y * scaleFactor), 32, new BlenderBGRA()); Vector2 renderOffset = new Vector2(buildVolume.x / 2, buildVolume.y / 2) - new Vector2(partBounds.Center.x, partBounds.Center.y); PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partPlate.NewGraphics2D(), meshToSplit, renderOffset, scaleFactor, RGBA_Bytes.White); bool continueProcessin = true; if (reportProgress != null) { reportProgress(.2, "", out continueProcessin); } //ImageIO.SaveImageData("test part plate 0.png", partPlate); // expand the bounds a bit so that we can collect all the vertices and polygons within each bound Dilate.DoDilate3x3Binary(partPlate, 1); //ImageIO.SaveImageData("test part plate 1.png", partPlate); // trace all the bounds of the objects on the plate PolyTree polyTreeForPlate = FindDistictObjectBounds(partPlate); if (polyTreeForPlate == null) { Mesh[] singleMesh = new Mesh[1]; singleMesh[0] = meshToSplit; return singleMesh; } // get all the discrete areas that are polygons so we can search them Polygons discreteAreas = new Polygons(); GetAreasRecursive(polyTreeForPlate, discreteAreas); if (discreteAreas.Count == 0) { return null; } else if (discreteAreas.Count == 1) { Mesh[] singleMesh = new Mesh[1]; singleMesh[0] = meshToSplit; return singleMesh; } Graphics2D graphics2D = partPlate.NewGraphics2D(); graphics2D.Clear(RGBA_Bytes.Black); Random rand = new Random(); foreach (Polygon polygon in discreteAreas) { graphics2D.Render(PlatingHelper.PolygonToPathStorage(polygon), new RGBA_Bytes(rand.Next(128, 255), rand.Next(128, 255), rand.Next(128, 255))); } if (reportProgress != null) { reportProgress(.5, "", out continueProcessin); } //ImageIO.SaveImageData("test part plate 2.png", partPlate); // add each of the separate bounds polygons to new meshes Mesh[] discreteMeshes = new Mesh[discreteAreas.Count]; for (int i = 0; i < discreteAreas.Count; i++) { discreteMeshes[i] = new Mesh(); } foreach (Face face in meshToSplit.Faces) { bool faceDone = false; // figure out which area one or more of the vertices are in add the face to the right new mesh foreach (FaceEdge faceEdge in face.FaceEdges()) { Vector2 position = new Vector2(faceEdge.firstVertex.Position.x, faceEdge.firstVertex.Position.y); position += renderOffset; position *= scaleFactor; for (int areaIndex = discreteAreas.Count - 1; areaIndex >= 0; areaIndex--) { if (PointInPolygon(discreteAreas[areaIndex], new IntPoint((int)position.x, (int)position.y))) { List<Vertex> faceVertices = new List<Vertex>(); foreach (FaceEdge faceEdgeToAdd in face.FaceEdges()) { Vertex newVertex = discreteMeshes[areaIndex].CreateVertex(faceEdgeToAdd.firstVertex.Position); faceVertices.Add(newVertex); } discreteMeshes[areaIndex].CreateFace(faceVertices.ToArray()); faceDone = true; break; } } if (faceDone) { break; } } } if (reportProgress != null) { reportProgress(.8, "", out continueProcessin); } for (int i = 0; i < discreteMeshes.Count(); i++) { Mesh mesh = discreteMeshes[i]; } return discreteMeshes; }
public static List <Mesh> SplitVolumesIntoMeshes(Mesh meshToSplit, ReportProgressRatio reportProgress) { List <Mesh> discreetVolumes = new List <Mesh>(); HashSet <Face> facesThatHaveBeenAdded = new HashSet <Face>(); Mesh meshFromCurrentVolume = null; Stack <Face> attachedFaces = new Stack <Face>(); for (int faceIndex = 0; faceIndex < meshToSplit.Faces.Count; faceIndex++) { Face currentFace = meshToSplit.Faces[faceIndex]; // If this face as not been added to any volume, create a new volume and add all of the attached faces. if (!facesThatHaveBeenAdded.Contains(currentFace)) { attachedFaces.Push(currentFace); meshFromCurrentVolume = new Mesh(); MeshMaterialData materialDataToCopy = MeshMaterialData.Get(meshToSplit); MeshMaterialData newMaterialData = MeshMaterialData.Get(meshFromCurrentVolume); newMaterialData.MaterialIndex = materialDataToCopy.MaterialIndex; while (attachedFaces.Count > 0) { Face faceToAdd = attachedFaces.Pop(); foreach (Vertex attachedVertex in faceToAdd.Vertices()) { foreach (Face faceAttachedToVertex in attachedVertex.ConnectedFaces()) { if (!facesThatHaveBeenAdded.Contains(faceAttachedToVertex)) { // marke that this face has been taken care of facesThatHaveBeenAdded.Add(faceAttachedToVertex); // add it to the list of faces we need to walk attachedFaces.Push(faceAttachedToVertex); // Add a new face to the new mesh we are creating. List <Vertex> faceVertices = new List <Vertex>(); foreach (FaceEdge faceEdgeToAdd in faceAttachedToVertex.FaceEdges()) { Vertex newVertex = meshFromCurrentVolume.CreateVertex(faceEdgeToAdd.firstVertex.Position, CreateOption.CreateNew, SortOption.WillSortLater); faceVertices.Add(newVertex); } meshFromCurrentVolume.CreateFace(faceVertices.ToArray(), CreateOption.CreateNew); } } } } meshFromCurrentVolume.CleanAndMergMesh(); discreetVolumes.Add(meshFromCurrentVolume); meshFromCurrentVolume = null; } if (reportProgress != null) { double progress = faceIndex / (double)meshToSplit.Faces.Count; bool continueProcessing; reportProgress(progress, "Split Into Meshes", out continueProcessing); } } return(discreetVolumes); }
public static List<Mesh> SplitVolumesIntoMeshes(Mesh meshToSplit, ReportProgressRatio reportProgress) { List<Mesh> discreetVolumes = new List<Mesh>(); HashSet<Face> facesThatHaveBeenAdded = new HashSet<Face>(); Mesh meshFromCurrentVolume = null; Stack<Face> attachedFaces = new Stack<Face>(); for (int faceIndex = 0; faceIndex < meshToSplit.Faces.Count; faceIndex++) { Face currentFace = meshToSplit.Faces[faceIndex]; // If this face as not been added to any volume, create a new volume and add all of the attached faces. if (!facesThatHaveBeenAdded.Contains(currentFace)) { attachedFaces.Push(currentFace); meshFromCurrentVolume = new Mesh(); MeshMaterialData materialDataToCopy = MeshMaterialData.Get(meshToSplit); MeshMaterialData newMaterialData = MeshMaterialData.Get(meshFromCurrentVolume); newMaterialData.MaterialIndex = materialDataToCopy.MaterialIndex; while (attachedFaces.Count > 0) { Face faceToAdd = attachedFaces.Pop(); foreach (Vertex attachedVertex in faceToAdd.Vertices()) { foreach (Face faceAttachedToVertex in attachedVertex.ConnectedFaces()) { if (!facesThatHaveBeenAdded.Contains(faceAttachedToVertex)) { // marke that this face has been taken care of facesThatHaveBeenAdded.Add(faceAttachedToVertex); // add it to the list of faces we need to walk attachedFaces.Push(faceAttachedToVertex); // Add a new face to the new mesh we are creating. List<Vertex> faceVertices = new List<Vertex>(); foreach (FaceEdge faceEdgeToAdd in faceAttachedToVertex.FaceEdges()) { Vertex newVertex = meshFromCurrentVolume.CreateVertex(faceEdgeToAdd.firstVertex.Position, CreateOption.CreateNew, SortOption.WillSortLater); faceVertices.Add(newVertex); } meshFromCurrentVolume.CreateFace(faceVertices.ToArray(), CreateOption.CreateNew); } } } } meshFromCurrentVolume.CleanAndMergMesh(); discreetVolumes.Add(meshFromCurrentVolume); meshFromCurrentVolume = null; } if (reportProgress != null) { double progress = faceIndex / (double)meshToSplit.Faces.Count; bool continueProcessing; reportProgress(progress, "Split Into Meshes", out continueProcessing); } } return discreetVolumes; }
public override void AddFilesToLibrary(IList <string> files, ReportProgressRatio reportProgress = null) { throw new NotImplementedException(); }