private void RemoveHeatingOfUnusedTools(HashSet <int> usedTools) { // Filter out heating for unsused tools foreach (GCodeLayer l in layers) { foreach (GCodeSegment s in l.Segments) { for (int i = 0; i < s.Lines.Count; i++) { GCodeLine line = s.Lines[i]; if (line.Content.StartsWith("G10 P", StringComparison.InvariantCulture)) { int?toolNo = line.GetIValue('P'); if (!usedTools.Contains(toolNo.Value)) { // If this tool was never called remove it's heating command s.Lines.RemoveAt(i); // We need to manually decrement i to not miss the next line --i; } } } } } }
// Split up the G-code file into different segments holding corresponding G-code lines plus feedrate // Each segment is created when // - the tool number OR // - the print region as indicated by S3D ("; feature..." or "; ...") // changes. // These segments are combined later on in the post-processing step public async Task PreProcess() { StreamReader reader = new StreamReader(input); string lineBuffer = await reader.ReadLineAsync(); if (lineBuffer == null) { throw new ProcessorException("File is empty"); } if (lineBuffer.Contains("G-Code generated by Simplify3D(R)")) { maxProgress.Report((int)input.Length); double feedrate = DefaultFeedrate; double firstLayerHeight = 0; bool rotaryPrinting = settings.RotaryPrinting != null; int lineNumber = 1, numExtrusions = 0; bool isInterfacingSet = true; GCodeLayer layer = new GCodeLayer(0, 0.0), lastLayer = null; GCodeSegment segment = new GCodeSegment("Initialization", -1, null); layer.Segments.Add(segment); HashSet <int> usedTools = new HashSet <int>(); do { bool writeLine = true; GCodeLine line = new GCodeLine(lineBuffer); if (lineBuffer.StartsWith(";", StringComparison.InvariantCulture)) { if (lineBuffer.StartsWith("; layer ", StringComparison.InvariantCulture)) { segment.LastPosition = lastPoint.Clone(); // Add past layer layers.Add(layer); lastLayer = layer; // Get the Z height. S3D provides it via the comment except before the end string lastParameter = lineBuffer.Split(' ').Last(); double zHeight = (lastParameter == "end") ? double.NaN : double.Parse(lastParameter, FrmMain.numberFormat); if (lineBuffer.StartsWith("; layer 1, Z =", StringComparison.InvariantCulture)) { firstLayerHeight = zHeight; } // Create a new one layer = new GCodeLayer(layer.Number + 1, zHeight); segment = new GCodeSegment(lineBuffer, segment.Tool, segment); layer.Segments.Add(segment); isInterfacingSet = layer.Number < 2; } else if ((layer.Number == 0 && lineNumber > 2 && !lineBuffer.Contains("layerHeight")) || lineBuffer.StartsWith("; tool", StringComparison.InvariantCulture) || lineBuffer.StartsWith("; process", StringComparison.InvariantCulture)) { // Keep first two comment lines but get rid of S3D process description and // remove "; tool" as well as "; process" lines because they are completely useless writeLine = false; // Try to get the tool change parameters if (lineBuffer.Contains("toolChangeRetractionDistance")) { double?value = line.GetFValue(',', true); if (value.HasValue) { toolChangeRetractionDistance = value.Value; } } if (lineBuffer.Contains("toolChangeRetractionSpeed")) { double?value = line.GetFValue(',', true); if (value.HasValue) { toolChangeRetractionSpeed = value.Value; } } } else if (layer.Number > 0) { // T-codes are generated just before a new segment starts string region = lineBuffer.Substring(lineBuffer.StartsWith("; feature", StringComparison.InvariantCulture) ? 9 : 1).Trim(); if (segment.Lines.Count == 0) { segment.Name = region; } else { segment = new GCodeSegment(region, segment.Tool, segment); layer.Segments.Add(segment); } } } else { int?gCode = line.GetIValue('G'); if (gCode.HasValue) { // G0 / G1 if (gCode == 0 || gCode == 1) { double?xParam = line.GetFValue('X'); double?yParam = line.GetFValue('Y'); double?zParam = line.GetFValue('Z'); if (xParam.HasValue) { lastPoint.X = xParam.Value; } if (yParam.HasValue) { if (rotaryPrinting) { yParam = HandleRescale(firstLayerHeight, line, yParam); } lastPoint.Y = yParam.Value; } if (zParam.HasValue) { lastPoint.Z = zParam.Value; } if (numExtrusions < 2) { if (line.GetFValue('E').HasValue) { numExtrusions++; writeLine = false; } } double?fParam = line.GetFValue('F'); if (fParam.HasValue) { feedrate = fParam.Value / 60.0; } if (!isInterfacingSet && segment.Tool != -1 && xParam.HasValue && yParam.HasValue) { segment.IsInterfacing = GetClosestSegment(lastLayer, xParam.Value, yParam.Value)?.Tool != segment.Tool; isInterfacingSet = true; } } // G10 else if (gCode == 10) { int? pParam = line.GetIValue('P'); double?sParam = line.GetFValue('S'); if (pParam.HasValue && pParam.Value > 0 && pParam.Value <= settings.Tools.Length && sParam.HasValue) { // G10 P... S... settings.Tools[pParam.Value - 1].ActiveTemperature = (decimal)sParam.Value; } } else if (gCode == 28) { lastPoint = homingPosition.Clone(); } } else { int?mCode = line.GetIValue('M'); if (mCode.HasValue) { // M104 if (mCode == 104) { double?sParam = line.GetFValue('S'); int? tParam = line.GetIValue('T'); if (sParam.HasValue && tParam.HasValue && tParam.Value > 0 && tParam.Value <= settings.Tools.Length) { ToolSettings toolSettings = settings.Tools[tParam.Value - 1]; if (toolSettings.Type == ToolType.Nozzle) { if (toolSettings.ActiveTemperature <= 0m) { toolSettings.ActiveTemperature = (decimal)sParam.Value; segment.AddLine($"G10 P{tParam} R{toolSettings.StandbyTemperature.ToString(FrmMain.numberFormat)} S{toolSettings.ActiveTemperature.ToString(FrmMain.numberFormat)}"); } else { segment.AddLine($"G10 P{tParam} S{sParam.Value.ToString(FrmMain.numberFormat)}"); } } writeLine = false; } } } else { // T-Code int?tCode = line.GetIValue('T'); if (tCode.HasValue) { if (tCode > 0 && tCode <= settings.Tools.Length) { usedTools.Add(tCode.Value); if (settings.Tools[tCode.Value - 1].Type == ToolType.Nozzle) { // Keep track of tools in use. Tool change sequences are inserted by the post-processor if (segment.Lines.Count <= 1) { segment.Tool = tCode.Value; } else { segment = new GCodeSegment(segment.Name, tCode.Value, segment); layer.Segments.Add(segment); } writeLine = false; } else { // Make sure we don't print with inproperly configured tools... throw new ProcessorException($"Tool {tCode} is not configured as a nozzle (see line {lineNumber})"); } } else if (segment.Lines.Count == 0) { segment.Tool = -1; } else { segment = new GCodeSegment(segment.Name, -1, segment); layer.Segments.Add(segment); } } } } } // Add this line unless it was handled before if (writeLine) { line.Feedrate = feedrate; segment.AddLine(line); } lineBuffer = await reader.ReadLineAsync(); lineNumber++; // Report progress to the UI progress.Report((int)input.Position); } while (lineBuffer != null); layers.Add(layer); RemoveHeatingOfUnusedTools(usedTools); if (rotaryPrinting) { RotaryPrintingFixes(); } } else if (lineBuffer.Contains("Diabase")) { throw new ProcessorException("File has been already processed"); } else { throw new ProcessorException("File was not generated by Simplify3D"); } }