Exemplo n.º 1
0
		private 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()]);
		}
Exemplo n.º 2
0
        private void AddSupportToGCode(SliceDataStorage storage, GCodePlanner gcodeLayer, int layerIndex, ConfigSettings config)
        {
            if (!storage.support.generated)
            {
                return;
            }

            if (config.supportExtruder > -1)
            {
                int prevExtruder = gcodeLayer.getExtruder();
                if (gcodeLayer.SetExtruder(config.supportExtruder))
                {
                    addWipeTower(storage, gcodeLayer, layerIndex, prevExtruder, config.extrusionWidth_um);
                }

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

            int currentZHeight_um = config.firstLayerThickness_um;

            if (layerIndex == 0)
            {
                currentZHeight_um /= 2;
            }
            else
            {
                if (layerIndex > 1)
                {
                    currentZHeight_um += (layerIndex - 1) * config.layerThickness_um;
                }
                currentZHeight_um += config.layerThickness_um / 2;
            }

            SupportPolyGenerator supportGenerator = new SupportPolyGenerator(storage.support, currentZHeight_um);

            WriteSupportPolygons(storage, gcodeLayer, layerIndex, config, supportGenerator.supportPolygons, SupportType.General);

            if (config.supportInterfaceExtruder != -1 &&
                config.supportInterfaceExtruder != config.supportExtruder)
            {
                gcodeLayer.SetExtruder(config.supportInterfaceExtruder);
            }
            WriteSupportPolygons(storage, gcodeLayer, layerIndex, config, supportGenerator.interfacePolygons, SupportType.Interface);
        }
Exemplo n.º 3
0
		private void AddSkirtToGCode(SliceDataStorage storage, GCodePlanner gcodeLayer, int volumeIndex, int layerIndex)
		{
			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);
		}
Exemplo n.º 4
0
        private void WriteSupportPolygons(SliceDataStorage storage, GCodePlanner gcodeLayer, int layerIndex, ConfigSettings config, Polygons supportPolygons, SupportType interfaceLayer)
        {
            for (int volumeIndex = 0; volumeIndex < storage.volumes.Count; volumeIndex++)
            {
                SliceLayer layer = storage.volumes[volumeIndex].layers[layerIndex];
                for (int partIndex = 0; partIndex < layer.parts.Count; partIndex++)
                {
                    supportPolygons = supportPolygons.CreateDifference(layer.parts[partIndex].TotalOutline.Offset(config.supportXYDistance_um));
                }
            }

            //Contract and expand the support polygons so small sections are removed and the final polygon is smoothed a bit.
            supportPolygons = supportPolygons.Offset(-config.extrusionWidth_um * 1);
            supportPolygons = supportPolygons.Offset(config.extrusionWidth_um * 1);

            List<Polygons> supportIslands = supportPolygons.CreateLayerOutlines(PolygonsHelper.LayerOpperation.EvenOdd);
            PathOrderOptimizer islandOrderOptimizer = new PathOrderOptimizer(gcode.GetPositionXY());

            for (int islandIndex = 0; islandIndex < supportIslands.Count; islandIndex++)
            {
                islandOrderOptimizer.AddPolygon(supportIslands[islandIndex][0]);
            }
            islandOrderOptimizer.Optimize();

            for (int islandIndex = 0; islandIndex < supportIslands.Count; islandIndex++)
            {
                Polygons island = supportIslands[islandOrderOptimizer.bestPolygonOrderIndex[islandIndex]];
                Polygons supportLines = new Polygons();
                if (config.supportLineSpacing_um > 0)
                {
                    switch (interfaceLayer)
                    {
                        case SupportType.Interface:
                            Infill.GenerateLineInfill(config, island, ref supportLines, config.supportInfillStartingAngle + 90, config.extrusionWidth_um);
                            break;

                        case SupportType.General:
                            switch (config.supportType)
                            {
                                case ConfigConstants.SUPPORT_TYPE.GRID:
                                    Infill.GenerateGridInfill(config, island, ref supportLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
                                    break;

                                case ConfigConstants.SUPPORT_TYPE.LINES:
                                    Infill.GenerateLineInfill(config, island, ref supportLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
                                    break;
                            }
                            break;

                        default:
                            throw new NotImplementedException();
                    }
                }

                if (config.avoidCrossingPerimeters)
                {
                    gcodeLayer.SetOuterPerimetersToAvoidCrossing(island);
                }

                switch (interfaceLayer)
                {
                    case SupportType.Interface:
                        gcodeLayer.WritePolygonsByOptimizer(supportLines, supportInterfaceConfig);
                        break;

                    case SupportType.General:
                        if (config.supportType == ConfigConstants.SUPPORT_TYPE.GRID)
                        {
                            gcodeLayer.WritePolygonsByOptimizer(island, supportNormalConfig);
                        }
                        gcodeLayer.WritePolygonsByOptimizer(supportLines, supportNormalConfig);
                        break;

                    default:
                        throw new NotImplementedException();
                }

                gcodeLayer.SetOuterPerimetersToAvoidCrossing(null);
            }
        }
Exemplo n.º 5
0
        private 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()]);
        }
Exemplo n.º 6
0
        //Add a single layer from a single mesh-volume to the GCode
        private void AddVolumeLayerToGCode(SliceDataStorage storage, GCodePlanner gcodeLayer, int volumeIndex, int layerIndex, int extrusionWidth_um, int fanSpeedPercent)
        {
            int prevExtruder = gcodeLayer.getExtruder();
            bool extruderChanged = gcodeLayer.SetExtruder(volumeIndex);

            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++)
            {
                if (config.continuousSpiralOuterPerimeter && partIndex > 0)
                {
                    continue;
                }

                partOrderOptimizer.AddPolygon(layer.parts[partIndex].Insets[0][0]);
            }
            partOrderOptimizer.Optimize();

            for (int partIndex = 0; partIndex < partOrderOptimizer.bestPolygonOrderIndex.Count; partIndex++)
            {
                if (config.continuousSpiralOuterPerimeter && partIndex > 0)
                {
                    continue;
                }

                SliceLayerPart part = layer.parts[partOrderOptimizer.bestPolygonOrderIndex[partIndex]];

                if (config.avoidCrossingPerimeters)
                {
                    gcodeLayer.SetOuterPerimetersToAvoidCrossing(part.AvoidCrossingBoundery);
                }
                else
                {
                    gcodeLayer.SetAlwaysRetract(true);
                }

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

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

                // Write the bridge 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 (partIndex != lastPartIndex)
                    {
                        // force a retract if changing islands
                        gcodeLayer.ForceRetract();
                        lastPartIndex = partIndex;
                    }

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

                    // 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 || inset0Config.spiralize)
                    {
                        // First the outside (this helps with accuracy)
                        if (part.Insets.Count > 0)
                        {
                            gcodeLayer.WritePolygonsByOptimizer(part.Insets[0], inset0Config);
                        }

                        if (!inset0Config.spiralize)
                        {
                            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);
        }
Exemplo n.º 7
0
        private void AddSupportToGCode(SliceDataStorage storage, GCodePlanner gcodeLayer, int layerIndex, ConfigSettings config)
        {
            if (!storage.support.generated)
            {
                return;
            }

            if (config.supportExtruder > -1)
            {
                int prevExtruder = gcodeLayer.getExtruder();
                if (gcodeLayer.SetExtruder(config.supportExtruder))
                {
                    addWipeTower(storage, gcodeLayer, layerIndex, prevExtruder, config.extrusionWidth_um);
                }

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

            int currentZHeight_um = config.firstLayerThickness_um;
            if (layerIndex == 0)
            {
                currentZHeight_um /= 2;
            }
            else
            {
                if (layerIndex > 1)
                {
                    currentZHeight_um += (layerIndex - 1) * config.layerThickness_um;
                }
                currentZHeight_um += config.layerThickness_um / 2;
            }

            SupportPolyGenerator supportGenerator = new SupportPolyGenerator(storage.support, currentZHeight_um);

            WriteSupportPolygons(storage, gcodeLayer, layerIndex, config, supportGenerator.supportPolygons, SupportType.General);

            if (config.supportInterfaceExtruder != -1
                && config.supportInterfaceExtruder != config.supportExtruder)
            {
                gcodeLayer.SetExtruder(config.supportInterfaceExtruder);
            }
            WriteSupportPolygons(storage, gcodeLayer, layerIndex, config, supportGenerator.interfacePolygons, SupportType.Interface);
        }
Exemplo n.º 8
0
        private void AddSkirtToGCode(SliceDataStorage storage, GCodePlanner gcodeLayer, int volumeIndex, int layerIndex)
        {
            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);
        }
Exemplo n.º 9
0
		private void WriteSupportPolygons(SliceDataStorage storage, GCodePlanner gcodeLayer, int layerIndex, ConfigSettings config, Polygons supportPolygons, SupportType interfaceLayer)
		{
			for (int volumeIndex = 0; volumeIndex < storage.volumes.Count; volumeIndex++)
			{
				SliceLayer layer = storage.volumes[volumeIndex].layers[layerIndex];
				for (int partIndex = 0; partIndex < layer.parts.Count; partIndex++)
				{
					supportPolygons = supportPolygons.CreateDifference(layer.parts[partIndex].TotalOutline.Offset(config.supportXYDistance_um));
				}
			}

			//Contract and expand the support polygons so small sections are removed and the final polygon is smoothed a bit.
			supportPolygons = supportPolygons.Offset(-config.extrusionWidth_um * 1);
			supportPolygons = supportPolygons.Offset(config.extrusionWidth_um * 1);

			List<Polygons> supportIslands = supportPolygons.CreateLayerOutlines(PolygonsHelper.LayerOpperation.EvenOdd);
			PathOrderOptimizer islandOrderOptimizer = new PathOrderOptimizer(gcode.GetPositionXY());

			for (int islandIndex = 0; islandIndex < supportIslands.Count; islandIndex++)
			{
				islandOrderOptimizer.AddPolygon(supportIslands[islandIndex][0]);
			}
			islandOrderOptimizer.Optimize();

			for (int islandIndex = 0; islandIndex < supportIslands.Count; islandIndex++)
			{
				Polygons island = supportIslands[islandOrderOptimizer.bestPolygonOrderIndex[islandIndex]];
				Polygons supportLines = new Polygons();
				if (config.supportLineSpacing_um > 0)
				{
					switch (interfaceLayer)
					{
						case SupportType.Interface:
							Infill.GenerateLineInfill(config, island, ref supportLines, config.supportInfillStartingAngle + 90, config.extrusionWidth_um);
							break;

						case SupportType.General:
							switch (config.supportType)
							{
								case ConfigConstants.SUPPORT_TYPE.GRID:
									Infill.GenerateGridInfill(config, island, ref supportLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
									break;

								case ConfigConstants.SUPPORT_TYPE.LINES:
									Infill.GenerateLineInfill(config, island, ref supportLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
									break;
							}
							break;

						default:
							throw new NotImplementedException();
					}
				}

				if (config.avoidCrossingPerimeters)
				{
					gcodeLayer.SetOuterPerimetersToAvoidCrossing(island);
				}

				switch (interfaceLayer)
				{
					case SupportType.Interface:
						gcodeLayer.WritePolygonsByOptimizer(supportLines, supportInterfaceConfig);
						break;

					case SupportType.General:
						if (config.supportType == ConfigConstants.SUPPORT_TYPE.GRID)
						{
							gcodeLayer.WritePolygonsByOptimizer(island, supportNormalConfig);
						}
						gcodeLayer.WritePolygonsByOptimizer(supportLines, supportNormalConfig);
						break;

					default:
						throw new NotImplementedException();
				}

				gcodeLayer.SetOuterPerimetersToAvoidCrossing(null);
			}
		}
Exemplo n.º 10
0
		//Add a single layer from a single mesh-volume to the GCode
		private void AddVolumeLayerToGCode(SliceDataStorage storage, GCodePlanner gcodeLayer, int volumeIndex, int layerIndex, int extrusionWidth_um, int fanSpeedPercent)
		{
			int prevExtruder = gcodeLayer.getExtruder();
			bool extruderChanged = gcodeLayer.SetExtruder(volumeIndex);

			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++)
			{
				if (config.continuousSpiralOuterPerimeter && partIndex > 0)
				{
					continue;
				}

				partOrderOptimizer.AddPolygon(layer.parts[partIndex].Insets[0][0]);
			}
			partOrderOptimizer.Optimize();

			for (int partIndex = 0; partIndex < partOrderOptimizer.bestPolygonOrderIndex.Count; partIndex++)
			{
				if (config.continuousSpiralOuterPerimeter && partIndex > 0)
				{
					continue;
				}

				SliceLayerPart part = layer.parts[partOrderOptimizer.bestPolygonOrderIndex[partIndex]];

				if (config.avoidCrossingPerimeters)
				{
					gcodeLayer.SetOuterPerimetersToAvoidCrossing(part.AvoidCrossingBoundery);
				}
				else
				{
					gcodeLayer.SetAlwaysRetract(true);
				}

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

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

				// Write the bridge 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 (partIndex != lastPartIndex)
					{
						// force a retract if changing islands
						gcodeLayer.ForceRetract();
						lastPartIndex = partIndex;
					}

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

					// 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 || inset0Config.spiralize)
					{
						// First the outside (this helps with accuracy)
						if (part.Insets.Count > 0)
						{
							gcodeLayer.WritePolygonsByOptimizer(part.Insets[0], inset0Config);
						}

						if (!inset0Config.spiralize)
						{
							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);
		}
Exemplo n.º 11
0
        public static void GenerateRaftGCodeIfRequired(SliceDataStorage storage, ConfigSettings config, GCodeExport gcode)
        {
            if (ShouldGenerateRaft(config))
            {
                GCodePathConfig raftBaseConfig = new GCodePathConfig(config.firstLayerSpeed, config.raftBaseExtrusionWidth_um, "SUPPORT");
                GCodePathConfig raftMiddleConfig = new GCodePathConfig(config.raftPrintSpeed, config.raftInterfaceExtrusionWidth_um, "SUPPORT");
                GCodePathConfig raftSurfaceConfig = new GCodePathConfig((config.raftSurfacePrintSpeed > 0) ? config.raftSurfacePrintSpeed : config.raftPrintSpeed, config.raftSurfaceExtrusionWidth_um, "SUPPORT");

                // create the raft base
                {
                    gcode.WriteComment("LAYER:-3");
                    gcode.WriteComment("RAFT BASE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.travelSpeed, config.minimumTravelToCauseRetraction_um);
                    if (config.raftExtruder >= 0)
                    {
                        // if we have a specified raft extruder use it
                        gcodeLayer.SetExtruder(config.raftExtruder);
                    }
                    else if (config.supportExtruder >= 0)
                    {
                        // else preserve the old behavior of using the support extruder if set.
                        gcodeLayer.SetExtruder(config.supportExtruder);
                    }

                    gcode.setZ(config.raftBaseThickness_um);
                    gcode.SetExtrusion(config.raftBaseThickness_um, config.filamentDiameter_um, config.extrusionMultiplier);

                    Polygons raftLines = new Polygons();
                    Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftBaseLineSpacing_um, config.infillExtendIntoPerimeter_um, 0);

                    // write the skirt around the raft
                    gcodeLayer.WritePolygonsByOptimizer(storage.skirt, raftBaseConfig);

                    // write the outline of the raft
                    gcodeLayer.WritePolygonsByOptimizer(storage.raftOutline, raftBaseConfig);

                    // write the inside of the raft base
                    gcodeLayer.WritePolygonsByOptimizer(raftLines, raftBaseConfig);

                    gcodeLayer.WriteGCode(false, config.raftBaseThickness_um);
                }

                if (config.raftFanSpeedPercent > 0)
                {
                    gcode.WriteFanCommand(config.raftFanSpeedPercent);
                }

                // raft middle layers
                {
                    gcode.WriteComment("LAYER:-2");
                    gcode.WriteComment("RAFT MIDDLE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.travelSpeed, config.minimumTravelToCauseRetraction_um);
                    gcode.setZ(config.raftBaseThickness_um + config.raftInterfaceThicknes_um);
                    gcode.SetExtrusion(config.raftInterfaceThicknes_um, config.filamentDiameter_um, config.extrusionMultiplier);

                    Polygons raftLines = new Polygons();
                    Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftInterfaceLineSpacing_um, config.infillExtendIntoPerimeter_um, 45);
                    gcodeLayer.WritePolygonsByOptimizer(raftLines, raftMiddleConfig);

                    gcodeLayer.WriteGCode(false, config.raftInterfaceThicknes_um);
                }

                for (int raftSurfaceIndex = 1; raftSurfaceIndex <= config.raftSurfaceLayers; raftSurfaceIndex++)
                {
                    gcode.WriteComment("LAYER:-1");
                    gcode.WriteComment("RAFT SURFACE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.travelSpeed, config.minimumTravelToCauseRetraction_um);
                    gcode.setZ(config.raftBaseThickness_um + config.raftInterfaceThicknes_um + config.raftSurfaceThickness_um * raftSurfaceIndex);
                    gcode.SetExtrusion(config.raftSurfaceThickness_um, config.filamentDiameter_um, config.extrusionMultiplier);

                    Polygons raftLines = new Polygons();
                    if (raftSurfaceIndex == config.raftSurfaceLayers)
                    {
                        // make sure the top layer of the raft is 90 degrees offset to the first layer of the part so that it has minimum contact points.
                        Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftSurfaceLineSpacing_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle + 90);
                    }
                    else
                    {
                        Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftSurfaceLineSpacing_um, config.infillExtendIntoPerimeter_um, 90 * raftSurfaceIndex);
                    }
                    gcodeLayer.WritePolygonsByOptimizer(raftLines, raftSurfaceConfig);

                    gcodeLayer.WriteGCode(false, config.raftInterfaceThicknes_um);
                }
            }
        }
Exemplo n.º 12
0
        public static void GenerateRaftGCodeIfRequired(SliceDataStorage storage, ConfigSettings config, GCodeExport gcode)
        {
            if (ShouldGenerateRaft(config))
            {
                GCodePathConfig raftBaseConfig    = new GCodePathConfig(config.firstLayerSpeed, config.raftBaseExtrusionWidth_um, "SUPPORT");
                GCodePathConfig raftMiddleConfig  = new GCodePathConfig(config.raftPrintSpeed, config.raftInterfaceExtrusionWidth_um, "SUPPORT");
                GCodePathConfig raftSurfaceConfig = new GCodePathConfig((config.raftSurfacePrintSpeed > 0) ? config.raftSurfacePrintSpeed : config.raftPrintSpeed, config.raftSurfaceExtrusionWidth_um, "SUPPORT");

                // create the raft base
                {
                    gcode.WriteComment("LAYER:-3");
                    gcode.WriteComment("RAFT BASE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.travelSpeed, config.minimumTravelToCauseRetraction_um);
                    if (config.raftExtruder >= 0)
                    {
                        // if we have a specified raft extruder use it
                        gcodeLayer.SetExtruder(config.raftExtruder);
                    }
                    else if (config.supportExtruder >= 0)
                    {
                        // else preserve the old behavior of using the support extruder if set.
                        gcodeLayer.SetExtruder(config.supportExtruder);
                    }

                    gcode.setZ(config.raftBaseThickness_um);
                    gcode.SetExtrusion(config.raftBaseThickness_um, config.filamentDiameter_um, config.extrusionMultiplier);

                    Polygons raftLines = new Polygons();
                    Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftBaseLineSpacing_um, config.infillExtendIntoPerimeter_um, 0);

                    // write the skirt around the raft
                    gcodeLayer.WritePolygonsByOptimizer(storage.skirt, raftBaseConfig);

                    // write the outline of the raft
                    gcodeLayer.WritePolygonsByOptimizer(storage.raftOutline, raftBaseConfig);

                    // write the inside of the raft base
                    gcodeLayer.WritePolygonsByOptimizer(raftLines, raftBaseConfig);

                    gcodeLayer.WriteGCode(false, config.raftBaseThickness_um);
                }

                if (config.raftFanSpeedPercent > 0)
                {
                    gcode.WriteFanCommand(config.raftFanSpeedPercent);
                }

                // raft middle layers
                {
                    gcode.WriteComment("LAYER:-2");
                    gcode.WriteComment("RAFT MIDDLE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.travelSpeed, config.minimumTravelToCauseRetraction_um);
                    gcode.setZ(config.raftBaseThickness_um + config.raftInterfaceThicknes_um);
                    gcode.SetExtrusion(config.raftInterfaceThicknes_um, config.filamentDiameter_um, config.extrusionMultiplier);

                    Polygons raftLines = new Polygons();
                    Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftInterfaceLineSpacing_um, config.infillExtendIntoPerimeter_um, 45);
                    gcodeLayer.WritePolygonsByOptimizer(raftLines, raftMiddleConfig);

                    gcodeLayer.WriteGCode(false, config.raftInterfaceThicknes_um);
                }

                for (int raftSurfaceIndex = 1; raftSurfaceIndex <= config.raftSurfaceLayers; raftSurfaceIndex++)
                {
                    gcode.WriteComment("LAYER:-1");
                    gcode.WriteComment("RAFT SURFACE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.travelSpeed, config.minimumTravelToCauseRetraction_um);
                    gcode.setZ(config.raftBaseThickness_um + config.raftInterfaceThicknes_um + config.raftSurfaceThickness_um * raftSurfaceIndex);
                    gcode.SetExtrusion(config.raftSurfaceThickness_um, config.filamentDiameter_um, config.extrusionMultiplier);

                    Polygons raftLines = new Polygons();
                    if (raftSurfaceIndex == config.raftSurfaceLayers)
                    {
                        // make sure the top layer of the raft is 90 degrees offset to the first layer of the part so that it has minimum contact points.
                        Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftSurfaceLineSpacing_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle + 90);
                    }
                    else
                    {
                        Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftSurfaceLineSpacing_um, config.infillExtendIntoPerimeter_um, 90 * raftSurfaceIndex);
                    }
                    gcodeLayer.WritePolygonsByOptimizer(raftLines, raftSurfaceConfig);

                    gcodeLayer.WriteGCode(false, config.raftInterfaceThicknes_um);
                }
            }
        }