public void writeGCode(bool liftHeadIfNeeded, int layerThickness) { GCodePathConfig lastConfig = null; int extruderIndex = gcode.getExtruderIndex(); for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++) { GCodePath path = paths[pathIndex]; if (extruderIndex != path.extruderIndex) { extruderIndex = path.extruderIndex; gcode.switchExtruder(extruderIndex); } else if (path.Retract) { gcode.writeRetraction(); } if (path.config != travelConfig && lastConfig != path.config) { gcode.writeComment("TYPE:{0}".FormatWith(path.config.name)); lastConfig = path.config; } int speed = path.config.speed; if (path.config.lineWidth != 0) { // Only apply the extrudeSpeedFactor to extrusion moves speed = speed * extrudeSpeedFactor / 100; } else { speed = speed * travelSpeedFactor / 100; } if (path.points.Count == 1 && path.config != travelConfig && (gcode.getPositionXY() - path.points[0]).ShorterThen(path.config.lineWidth * 2)) { //Check for lots of small moves and combine them into one large line IntPoint nextPosition = path.points[0]; int i = pathIndex + 1; while (i < paths.Count && paths[i].points.Count == 1 && (nextPosition - paths[i].points[0]).ShorterThen(path.config.lineWidth * 2)) { nextPosition = paths[i].points[0]; i++; } if (paths[i - 1].config == travelConfig) { i--; } if (i > pathIndex + 2) { nextPosition = gcode.getPositionXY(); for (int x = pathIndex; x < i - 1; x += 2) { long oldLen = (nextPosition - paths[x].points[0]).vSize(); IntPoint newPoint = (paths[x].points[0] + paths[x + 1].points[0]) / 2; long newLen = (gcode.getPositionXY() - newPoint).vSize(); if (newLen > 0) { gcode.writeMove(newPoint, speed, (int)(path.config.lineWidth * oldLen / newLen)); } nextPosition = paths[x + 1].points[0]; } gcode.writeMove(paths[i - 1].points[0], speed, path.config.lineWidth); pathIndex = i - 1; continue; } } bool spiralize = path.config.spiralize; if (spiralize) { //Check if we are the last spiralize path in the list, if not, do not spiralize. for (int m = pathIndex + 1; m < paths.Count; m++) { if (paths[m].config.spiralize) { spiralize = false; } } } if (spiralize) { //If we need to spiralize then raise the head slowly by 1 layer as this path progresses. double totalLength = 0; int z = gcode.getPositionZ(); IntPoint currentPosition = gcode.getPositionXY(); for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++) { IntPoint nextPosition = path.points[pointIndex]; totalLength += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; } double length = 0.0; currentPosition = gcode.getPositionXY(); for (int i = 0; i < path.points.Count; i++) { IntPoint nextPosition = path.points[i]; length += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; gcode.setZ((int)(z + layerThickness * length / totalLength + .5)); gcode.writeMove(path.points[i], speed, path.config.lineWidth); } } else { for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++) { gcode.writeMove(path.points[pointIndex], speed, path.config.lineWidth); } } } gcode.updateTotalPrintTime(); if (liftHeadIfNeeded && extraTime > 0.0) { gcode.writeComment("Small layer, adding delay of {0}".FormatWith(extraTime)); gcode.writeRetraction(); gcode.setZ(gcode.getPositionZ() + 3000); gcode.writeMove(gcode.getPositionXY(), travelConfig.speed, 0); gcode.writeMove(gcode.getPositionXY() - new IntPoint(-20000, 0), travelConfig.speed, 0); gcode.writeDelay(extraTime); } }
private void writeGCode(SliceDataStorage storage) { gcode.WriteComment("filamentDiameter = {0}".FormatWith(config.filamentDiameter)); gcode.WriteComment("extrusionWidth = {0}".FormatWith(config.extrusionWidth)); gcode.WriteComment("firstLayerExtrusionWidth = {0}".FormatWith(config.firstLayerExtrusionWidth)); gcode.WriteComment("layerThickness = {0}".FormatWith(config.layerThickness)); gcode.WriteComment("firstLayerThickness = {0}".FormatWith(config.firstLayerThickness)); if (fileNumber == 1) { if (gcode.GetOutputType() == ConfigConstants.OUTPUT_TYPE.ULTIGCODE) { gcode.WriteComment("TYPE:UltiGCode"); gcode.WriteComment("TIME:<__TIME__>"); gcode.WriteComment("MATERIAL:<FILAMENT>"); gcode.WriteComment("MATERIAL2:<FILAMEN2>"); } gcode.WriteCode(config.startCode); if (gcode.GetOutputType() == ConfigConstants.OUTPUT_TYPE.BFB) { gcode.WriteComment("enable auto-retraction"); gcode.WriteLine("M227 S{0} P{1}".FormatWith(config.retractionOnTravel * 2560, config.retractionOnTravel * 2560)); } } else { gcode.WriteFanCommand(0); gcode.ResetExtrusionValue(); gcode.WriteRetraction(); gcode.setZ(maxObjectHeight + 5000); gcode.WriteMove(gcode.GetPositionXY(), config.travelSpeed, 0); gcode.WriteMove(new IntPoint(storage.modelMin.x, storage.modelMin.y), config.travelSpeed, 0); } fileNumber++; int totalLayers = storage.volumes[0].layers.Count; // let's remove any of the layers on top that are empty { for (int layerIndex = totalLayers - 1; layerIndex >= 0; layerIndex--) { bool layerHasData = false; foreach (SliceVolumeStorage currentVolume in storage.volumes) { SliceLayer currentLayer = currentVolume.layers[layerIndex]; for (int partIndex = 0; partIndex < currentVolume.layers[layerIndex].parts.Count; partIndex++) { SliceLayerPart currentPart = currentLayer.parts[partIndex]; if (currentPart.TotalOutline.Count > 0) { layerHasData = true; break; } } } if (layerHasData) { break; } totalLayers--; } } gcode.WriteComment("Layer count: {0}".FormatWith(totalLayers)); // keep the raft generation code inside of raft Raft.GenerateRaftGCodeIfRequired(storage, config, gcode); int volumeIndex = 0; for (int layerIndex = 0; layerIndex < totalLayers; layerIndex++) { if (MatterSlice.Canceled) { return; } LogOutput.Log("Writing Layers {0}/{1}\n".FormatWith(layerIndex + 1, totalLayers)); LogOutput.logProgress("export", layerIndex + 1, totalLayers); int extrusionWidth_um = config.extrusionWidth_um; if (layerIndex == 0) { extrusionWidth_um = config.firstLayerExtrusionWidth_um; } if (layerIndex == 0) { skirtConfig.setData(config.firstLayerSpeed, extrusionWidth_um, "SKIRT"); inset0Config.setData(config.firstLayerSpeed, extrusionWidth_um, "WALL-OUTER"); insetXConfig.setData(config.firstLayerSpeed, extrusionWidth_um, "WALL-INNER"); fillConfig.setData(config.firstLayerSpeed, extrusionWidth_um, "FILL", false); bridgConfig.setData(config.firstLayerSpeed, extrusionWidth_um, "BRIDGE"); supportNormalConfig.setData(config.firstLayerSpeed, config.supportExtrusionWidth_um, "SUPPORT"); supportInterfaceConfig.setData(config.firstLayerSpeed, config.extrusionWidth_um, "SUPPORT-INTERFACE"); } else { skirtConfig.setData(config.insidePerimetersSpeed, extrusionWidth_um, "SKIRT"); inset0Config.setData(config.outsidePerimeterSpeed, extrusionWidth_um, "WALL-OUTER"); insetXConfig.setData(config.insidePerimetersSpeed, extrusionWidth_um, "WALL-INNER"); fillConfig.setData(config.infillSpeed, extrusionWidth_um, "FILL", false); bridgConfig.setData(config.bridgeSpeed, extrusionWidth_um, "BRIDGE"); supportNormalConfig.setData(config.supportMaterialSpeed, config.supportExtrusionWidth_um, "SUPPORT"); supportInterfaceConfig.setData(config.supportMaterialSpeed, config.extrusionWidth_um, "SUPPORT-INTERFACE"); } gcode.WriteComment("LAYER:{0}".FormatWith(layerIndex)); if (layerIndex == 0) { gcode.SetExtrusion(config.firstLayerThickness_um, config.filamentDiameter_um, config.extrusionMultiplier); } else { gcode.SetExtrusion(config.layerThickness_um, config.filamentDiameter_um, config.extrusionMultiplier); } GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.travelSpeed, config.minimumTravelToCauseRetraction_um); // get the correct height for this layer int z = config.firstLayerThickness_um + layerIndex * config.layerThickness_um; if (config.enableRaft) { z += config.raftBaseThickness_um + config.raftInterfaceThicknes_um + config.raftSurfaceLayers * config.raftSurfaceThickness_um; if (layerIndex == 0) { // We only raise the first layer of the print up by the air gap. // To give it: // Less press into the raft // More time to cool // more surface area to air while extruding z += config.raftAirGap_um; } } gcode.setZ(z); // We only create the skirt if we are on layer 0 and the first volume and there is no raft. if (layerIndex == 0 && volumeIndex == 0 && !Raft.ShouldGenerateRaft(config)) { AddSkirtToGCode(storage, gcodeLayer, volumeIndex, layerIndex); } bool printSupportFirst = (storage.support.generated && config.supportExtruder >= 0 && config.supportExtruder == gcodeLayer.getExtruder()); if (printSupportFirst) { AddSupportToGCode(storage, gcodeLayer, layerIndex, config); } int fanSpeedPercent = GetFanSpeed(layerIndex, gcodeLayer); for (int volumeCnt = 0; volumeCnt < storage.volumes.Count; volumeCnt++) { if (volumeCnt > 0) { volumeIndex = (volumeIndex + 1) % storage.volumes.Count; } AddVolumeLayerToGCode(storage, gcodeLayer, volumeIndex, layerIndex, extrusionWidth_um, fanSpeedPercent); } if (!printSupportFirst) { AddSupportToGCode(storage, gcodeLayer, layerIndex, config); } //Finish the layer by applying speed corrections for minimum layer times. gcodeLayer.ForceMinimumLayerTime(config.minimumLayerTimeSeconds, config.minimumPrintingSpeed); gcode.WriteFanCommand(fanSpeedPercent); int currentLayerThickness_um = config.layerThickness_um; if (layerIndex <= 0) { currentLayerThickness_um = config.firstLayerThickness_um; } gcodeLayer.WriteGCode(config.doCoolHeadLift, currentLayerThickness_um); } LogOutput.Log("Wrote layers in {0:0.00}s.\n".FormatWith(timeKeeper.Elapsed.Seconds)); timeKeeper.Restart(); gcode.TellFileSize(); gcode.WriteFanCommand(0); //Store the object height for when we are printing multiple objects, as we need to clear every one of them when moving to the next position. maxObjectHeight = Math.Max(maxObjectHeight, storage.modelSize.z); }
public void WriteRaftGCodeIfRequired(ConfigSettings config, GCodeExport gcode) { LayerDataStorage storage = this; if (config.ShouldGenerateRaft()) { 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.QueuePolygonsByOptimizer(storage.skirt, raftBaseConfig); // write the outline of the raft gcodeLayer.QueuePolygonsByOptimizer(storage.raftOutline, raftBaseConfig); // write the inside of the raft base gcodeLayer.QueuePolygonsByOptimizer(raftLines, raftBaseConfig); gcodeLayer.WriteQueuedGCode(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.QueuePolygonsByOptimizer(raftLines, raftMiddleConfig); gcodeLayer.WriteQueuedGCode(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.QueuePolygonsByOptimizer(raftLines, raftSurfaceConfig); gcodeLayer.WriteQueuedGCode(config.raftInterfaceThicknes_um); } } }
public void WriteRaftGCodeIfRequired(GCodeExport gcode, ConfigSettings config) { LayerDataStorage storage = this; if (config.ShouldGenerateRaft()) { GCodePathConfig raftBaseConfig = new GCodePathConfig("raftBaseConfig"); raftBaseConfig.SetData(config.FirstLayerSpeed, config.RaftBaseExtrusionWidth_um, "SUPPORT"); GCodePathConfig raftMiddleConfig = new GCodePathConfig("raftMiddleConfig"); raftMiddleConfig.SetData(config.RaftPrintSpeed, config.RaftInterfaceExtrusionWidth_um, "SUPPORT"); GCodePathConfig raftSurfaceConfig = new GCodePathConfig("raftMiddleConfig"); raftSurfaceConfig.SetData((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, config.PerimeterStartEndOverlapRatio); 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); // write the skirt around the raft gcodeLayer.QueuePolygonsByOptimizer(storage.skirt, raftBaseConfig); List <Polygons> raftIslands = storage.raftOutline.ProcessIntoSeparatIslands(); foreach (var raftIsland in raftIslands) { // write the outline of the raft gcodeLayer.QueuePolygonsByOptimizer(raftIsland, raftBaseConfig); Polygons raftLines = new Polygons(); Infill.GenerateLinePaths(raftIsland, raftLines, config.RaftBaseLineSpacing_um, config.InfillExtendIntoPerimeter_um, 0); // write the inside of the raft base gcodeLayer.QueuePolygonsByOptimizer(raftLines, raftBaseConfig); if (config.RetractWhenChangingIslands) { gcodeLayer.ForceRetract(); } } gcodeLayer.WriteQueuedGCode(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, config.PerimeterStartEndOverlapRatio); 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, raftLines, config.RaftInterfaceLineSpacing_um, config.InfillExtendIntoPerimeter_um, 45); gcodeLayer.QueuePolygonsByOptimizer(raftLines, raftMiddleConfig); gcodeLayer.WriteQueuedGCode(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, config.PerimeterStartEndOverlapRatio); 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, raftLines, config.RaftSurfaceLineSpacing_um, config.InfillExtendIntoPerimeter_um, config.InfillStartingAngle + 90); } else { Infill.GenerateLinePaths(storage.raftOutline, raftLines, config.RaftSurfaceLineSpacing_um, config.InfillExtendIntoPerimeter_um, 90 * raftSurfaceIndex); } gcodeLayer.QueuePolygonsByOptimizer(raftLines, raftSurfaceConfig); gcodeLayer.WriteQueuedGCode(config.RaftInterfaceThicknes_um); } } }
public static void GenerateRaftGCodeIfRequired(SliceDataStorage storage, ConfigSettings config, GCodeExport gcode) { if (ShouldGenerateRaft(config)) { GCodePathConfig raftBaseConfig = new GCodePathConfig(config.firstLayerSpeed, config.extrusionWidth_um * 3, "SUPPORT"); GCodePathConfig raftMiddleConfig = new GCodePathConfig(config.raftPrintSpeed, config.raftInterfaceLinewidth_um, "SUPPORT"); GCodePathConfig raftSurfaceConfig = new GCodePathConfig((config.raftSurfacePrintSpeed > 0) ? config.raftSurfacePrintSpeed : config.raftPrintSpeed, config.raftSurfaceLinewidth_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.supportExtruder > 0) { gcodeLayer.setExtruder(config.supportExtruder); } gcode.setZ(config.raftBaseThickness_um); gcode.setExtrusion(config.raftBaseThickness_um, config.filamentDiameter_um, config.extrusionMultiplier); gcodeLayer.writePolygonsByOptimizer(storage.raftOutline, raftBaseConfig); Polygons raftLines = new Polygons(); Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftBaseThickness_um, config.raftLineSpacing_um, config.infillExtendIntoPerimeter_um, 0); gcodeLayer.writePolygonsByOptimizer(storage.skirt, raftBaseConfig); 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.raftInterfaceLinewidth_um, config.raftInterfaceLineSpacing_um, config.infillExtendIntoPerimeter_um, 45); gcodeLayer.writePolygonsByOptimizer(raftLines, raftMiddleConfig); gcodeLayer.writeGCode(false, config.raftInterfaceThicknes_um); } for (int raftSurfaceLayer = 1; raftSurfaceLayer <= config.raftSurfaceLayers; raftSurfaceLayer++) { 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 * raftSurfaceLayer); gcode.setExtrusion(config.raftSurfaceThickness_um, config.filamentDiameter_um, config.extrusionMultiplier); Polygons raftLines = new Polygons(); Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftSurfaceLinewidth_um, config.raftSurfaceLineSpacing_um, config.infillExtendIntoPerimeter_um, 90 * raftSurfaceLayer); gcodeLayer.writePolygonsByOptimizer(raftLines, raftSurfaceConfig); gcodeLayer.writeGCode(false, config.raftInterfaceThicknes_um); } } }
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); gcodeLayer.writePolygonsByOptimizer(storage.raftOutline, raftBaseConfig); Polygons raftLines = new Polygons(); Infill.GenerateLinePaths(storage.raftOutline, ref raftLines, config.raftBaseLineSpacing_um, config.infillExtendIntoPerimeter_um, 0); gcodeLayer.writePolygonsByOptimizer(storage.skirt, raftBaseConfig); 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); } } }
public void WriteGCode(bool liftHeadIfNeeded, int layerThickness) { GCodePathConfig lastConfig = null; int extruderIndex = gcode.GetExtruderIndex(); for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++) { GCodePath path = paths[pathIndex]; if (extruderIndex != path.extruderIndex) { extruderIndex = path.extruderIndex; gcode.SwitchExtruder(extruderIndex); } else if (path.Retract) { gcode.WriteRetraction(); } if (path.config != travelConfig && lastConfig != path.config) { //gcode.WriteComment("TYPE:{0}".FormatWith(path.config.gcodeComment)); lastConfig = path.config; ////后加的//只是边框,不填充。 if ((path.config.gcodeComment == "SKIRT") || (path.config.gcodeComment == "FILL") || (path.config.gcodeComment == "TOP-FILL")) { return; } } double speed = path.config.speed; if (path.config.lineWidth != 0) { // Only apply the extrudeSpeedFactor to extrusion moves speed = speed * extrudeSpeedFactor / 100; } else { speed = speed * travelSpeedFactor / 100; } if (path.points.Count == 1 && path.config != travelConfig && (gcode.GetPositionXY() - path.points[0]).ShorterThen(path.config.lineWidth * 2)) { //Check for lots of small moves and combine them into one large line IntPoint nextPosition = path.points[0]; int i = pathIndex + 1; while (i < paths.Count && paths[i].points.Count == 1 && (nextPosition - paths[i].points[0]).ShorterThen(path.config.lineWidth * 2)) { nextPosition = paths[i].points[0]; i++; } if (paths[i - 1].config == travelConfig) { i--; } if (i > pathIndex + 2) { nextPosition = gcode.GetPositionXY(); for (int x = pathIndex; x < i - 1; x += 2) { long oldLen = (nextPosition - paths[x].points[0]).Length(); IntPoint newPoint = (paths[x].points[0] + paths[x + 1].points[0]) / 2; long newLen = (gcode.GetPositionXY() - newPoint).Length(); if (newLen > 0) { gcode.WriteMove(newPoint, speed, (int)(path.config.lineWidth * oldLen / newLen)); } nextPosition = paths[x + 1].points[0]; } gcode.WriteMove(paths[i - 1].points[0], speed, path.config.lineWidth); pathIndex = i - 1; continue; } } bool spiralize = path.config.spiralize; if (spiralize) { //Check if we are the last spiralize path in the list, if not, do not spiralize. for (int m = pathIndex + 1; m < paths.Count; m++) { if (paths[m].config.spiralize) { spiralize = false; } } } if (spiralize) { //If we need to spiralize then raise the head slowly by 1 layer as this path progresses. double totalLength = 0; int z = gcode.GetPositionZ(); IntPoint currentPosition = gcode.GetPositionXY(); for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++) { IntPoint nextPosition = path.points[pointIndex]; totalLength += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; } double length = 0.0; currentPosition = gcode.GetPositionXY(); for (int i = 0; i < path.points.Count; i++) { IntPoint nextPosition = path.points[i]; length += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; gcode.setZ((int)(z + layerThickness * length / totalLength + .5)); gcode.WriteMove(path.points[i], speed, path.config.lineWidth); } } else { #if false // This is test code to remove double drawn small perimeter lines. if (path.config.lineWidth > 0 && path.points.Count > 2 && // If the count is not greater than 2 there is no way it can ovelap itself. gcode.GetPositionXY() == path.points[path.points.Count - 1]) { Polygons pathsWithOverlapsRemoved = GetPathsWithOverlapsRemoved(path.points, path.config.lineWidth / 2); if (pathsWithOverlapsRemoved.Count > 0) { for (int polygonIndex = 0; polygonIndex < pathsWithOverlapsRemoved.Count; polygonIndex++) { int startIndex = 0; Polygon polygon = pathsWithOverlapsRemoved[polygonIndex]; if (polygonIndex > 0) { gcode.WriteMove(polygon[0], travelConfig.speed, 0); startIndex = 1; // We skip the first point in the next extrusion, because we just moved to it. } for (int pointIndex = startIndex; pointIndex < polygon.Count; pointIndex++) { gcode.WriteMove(polygon[pointIndex], speed, path.config.lineWidth); } } } } else #endif { //TrimPerimeterIfNeeded(path); for (int i = 0; i < path.points.Count; i++) { gcode.WriteMove(path.points[i], speed, path.config.lineWidth); } } } } gcode.UpdateTotalPrintTime(); if (liftHeadIfNeeded && extraTime > 0.0) { gcode.WriteComment("Small layer, adding delay of {0}".FormatWith(extraTime)); gcode.WriteRetraction(); gcode.setZ(gcode.GetPositionZ() + 3000); gcode.WriteMove(gcode.GetPositionXY(), travelConfig.speed, 0); gcode.WriteMove(gcode.GetPositionXY() - new IntPoint(-20000, 0), travelConfig.speed, 0); gcode.WriteDelay(extraTime); } }