public void CreateFeaturesForLayerIfRequired(int layerToCreate)
        {
            if (extrusionColors == null &&
                gCodeFileToDraw != null &&
                gCodeFileToDraw.LineCount > 0)
            {
                extrusionColors = new ExtrusionColors();
                HashSet <float>           speeds          = new HashSet <float>();
                PrinterMachineInstruction prevInstruction = gCodeFileToDraw.Instruction(0);
                for (int i = 1; i < gCodeFileToDraw.LineCount; i++)
                {
                    PrinterMachineInstruction instruction = gCodeFileToDraw.Instruction(i);
                    if (instruction.EPosition > prevInstruction.EPosition && (instruction.Line.IndexOf('X') != -1 || instruction.Line.IndexOf('Y') != -1))
                    {
                        speeds.Add((float)instruction.FeedRate);
                    }

                    prevInstruction = instruction;
                }

                foreach (float speed in speeds)
                {
                    extrusionColors.GetColorForSpeed(speed);
                }
            }

            if (renderFeatures.Count == 0 ||
                renderFeatures[layerToCreate].Count > 0)
            {
                return;
            }

            List <RenderFeatureBase> renderFeaturesForLayer = renderFeatures[layerToCreate];

            int startRenderIndex = gCodeFileToDraw.GetInstructionIndexAtLayer(layerToCreate);
            int endRenderIndex   = gCodeFileToDraw.LineCount - 1;

            if (layerToCreate < gCodeFileToDraw.NumChangesInZ - 1)
            {
                endRenderIndex = gCodeFileToDraw.GetInstructionIndexAtLayer(layerToCreate + 1);
            }

            for (int instructionIndex = startRenderIndex; instructionIndex < endRenderIndex; instructionIndex++)
            {
                PrinterMachineInstruction currentInstruction  = gCodeFileToDraw.Instruction(instructionIndex);
                PrinterMachineInstruction previousInstruction = currentInstruction;
                if (instructionIndex > 0)
                {
                    previousInstruction = gCodeFileToDraw.Instruction(instructionIndex - 1);
                }

                if (currentInstruction.Position == previousInstruction.Position)
                {
                    if (Math.Abs(currentInstruction.EPosition - previousInstruction.EPosition) > 0)
                    {
                        // this is a retraction
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(currentInstruction.Position, currentInstruction.EPosition - previousInstruction.EPosition, currentInstruction.ExtruderIndex, currentInstruction.FeedRate));
                    }
                    if (currentInstruction.Line.StartsWith("G10"))
                    {
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(currentInstruction.Position, -1, currentInstruction.ExtruderIndex, currentInstruction.FeedRate));
                    }
                    else if (currentInstruction.Line.StartsWith("G11"))
                    {
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(currentInstruction.Position, 1, currentInstruction.ExtruderIndex, currentInstruction.FeedRate));
                    }
                }
                else
                {
                    if (gCodeFileToDraw.IsExtruding(instructionIndex))
                    {
                        double layerThickness = gCodeFileToDraw.GetLayerHeight();
                        if (layerToCreate == 0)
                        {
                            layerThickness = gCodeFileToDraw.GetFirstLayerHeight();
                        }

                        Color extrusionColor = extrusionColors.GetColorForSpeed((float)currentInstruction.FeedRate);
                        renderFeaturesForLayer.Add(new RenderFeatureExtrusion(previousInstruction.Position, currentInstruction.Position, currentInstruction.ExtruderIndex, currentInstruction.FeedRate, currentInstruction.EPosition - previousInstruction.EPosition, gCodeFileToDraw.GetFilamentDiameter(), layerThickness, extrusionColor));
                    }
                    else
                    {
                        renderFeaturesForLayer.Add(new RenderFeatureTravel(previousInstruction.Position, currentInstruction.Position, currentInstruction.ExtruderIndex, currentInstruction.FeedRate));
                    }
                }
            }
        }
        public void CreateFeaturesForLayerIfRequired(int layerToCreate)
        {
            if (renderFeatures.Count == 0 ||
                renderFeatures[layerToCreate].Count > 0)
            {
                return;
            }

            List <RenderFeatureBase> renderFeaturesForLayer = renderFeatures[layerToCreate];

            int startRenderIndex = gCodeFileToDraw.GetFirstLayerInstruction(layerToCreate);
            int endRenderIndex   = gCodeFileToDraw.LineCount - 1;

            if (layerToCreate < gCodeFileToDraw.LayerCount - 1)
            {
                endRenderIndex = gCodeFileToDraw.GetFirstLayerInstruction(layerToCreate + 1);
            }

            for (int instructionIndex = startRenderIndex; instructionIndex < endRenderIndex; instructionIndex++)
            {
                PrinterMachineInstruction currentInstruction  = gCodeFileToDraw.Instruction(instructionIndex);
                PrinterMachineInstruction previousInstruction = currentInstruction;
                if (instructionIndex > 0)
                {
                    previousInstruction = gCodeFileToDraw.Instruction(instructionIndex - 1);
                }

                if (currentInstruction.Position == previousInstruction.Position)
                {
                    if (Math.Abs(currentInstruction.EPosition - previousInstruction.EPosition) > 0)
                    {
                        // this is a retraction
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(currentInstruction.Position, currentInstruction.EPosition - previousInstruction.EPosition, currentInstruction.ExtruderIndex, currentInstruction.FeedRate));
                    }
                    if (currentInstruction.Line.StartsWith("G10"))
                    {
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(currentInstruction.Position, -1, currentInstruction.ExtruderIndex, currentInstruction.FeedRate));
                    }
                    else if (currentInstruction.Line.StartsWith("G11"))
                    {
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(currentInstruction.Position, 1, currentInstruction.ExtruderIndex, currentInstruction.FeedRate));
                    }
                }
                else
                {
                    if (gCodeFileToDraw.IsExtruding(instructionIndex))
                    {
                        double layerThickness = gCodeFileToDraw.GetLayerHeight(layerToCreate);

                        Color extrusionColor = ExtrusionColors.GetColorForSpeed((float)currentInstruction.FeedRate);
                        renderFeaturesForLayer.Add(
                            new RenderFeatureExtrusion(
                                previousInstruction.Position,
                                currentInstruction.Position,
                                currentInstruction.ExtruderIndex,
                                currentInstruction.FeedRate,
                                currentInstruction.EPosition - previousInstruction.EPosition,
                                gCodeFileToDraw.GetFilamentDiameter(),
                                layerThickness,
                                extrusionColor,
                                this.Gray));
                    }
                    else
                    {
                        renderFeaturesForLayer.Add(
                            new RenderFeatureTravel(
                                previousInstruction.Position,
                                currentInstruction.Position,
                                currentInstruction.ExtruderIndex,
                                currentInstruction.FeedRate));
                    }
                }
            }
        }
        public void CreateFeaturesForLayerIfRequired(int layerToCreate)
        {
            if (all.layers.Count == 0 ||
                all.layers[layerToCreate].features.Count > 0)
            {
                return;
            }

            List <RenderFeatureBase> renderFeaturesForLayer = all.layers[layerToCreate].features;

            int startRenderIndex = gCodeFileToDraw.GetFirstLayerInstruction(layerToCreate);
            int endRenderIndex   = gCodeFileToDraw.LineCount - 1;

            if (layerToCreate < gCodeFileToDraw.LayerCount - 1)
            {
                endRenderIndex = gCodeFileToDraw.GetFirstLayerInstruction(layerToCreate + 1);
            }

            for (int instructionIndex = startRenderIndex; instructionIndex < endRenderIndex; instructionIndex++)
            {
                PrinterMachineInstruction currentInstruction  = gCodeFileToDraw.Instruction(instructionIndex);
                PrinterMachineInstruction previousInstruction = currentInstruction;
                if (instructionIndex > 0)
                {
                    previousInstruction = gCodeFileToDraw.Instruction(instructionIndex - 1);
                }

                if (currentInstruction.Position == previousInstruction.Position)
                {
                    double eMovement = 0;
                    if (currentInstruction.PositionSet != PositionSet.E)
                    {
                        eMovement = currentInstruction.EPosition - previousInstruction.EPosition;
                    }

                    if (Math.Abs(eMovement) > 0)
                    {
                        // this is a retraction
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(instructionIndex, currentInstruction.Position, eMovement, currentInstruction.ToolIndex, currentInstruction.FeedRate));
                    }

                    if (currentInstruction.Line.StartsWith("G10"))
                    {
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(instructionIndex, currentInstruction.Position, -1, currentInstruction.ToolIndex, currentInstruction.FeedRate));
                    }
                    else if (currentInstruction.Line.StartsWith("G11"))
                    {
                        renderFeaturesForLayer.Add(new RenderFeatureRetract(instructionIndex, currentInstruction.Position, 1, currentInstruction.ToolIndex, currentInstruction.FeedRate));
                    }
                }
                else
                {
                    var extrusionAmount    = currentInstruction.EPosition - previousInstruction.EPosition;
                    var filamentDiameterMm = gCodeFileToDraw.GetFilamentDiameter();

                    if (gCodeFileToDraw.IsExtruding(instructionIndex))
                    {
                        double layerThickness = gCodeFileToDraw.GetLayerHeight(layerToCreate);

                        Color extrusionColor = ExtrusionColors.GetColorForSpeed((float)currentInstruction.FeedRate);
                        renderFeaturesForLayer.Add(
                            new RenderFeatureExtrusion(
                                instructionIndex,
                                previousInstruction.Position,
                                currentInstruction.Position,
                                currentInstruction.ToolIndex,
                                currentInstruction.FeedRate,
                                extrusionAmount,
                                filamentDiameterMm,
                                layerThickness,
                                extrusionColor,
                                this.Gray));
                    }
                    else
                    {
                        if (extrusionAmount < 0)
                        {
                            double moveLength     = (currentInstruction.Position - previousInstruction.Position).Length;
                            double filamentRadius = filamentDiameterMm / 2;
                            double areaSquareMm   = (filamentRadius * filamentRadius) * Math.PI;

                            var extrusionVolumeMm3 = (float)(areaSquareMm * extrusionAmount);
                            var area = extrusionVolumeMm3 / moveLength;
                        }

                        renderFeaturesForLayer.Add(
                            new RenderFeatureTravel(
                                instructionIndex,
                                previousInstruction.Position,
                                currentInstruction.Position,
                                currentInstruction.ToolIndex,
                                currentInstruction.FeedRate,
                                extrusionAmount < 0));
                    }
                }
            }
        }