예제 #1
0
        void addWipeTower(SliceDataStorage storage, GCodePlanner gcodeLayer, int layerNr, int prevExtruder, int extrusionWidth_um)
        {
            if (config.wipeTowerSize_um < 1)
            {
                return;
            }

            //If we changed extruder, print the wipe/prime tower for this nozzle;
            gcodeLayer.writePolygonsByOptimizer(storage.wipeTower, supportInterfaceConfig);
            Polygons fillPolygons = new Polygons();

            Infill.GenerateLinePaths(storage.wipeTower, ref fillPolygons, extrusionWidth_um, config.infillExtendIntoPerimeter_um, 45 + 90 * (layerNr % 2));
            gcodeLayer.writePolygonsByOptimizer(fillPolygons, supportInterfaceConfig);

            //Make sure we wipe the old extruder on the wipe tower.
            gcodeLayer.writeTravel(storage.wipePoint - config.extruderOffsets[prevExtruder] + config.extruderOffsets[gcodeLayer.getExtruder()]);
        }
예제 #2
0
        //Add a single layer from a single mesh-volume to the GCode
        void AddVolumeLayerToGCode(SliceDataStorage storage, GCodePlanner gcodeLayer, int volumeIndex, int layerIndex, int extrusionWidth_um, int fanSpeedPercent)
        {
            int  prevExtruder    = gcodeLayer.getExtruder();
            bool extruderChanged = gcodeLayer.setExtruder(volumeIndex);

            if (layerIndex == 0 && volumeIndex == 0 && !Raft.ShouldGenerateRaft(config))
            {
                if (storage.skirt.Count > 0 &&
                    storage.skirt[0].Count > 0)
                {
                    IntPoint lowestPoint = storage.skirt[0][0];

                    // lets make sure we start with the most outside loop
                    foreach (Polygon polygon in storage.skirt)
                    {
                        foreach (IntPoint position in polygon)
                        {
                            if (position.Y < lowestPoint.Y)
                            {
                                lowestPoint = polygon[0];
                            }
                        }
                    }

                    gcodeLayer.writeTravel(lowestPoint);
                }

                gcodeLayer.writePolygonsByOptimizer(storage.skirt, skirtConfig);
            }

            SliceLayer layer = storage.volumes[volumeIndex].layers[layerIndex];

            if (extruderChanged)
            {
                addWipeTower(storage, gcodeLayer, layerIndex, prevExtruder, extrusionWidth_um);
            }

            if (storage.wipeShield.Count > 0 && storage.volumes.Count > 1)
            {
                gcodeLayer.setAlwaysRetract(true);
                gcodeLayer.writePolygonsByOptimizer(storage.wipeShield[layerIndex], skirtConfig);
                gcodeLayer.setAlwaysRetract(!config.avoidCrossingPerimeters);
            }

            PathOrderOptimizer partOrderOptimizer = new PathOrderOptimizer(new IntPoint());

            for (int partIndex = 0; partIndex < layer.parts.Count; partIndex++)
            {
                partOrderOptimizer.AddPolygon(layer.parts[partIndex].insets[0][0]);
            }
            partOrderOptimizer.Optimize();

            for (int partCounter = 0; partCounter < partOrderOptimizer.bestPolygonOrderIndex.Count; partCounter++)
            {
                SliceLayerPart part = layer.parts[partOrderOptimizer.bestPolygonOrderIndex[partCounter]];

                if (config.avoidCrossingPerimeters)
                {
                    gcodeLayer.SetOuterPerimetersToAvoidCrossing(part.combBoundery);
                }
                else
                {
                    gcodeLayer.setAlwaysRetract(true);
                }

                Polygons fillPolygons   = new Polygons();
                Polygons bridgePolygons = new Polygons();

                CalculateInfillData(storage, volumeIndex, layerIndex, extrusionWidth_um, part, ref fillPolygons, ref bridgePolygons);

                // Write the bidge polgons out first so the perimeter will have more to hold to while bridging the gaps.
                // It would be even better to slow down the perimeters that are part of bridges but that is a bit harder.
                if (bridgePolygons.Count > 0)
                {
                    gcode.writeFanCommand(config.bridgeFanSpeedPercent);
                    gcodeLayer.writePolygonsByOptimizer(bridgePolygons, bridgConfig);
                    gcode.writeFanCommand(fanSpeedPercent);
                }

                if (config.numberOfPerimeters > 0)
                {
                    if (partCounter > 0)
                    {
                        gcodeLayer.forceRetract();
                    }

                    if (config.continuousSpiralOuterPerimeter)
                    {
                        if (layerIndex >= config.numberOfBottomLayers)
                        {
                            inset0Config.spiralize = true;
                        }

                        if (layerIndex == config.numberOfBottomLayers && part.insets.Count > 0)
                        {
                            gcodeLayer.writePolygonsByOptimizer(part.insets[0], insetXConfig);
                        }
                    }

                    // If we are on the very first layer we start with the outside in so that we can stick to the bed better.
                    if (config.outsidePerimetersFirst || layerIndex == 0)
                    {
                        // First the outside (this helps with accuracy)
                        if (part.insets.Count > 0)
                        {
                            gcodeLayer.writePolygonsByOptimizer(part.insets[0], inset0Config);
                        }
                        for (int perimeterIndex = 1; perimeterIndex < part.insets.Count; perimeterIndex++)
                        {
                            gcodeLayer.writePolygonsByOptimizer(part.insets[perimeterIndex], insetXConfig);
                        }
                    }
                    else                     // This is so we can do overhanges better (the outside can stick a bit to the inside).
                    {
                        // Print everything but the first perimeter from the outside in so the little parts have more to stick to.
                        for (int perimeterIndex = 1; perimeterIndex < part.insets.Count; perimeterIndex++)
                        {
                            gcodeLayer.writePolygonsByOptimizer(part.insets[perimeterIndex], insetXConfig);
                        }
                        // then 0
                        if (part.insets.Count > 0)
                        {
                            gcodeLayer.writePolygonsByOptimizer(part.insets[0], inset0Config);
                        }
                    }
                }

                gcodeLayer.writePolygonsByOptimizer(fillPolygons, fillConfig);

                //After a layer part, make sure the nozzle is inside the comb boundary, so we do not retract on the perimeter.
                if (!config.continuousSpiralOuterPerimeter || layerIndex < config.numberOfBottomLayers)
                {
                    gcodeLayer.MoveInsideTheOuterPerimeter(extrusionWidth_um * 2);
                }
            }
            gcodeLayer.SetOuterPerimetersToAvoidCrossing(null);
        }