コード例 #1
0
        private void RotaryPrintingFixes()
        {
            if (layers.Count == 0 || layers[0].Segments.Count == 0)
            {
                return;
            }
            GCodeSegment initialization = layers[0].Segments[0];

            for (int i = 0; i < initialization.Lines.Count; i++)
            {
                GCodeLine line = initialization.Lines[i];
                if (line.Content.StartsWith("G28", StringComparison.InvariantCulture))
                {
                    initialization.Lines.RemoveAt(i);
                    // We need to manually decrement i to not miss the next line
                    --i;
                }
                else if (line.Content.StartsWith("G32", StringComparison.InvariantCulture))
                {
                    initialization.Lines.RemoveAt(i);
                    initialization.Lines.Insert(i, new GCodeLine("G29 S1 ; Load height map"));
                    break;
                }
            }
        }
コード例 #2
0
 public GCodeSegment(string name, int tool, GCodeSegment lastSegment)
 {
     Name  = name;
     Tool  = tool;
     Lines = new List <GCodeLine>();
     last  = lastSegment;
 }
コード例 #3
0
 private OverrideRule GetRule(int tool, int layer, GCodeSegment segment)
 {
     foreach (OverrideRule rule in rules)
     {
         if (rule.Matches(tool, layer, segment))
         {
             return(rule);
         }
     }
     return(null);
 }
コード例 #4
0
        private GCodeSegment GetClosestSegment(GCodeLayer layer, double x, double y)
        {
            GCodeSegment minSegment = null;
            double       minDistance = 0.0;
            double       lastX = double.NaN, lastY = double.NaN;

            foreach (GCodeSegment segment in layer.Segments)
            {
                foreach (GCodeLine line in segment.Lines)
                {
                    int?gCode = line.GetIValue('G');
                    if (gCode == 0 || gCode == 1)
                    {
                        double?xCoord = line.GetFValue('X');
                        double?yCoord = line.GetFValue('Y');
                        if (xCoord.HasValue && yCoord.HasValue)
                        {
                            if (double.IsNaN(lastX) || double.IsNaN(lastY))
                            {
                                lastX = xCoord.Value;
                                lastY = yCoord.Value;
                            }
                            else if (line.GetFValue('E').HasValue)
                            {
                                // Get distance from the extruding G0/G1 line segment ([lastX, lastY] to [xCoord, yCoord]) to [x, y]
                                double distance = Math.Abs((yCoord.Value - lastY) * x - (xCoord.Value - lastX) * y + xCoord.Value * lastY - yCoord.Value * lastX) /
                                                  Math.Sqrt(Math.Pow(yCoord.Value - lastY, 2) + Math.Pow(xCoord.Value - lastX, 2));
                                if (minSegment == null || distance < minDistance)
                                {
                                    minSegment  = segment;
                                    minDistance = distance;
                                }
                            }
                        }
                    }
                }
            }
            return(minSegment);
        }
コード例 #5
0
        private Coordinate EnrichSegment(GCodeLayer layer, GCodeSegment segment, List <GCodeLine> replacementLines, int toolNumber, ref int currentTool, ref OverrideRule activeRule, ref double currentZ)
        {
            bool primeTool = false;
            bool ensureUnhopAfterToolChange = false;

            foreach (GCodeLine line in segment.Lines)
            {
                // Get GCode of current line
                int?gCode = line.GetIValue('G');

                // Movement
                if (gCode == 0 || gCode == 1)
                {
                    // Keep track of the current Z position
                    double?zPosition = line.GetFValue('Z');
                    if (zPosition.HasValue)
                    {
                        currentZ = zPosition.Value;

                        // Since we have a Z height in this line we don't have to insert an artificial one
                        ensureUnhopAfterToolChange = false;
                    }

                    // Make sure to un-hop before the first extrusion if required
                    if (!double.IsNaN(layer.ZHeight) && line.GetFValue('E').HasValue&& (currentZ != layer.ZHeight || ensureUnhopAfterToolChange))
                    {
                        replacementLines.Add(new GCodeLine($"G1 Z{layer.ZHeight.ToString("F3", FrmMain.numberFormat)} F{(line.Feedrate * 60.0).ToString("F0", FrmMain.numberFormat)}"));
                        currentZ = layer.ZHeight;
                        ensureUnhopAfterToolChange = false;
                    }

                    // Prime tool before first extrusion
                    if (primeTool && line.GetFValue('E').HasValue)
                    {
                        replacementLines.Add(new GCodeLine($"G1 E{toolChangeRetractionDistance.ToString("F2", FrmMain.numberFormat)} F{toolChangeRetractionSpeed.ToString(FrmMain.numberFormat)}", toolChangeRetractionSpeed / 60.0));
                        toolPrimed[currentTool - 1] = true;
                        primeTool = false;
                    }

                    // Add next movement of the segment
                    replacementLines.Add(line);

                    // Insert potential tool changes after first G0/G1 code
                    if (toolNumber != currentTool)
                    {
                        // Reset any speed overrides so tool change is not slowed down
                        if (activeRule != null)
                        {
                            replacementLines.Add(new GCodeLine("M220 S100"));
                            activeRule = null;
                        }

                        AddToolChange(replacementLines, currentTool, toolNumber);
                        currentTool = toolNumber;
                        primeTool   = !toolPrimed[currentTool - 1];

                        // Make sure we go to the height of the current layer after tool change but only before the first extrusion (see above)
                        ensureUnhopAfterToolChange = true;
                    }
                }
                // Always add it if is no movement
                else
                {
                    replacementLines.Add(line);
                }

                // Deal with custom rules
                OverrideRule rule = GetRule(currentTool, layer.Number, segment);
                if (rule != activeRule)
                {
                    ApplyRule(activeRule, replacementLines, rule);
                    activeRule = rule;
                }
            }
            return(segment.LastPosition);
        }
コード例 #6
0
        // 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");
            }
        }
コード例 #7
0
        private void FixToolChangeRetractionAndPriming(ref int iteration)
        {
            // Fix toolchange retraction/priming
            for (int layerNumber = 1; layerNumber < layers.Count; layerNumber++)
            {
                GCodeLayer layer = layers[layerNumber];
                for (int segmentNumber = 0; segmentNumber < layer.Segments.Count; segmentNumber++)
                {
                    GCodeSegment segment = layer.Segments[segmentNumber];
                    for (int lineIndex = 0; lineIndex < segment.Lines.Count; lineIndex++)
                    {
                        GCodeLine line = segment.Lines[lineIndex];
                        // Look for toolchange
                        if (!line.Content.EndsWith(ToolChangeMarker, StringComparison.InvariantCulture))
                        {
                            continue;
                        }

                        // Search for retraction prior to toolchange
                        // It will be located at the end of the previous segment
                        var previousSegment = GetPreviousSegment(layerNumber, segmentNumber);
                        if (previousSegment != null)
                        {
                            var lookbehindLimit = Math.Max(previousSegment.Lines.Count - 5, 0);
                            for (var reverse = previousSegment.Lines.Count - 1; reverse >= lookbehindLimit; reverse--)
                            {
                                if (!previousSegment.Lines[reverse].Content.StartsWith("G1 E-", StringComparison.InvariantCulture))
                                {
                                    continue;
                                }
                                var eVal = previousSegment.Lines[reverse].GetFValue('E');
                                if (Math.Abs(eVal.Value) != toolChangeRetractionDistance)
                                {
                                    previousSegment.Lines.RemoveAt(reverse);
                                    previousSegment.Lines.Insert(reverse, new GCodeLine($"G1 E-{toolChangeRetractionDistance.ToString("F2", FrmMain.numberFormat)} F{toolChangeRetractionSpeed.ToString(FrmMain.numberFormat)}", toolChangeRetractionSpeed / 60.0));
                                }
                                break;
                            }
                        }

                        // Search for priming post toolchange
                        var lookaheadLimit = Math.Min(lineIndex + 5, segment.Lines.Count - 1);
                        for (var forward = lineIndex + 1; forward <= lookaheadLimit; forward++)
                        {
                            if (!segment.Lines[forward].Content.StartsWith("G1 E", StringComparison.InvariantCulture))
                            {
                                continue;
                            }
                            var eVal = segment.Lines[forward].GetFValue('E');
                            if (eVal.Value != toolChangeRetractionDistance)
                            {
                                segment.Lines.RemoveAt(forward);
                                segment.Lines.Insert(forward, new GCodeLine($"G1 E{toolChangeRetractionDistance.ToString("F2", FrmMain.numberFormat)} F{toolChangeRetractionSpeed.ToString(FrmMain.numberFormat)}", toolChangeRetractionSpeed / 60.0));
                            }
                            break;
                        }
                    }
                }
                progress.Report(iteration++);
            }
        }
コード例 #8
0
        public void PostProcess()
        {
            // We know how much we need to do here...
            maxProgress.Report(Math.Max(layers.Count * 4 - 4, 0));

            // Combine tool islands per layer, adjust tool change sequences and take care of rules
            OverrideRule activeRule          = null;
            int          iteration           = 1;
            bool         startWithLowestTool = true;
            int          currentTool         = -1;

            for (int layerIndex = 1; layerIndex < layers.Count; layerIndex++)
            {
                GCodeLayer layer            = layers[layerIndex];
                GCodeLayer replacementLayer = new GCodeLayer(layerIndex, layer.ZHeight);

                if (settings.IslandCombining)
                {
                    if (startWithLowestTool)
                    {
                        for (int toolNumber = 1; toolNumber <= settings.Tools.Length; toolNumber++)
                        {
                            // Go from T1-T5
                            GCodeSegment segment = CombineSegments(layer, toolNumber, ref currentTool, ref activeRule);
                            if (segment != null)
                            {
                                replacementLayer.Segments.Add(segment);
                            }
                        }
                    }
                    else
                    {
                        for (int toolNumber = settings.Tools.Length; toolNumber >= 1; toolNumber--)
                        {
                            // Go from T5-T1
                            GCodeSegment segment = CombineSegments(layer, toolNumber, ref currentTool, ref activeRule);
                            if (segment != null)
                            {
                                replacementLayer.Segments.Add(segment);
                            }
                        }
                    }
                    startWithLowestTool = !startWithLowestTool;
                }
                else
                {
                    double currentZ = 0.0;
                    foreach (GCodeSegment segment in layer.Segments)
                    {
                        int toolNumber = segment.Tool;
                        List <GCodeLine> replacementLines = new List <GCodeLine>();
                        Coordinate       lastPosition     = EnrichSegment(layer, segment, replacementLines, toolNumber, ref currentTool, ref activeRule, ref currentZ);
                        if (replacementLines.Count > 0)
                        {
                            replacementLayer.Segments.Add(
                                new GCodeSegment($"T{toolNumber}", toolNumber, null)
                            {
                                Lines        = replacementLines,
                                LastPosition = lastPosition
                            });
                        }
                    }
                }

                layers[layerIndex] = replacementLayer;
                progress.Report(iteration++);
            }

            // Make sure the last applied rule is reset before the print finishes
            if (activeRule != null)
            {
                GCodeSegment lastSegment = layers.Last((layer) => layer.Segments.Count > 0).Segments.Last();
                if (activeRule.SpeedFactor != 100)
                {
                    lastSegment.Lines.Add(new GCodeLine("M220 S100"));
                }
                if (activeRule.ExtrusionFactor != 100)
                {
                    lastSegment.Lines.Add(new GCodeLine("M221 S100"));
                }
                activeRule = null;
            }

            FixToolChangeRetractionAndPriming(ref iteration);

            InsertPreheatingSequences(ref iteration);
        }