Exemple #1
0
        public GCodePlanner(GCodeExport gcode, int travelSpeed, int retractionMinimumDistance_um, double perimeterStartEndOverlap = 0)
        {
            this.gcodeExport = gcode;
            travelConfig     = new GCodePathConfig("travelConfig");
            travelConfig.SetData(travelSpeed, 0, "travel");

            LastPosition         = gcode.GetPositionXY();
            totalPrintTime       = 0.0;
            forceRetraction      = false;
            currentExtruderIndex = gcode.GetExtruderIndex();
            this.retractionMinimumDistance_um = retractionMinimumDistance_um;

            this.perimeterStartEndOverlapRatio = Math.Max(0, Math.Min(1, perimeterStartEndOverlap));
        }
        public LayerGCodePlanner(ConfigSettings config, GCodeExport gcode, int travelSpeed, long retractionMinimumDistance_um, double perimeterStartEndOverlap = 0)
        {
            this.config = config;

            this.gcodeExport = gcode;
            travelConfig     = new GCodePathConfig("travelConfig", "travel");
            travelConfig.SetData(travelSpeed, 0);

            LastPosition         = gcode.GetPositionXY();
            forceRetraction      = false;
            currentExtruderIndex = gcode.GetExtruderIndex();
            this.retractionMinimumDistance_um = retractionMinimumDistance_um;

            this.perimeterStartEndOverlapRatio = Math.Max(0, Math.Min(1, perimeterStartEndOverlap));
        }
        public GCodePlanner(GCodeExport gcode, int travelSpeed, int retractionMinimumDistance_um)
        {
            this.gcode = gcode;
            travelConfig = new GCodePathConfig(travelSpeed, 0, "travel");

            lastPosition = gcode.GetPositionXY();
            outerPerimetersToAvoidCrossing = null;
            extrudeSpeedFactor = 100;
            travelSpeedFactor = 100;
            extraTime = 0.0;
            totalPrintTime = 0.0;
            forceRetraction = false;
            alwaysRetract = false;
            currentExtruderIndex = gcode.GetExtruderIndex();
            this.retractionMinimumDistance_um = retractionMinimumDistance_um;
        }
        public GCodePlanner(GCodeExport gcode, int travelSpeed, int retractionMinimumDistance_um)
        {
            this.gcodeExport = gcode;
            travelConfig     = new GCodePathConfig(travelSpeed, 0, "travel");

            LastPosition = gcode.GetPositionXY();
            outerPerimetersToAvoidCrossing = null;
            extrudeSpeedFactor             = 100;
            travelSpeedFactor    = 100;
            extraTime            = 0.0;
            totalPrintTime       = 0.0;
            forceRetraction      = false;
            alwaysRetract        = false;
            currentExtruderIndex = gcode.GetExtruderIndex();
            this.retractionMinimumDistance_um = retractionMinimumDistance_um;
        }
        public GCodePlanner(GCodeExport gcode, int travelSpeed, int retractionMinimumDistance_um, double perimeterStartEndOverlap = 0)
        {
            this.gcodeExport = gcode;
            travelConfig =  new GCodePathConfig("travelConfig");
            travelConfig.SetData(travelSpeed, 0, "travel");

            LastPosition = gcode.GetPositionXY();
            outerPerimetersToAvoidCrossing = null;
            extrudeSpeedFactor = 100;
            travelSpeedFactor = 100;
            extraTime = 0.0;
            totalPrintTime = 0.0;
            forceRetraction = false;
            alwaysRetract = false;
            currentExtruderIndex = gcode.GetExtruderIndex();
            this.retractionMinimumDistance_um = retractionMinimumDistance_um;

            this.perimeterStartEndOverlapRatio = Math.Max(0, Math.Min(1, perimeterStartEndOverlap));
        }
Exemple #6
0
        public GCodePlanner(GCodeExport gcode, int travelSpeed, int retractionMinimumDistance_um, double perimeterStartEndOverlap = 0, bool mergeOverlappingLines = false)
        {
            this.mergeOverlappingLines = mergeOverlappingLines;
            this.gcodeExport           = gcode;
            travelConfig = new GCodePathConfig("travelConfig");
            travelConfig.SetData(travelSpeed, 0, "travel");

            LastPosition = gcode.GetPositionXY();
            outerPerimetersToAvoidCrossing = null;
            extrudeSpeedFactor             = 100;
            travelSpeedFactor    = 100;
            extraTime            = 0.0;
            totalPrintTime       = 0.0;
            forceRetraction      = false;
            alwaysRetract        = false;
            currentExtruderIndex = gcode.GetExtruderIndex();
            this.retractionMinimumDistance_um = retractionMinimumDistance_um;

            this.perimeterStartEndOverlapRatio = Math.Max(0, Math.Min(1, perimeterStartEndOverlap));
        }
		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 WriteQueuedGCode(int layerThickness, int fanSpeedPercent = -1, int bridgeFanSpeedPercent = -1)
        {
            GCodePathConfig lastConfig    = null;
            int             extruderIndex = gcodeExport.GetExtruderIndex();

            for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++)
            {
                GCodePath path = paths[pathIndex];
                if (extruderIndex != path.extruderIndex)
                {
                    extruderIndex = path.extruderIndex;
                    gcodeExport.SwitchExtruder(extruderIndex);
                }
                else if (path.Retract)
                {
                    gcodeExport.WriteRetraction();
                }
                if (path.config != travelConfig && lastConfig != path.config)
                {
                    if (path.config.gcodeComment == "BRIDGE" && bridgeFanSpeedPercent != -1)
                    {
                        gcodeExport.WriteFanCommand(bridgeFanSpeedPercent);
                    }
                    else if (lastConfig?.gcodeComment == "BRIDGE" && bridgeFanSpeedPercent != -1)
                    {
                        gcodeExport.WriteFanCommand(fanSpeedPercent);
                    }

                    gcodeExport.WriteComment("TYPE:{0}".FormatWith(path.config.gcodeComment));
                    lastConfig = path.config;
                }

                double speed = path.config.speed;

                if (path.config.lineWidth_um != 0)
                {
                    // Prevent cooling overrides from affecting bridge moves
                    if (path.config.gcodeComment != "BRIDGE")
                    {
                        speed = speed * extrudeSpeedFactor / 100;
                    }
                }
                else
                {
                    speed = speed * travelSpeedFactor / 100;
                }

                if (path.points.Count == 1 &&
                    path.config != travelConfig &&
                    (gcodeExport.GetPositionXY() - path.points[0].XYPoint).ShorterThen(path.config.lineWidth_um * 2))
                {
                    //Check for lots of small moves and combine them into one large line
                    Point3 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_um * 2))
                    {
                        nextPosition = paths[i].points[0];
                        i++;
                    }
                    if (paths[i - 1].config == travelConfig)
                    {
                        i--;
                    }

                    if (i > pathIndex + 2)
                    {
                        nextPosition = gcodeExport.GetPosition();
                        for (int x = pathIndex; x < i - 1; x += 2)
                        {
                            long   oldLen   = (nextPosition - paths[x].points[0]).Length();
                            Point3 newPoint = (paths[x].points[0] + paths[x + 1].points[0]) / 2;
                            long   newLen   = (gcodeExport.GetPosition() - newPoint).Length();
                            if (newLen > 0)
                            {
                                gcodeExport.WriteMove(newPoint, speed, (int)(path.config.lineWidth_um * oldLen / newLen));
                            }

                            nextPosition = paths[x + 1].points[0];
                        }

                        gcodeExport.WriteMove(paths[i - 1].points[0], speed, path.config.lineWidth_um);
                        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 are still in spiralize mode
                {
                    //If we need to spiralize then raise the head slowly by 1 layer as this path progresses.
                    double   totalLength     = 0;
                    long     z               = gcodeExport.GetPositionZ();
                    IntPoint currentPosition = gcodeExport.GetPositionXY();
                    for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++)
                    {
                        IntPoint nextPosition = path.points[pointIndex].XYPoint;
                        totalLength    += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                    }

                    double length = 0.0;
                    currentPosition = gcodeExport.GetPositionXY();
                    for (int i = 0; i < path.points.Count; i++)
                    {
                        IntPoint nextPosition = path.points[i].XYPoint;
                        length         += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                        Point3 nextExtrusion = path.points[i];
                        nextExtrusion.z = (int)(z + layerThickness * length / totalLength + .5);
                        gcodeExport.WriteMove(nextExtrusion, speed, path.config.lineWidth_um);
                    }
                }
                else
                {
                    bool pathIsClosed = true;
                    if (perimeterStartEndOverlapRatio < 1)
                    {
                        pathIsClosed = !TrimPerimeterIfNeeded(path, perimeterStartEndOverlapRatio);
                    }

                    // This is test code to remove double drawn small perimeter lines.
                    List <PathAndWidth> pathsWithOverlapsRemoved;
                    if (RemovePerimetersThatOverlap(path, speed, out pathsWithOverlapsRemoved, pathIsClosed))
                    {
                        for (int polygonIndex = 0; polygonIndex < pathsWithOverlapsRemoved.Count; polygonIndex++)
                        {
                            PathAndWidth polygon = pathsWithOverlapsRemoved[polygonIndex];

                            if (polygon.Path.Count == 2)
                            {
                                // make sure the path is ordered with the first point the closest to where we are now
                                Point3 currentPosition = gcodeExport.GetPosition();
                                // if the second point is closer swap them
                                if ((polygon.Path[1] - currentPosition).LengthSquared() < (polygon.Path[0] - currentPosition).LengthSquared())
                                {
                                    // swap them
                                    Point3 temp = polygon.Path[0];
                                    polygon.Path[0] = polygon.Path[1];
                                    polygon.Path[1] = temp;
                                }
                            }

                            // move to the start of this polygon
                            gcodeExport.WriteMove(polygon.Path[0], travelConfig.speed, 0);

                            // write all the data for the polygon
                            for (int pointIndex = 1; pointIndex < polygon.Path.Count; pointIndex++)
                            {
                                gcodeExport.WriteMove(polygon.Path[pointIndex], speed, polygon.ExtrusionWidthUm);
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < path.points.Count; i++)
                        {
                            gcodeExport.WriteMove(path.points[i], speed, path.config.lineWidth_um);
                        }
                    }
                }
            }

            gcodeExport.UpdateTotalPrintTime();
        }
        public void WriteQueuedGCode(long layerThickness_um)
        {
            GCodePathConfig lastConfig    = null;
            int             extruderIndex = gcodeExport.GetExtruderIndex();

            for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++)
            {
                var path = paths[pathIndex];
                if (extruderIndex != path.ExtruderIndex)
                {
                    extruderIndex = path.ExtruderIndex;
                    gcodeExport.SwitchExtruder(extruderIndex);
                }
                else if (path.Retract != RetractType.None)
                {
                    double timeOfMove = 0;

                    if (path.Config.LineWidthUM == 0)
                    {
                        var lengthToStart = (gcodeExport.GetPosition() - path.Polygon[0]).Length();
                        var lengthOfMove  = lengthToStart + path.Polygon.PolygonLength();
                        timeOfMove = lengthOfMove / 1000.0 / path.Speed;
                    }

                    gcodeExport.WriteRetraction(timeOfMove, path.Retract == RetractType.Force);
                }
                if (lastConfig != path.Config && path.Config != travelConfig)
                {
                    gcodeExport.WriteComment("TYPE:{0}".FormatWith(path.Config.GCodeComment));
                    lastConfig = path.Config;
                }
                if (path.FanPercent != -1)
                {
                    gcodeExport.WriteFanCommand(path.FanPercent);
                }

                if (path.Polygon.Count == 1 &&
                    path.Config != travelConfig &&
                    (gcodeExport.GetPositionXY() - path.Polygon[0]).ShorterThen(path.Config.LineWidthUM * 2))
                {
                    //Check for lots of small moves and combine them into one large line
                    IntPoint nextPosition = path.Polygon[0];
                    int      i            = pathIndex + 1;
                    while (i < paths.Count && paths[i].Polygon.Count == 1 && (nextPosition - paths[i].Polygon[0]).ShorterThen(path.Config.LineWidthUM * 2))
                    {
                        nextPosition = paths[i].Polygon[0];
                        i++;
                    }
                    if (paths[i - 1].Config == travelConfig)
                    {
                        i--;
                    }

                    if (i > pathIndex + 2)
                    {
                        nextPosition = gcodeExport.GetPosition();
                        for (int x = pathIndex; x < i - 1; x += 2)
                        {
                            long     oldLen   = (nextPosition - paths[x].Polygon[0]).Length();
                            IntPoint newPoint = (paths[x].Polygon[0] + paths[x + 1].Polygon[0]) / 2;
                            long     newLen   = (gcodeExport.GetPosition() - newPoint).Length();
                            if (newLen > 0)
                            {
                                gcodeExport.WriteMove(newPoint, path.Speed, (int)(path.Config.LineWidthUM * oldLen / newLen));
                            }

                            nextPosition = paths[x + 1].Polygon[0];
                        }

                        long lineWidth_um = path.Config.LineWidthUM;
                        if (paths[i - 1].Polygon[0].Width != 0)
                        {
                            lineWidth_um = paths[i - 1].Polygon[0].Width;
                        }

                        gcodeExport.WriteMove(paths[i - 1].Polygon[0], path.Speed, lineWidth_um);
                        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 are still in spiralize mode
                {
                    //If we need to spiralize then raise the head slowly by 1 layer as this path progresses.
                    double   totalLength     = 0;
                    long     z               = gcodeExport.GetPositionZ();
                    IntPoint currentPosition = gcodeExport.GetPositionXY();
                    for (int pointIndex = 0; pointIndex < path.Polygon.Count; pointIndex++)
                    {
                        IntPoint nextPosition = path.Polygon[pointIndex];
                        totalLength    += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                    }

                    double length = 0.0;
                    currentPosition = gcodeExport.GetPositionXY();
                    for (int i = 0; i < path.Polygon.Count; i++)
                    {
                        IntPoint nextPosition = path.Polygon[i];
                        length         += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                        IntPoint nextExtrusion = path.Polygon[i];
                        nextExtrusion.Z = (int)(z + layerThickness_um * length / totalLength + .5);
                        gcodeExport.WriteMove(nextExtrusion, path.Speed, path.Config.LineWidthUM);
                    }
                }
                else
                {
                    var loopStart  = gcodeExport.GetPosition();
                    int pointCount = path.Polygon.Count;

                    bool outerPerimeter = path.Config.GCodeComment == "WALL-OUTER";
                    bool innerPerimeter = path.Config.GCodeComment == "WALL-INNER";
                    bool perimeter      = outerPerimeter || innerPerimeter;

                    bool completeLoop = (pointCount > 0 && path.Polygon[pointCount - 1] == loopStart);
                    bool trimmed      = perimeter && completeLoop && perimeterStartEndOverlapRatio < 1;

                    // This is test code to remove double drawn small perimeter lines.
                    if (trimmed)
                    {
                        long targetDistance = (long)(path.Config.LineWidthUM * (1 - perimeterStartEndOverlapRatio));
                        path = TrimGCodePathEnd(path, targetDistance);
                        // update the point count after trimming
                        pointCount = path.Polygon.Count;
                    }

                    for (int i = 0; i < pointCount; i++)
                    {
                        long lineWidth_um = path.Config.LineWidthUM;
                        if (path.Polygon[i].Width != 0)
                        {
                            lineWidth_um = path.Polygon[i].Width;
                        }

                        gcodeExport.WriteMove(path.Polygon[i], path.Speed, lineWidth_um);
                    }

                    if (trimmed)
                    {
                        // go back to the start of the loop
                        gcodeExport.WriteMove(loopStart, path.Speed, 0);

                        var length = path.Polygon.PolygonLength(false);
                        if (outerPerimeter &&
                            config.CoastAtEndDistance_um > 0 &&
                            length > config.CoastAtEndDistance_um)
                        {
                            //gcodeExport.WriteRetraction
                            var wipePoly = new Polygon(new IntPoint[] { loopStart });
                            wipePoly.AddRange(path.Polygon);
                            // then drive down it just a bit more to make sure we have a clean overlap
                            var extraMove = wipePoly.CutToLength(config.CoastAtEndDistance_um);
                            for (int i = 0; i < extraMove.Count; i++)
                            {
                                gcodeExport.WriteMove(extraMove[i], path.Speed, 0);
                            }
                        }
                    }
                }
            }

            gcodeExport.UpdateLayerPrintTime();
        }
Exemple #10
0
        public void WriteQueuedGCode(int layerThickness, int fanSpeedPercent = -1, int bridgeFanSpeedPercent = -1)
        {
            GCodePathConfig lastConfig    = null;
            int             extruderIndex = gcodeExport.GetExtruderIndex();

            for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++)
            {
                GCodePath path = paths[pathIndex];
                if (extruderIndex != path.extruderIndex)
                {
                    extruderIndex = path.extruderIndex;
                    gcodeExport.SwitchExtruder(extruderIndex);
                }
                else if (path.Retract)
                {
                    gcodeExport.WriteRetraction();
                }
                if (path.config != travelConfig && lastConfig != path.config)
                {
                    if (path.config.gcodeComment == "BRIDGE" && bridgeFanSpeedPercent != -1)
                    {
                        gcodeExport.WriteFanCommand(bridgeFanSpeedPercent);
                    }
                    else if (lastConfig?.gcodeComment == "BRIDGE" && bridgeFanSpeedPercent != -1)
                    {
                        gcodeExport.WriteFanCommand(fanSpeedPercent);
                    }

                    gcodeExport.WriteComment("TYPE:{0}".FormatWith(path.config.gcodeComment));
                    lastConfig = path.config;
                }

                double speed = path.config.speed;

                if (path.config.lineWidth_um != 0)
                {
                    // Prevent cooling overrides from affecting bridge moves
                    if (path.config.gcodeComment != "BRIDGE")
                    {
                        speed = speed * extrudeSpeedFactor / 100;
                    }
                }
                else
                {
                    speed = speed * travelSpeedFactor / 100;
                }

                if (path.points.Count == 1 &&
                    path.config != travelConfig &&
                    (gcodeExport.GetPositionXY() - path.points[0]).ShorterThen(path.config.lineWidth_um * 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_um * 2))
                    {
                        nextPosition = paths[i].points[0];
                        i++;
                    }
                    if (paths[i - 1].config == travelConfig)
                    {
                        i--;
                    }

                    if (i > pathIndex + 2)
                    {
                        nextPosition = gcodeExport.GetPosition();
                        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   = (gcodeExport.GetPosition() - newPoint).Length();
                            if (newLen > 0)
                            {
                                gcodeExport.WriteMove(newPoint, speed, (int)(path.config.lineWidth_um * oldLen / newLen));
                            }

                            nextPosition = paths[x + 1].points[0];
                        }

                        long lineWidth_um = path.config.lineWidth_um;
                        if (paths[i - 1].points[0].Width != 0)
                        {
                            lineWidth_um = paths[i - 1].points[0].Width;
                        }

                        gcodeExport.WriteMove(paths[i - 1].points[0], speed, lineWidth_um);
                        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 are still in spiralize mode
                {
                    //If we need to spiralize then raise the head slowly by 1 layer as this path progresses.
                    double   totalLength     = 0;
                    long     z               = gcodeExport.GetPositionZ();
                    IntPoint currentPosition = gcodeExport.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 = gcodeExport.GetPositionXY();
                    for (int i = 0; i < path.points.Count; i++)
                    {
                        IntPoint nextPosition = path.points[i];
                        length         += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                        IntPoint nextExtrusion = path.points[i];
                        nextExtrusion.Z = (int)(z + layerThickness * length / totalLength + .5);
                        gcodeExport.WriteMove(nextExtrusion, speed, path.config.lineWidth_um);
                    }
                }
                else
                {
                    // This is test code to remove double drawn small perimeter lines.
                    Polygons pathsWithOverlapsRemoved = null;
                    bool     pathHadOverlaps          = false;
                    bool     pathIsClosed             = true;
                    if (mergeOverlappingLines &&
                        (path.config.gcodeComment == "WALL-OUTER" || path.config.gcodeComment == "WALL-INNER"))
                    {
                        //string perimeterString = Newtonsoft.Json.JsonConvert.SerializeObject(path);
                        if (perimeterStartEndOverlapRatio < 1)
                        {
                            path = TrimPerimeter(path, perimeterStartEndOverlapRatio);
                            //string trimmedString = Newtonsoft.Json.JsonConvert.SerializeObject(path);
                            // it was closed but now it isn't
                            pathIsClosed = false;
                        }

                        if (path.config.lineWidth_um > 0 &&
                            path.points.Count > 2)
                        {
                            // have to add in the position we are currently at
                            path.points.Insert(0, gcodeExport.GetPosition());
                            //string openPerimeterString = Newtonsoft.Json.JsonConvert.SerializeObject(path);
                            pathHadOverlaps = MergePerimeterOverlaps(path.points, path.config.lineWidth_um, out pathsWithOverlapsRemoved, pathIsClosed) &&
                                              pathsWithOverlapsRemoved.Count > 0;
                            //string trimmedString = Newtonsoft.Json.JsonConvert.SerializeObject(pathsWithOverlapsRemoved);
                        }
                    }

                    if (pathHadOverlaps)
                    {
                        for (int polygonIndex = 0; polygonIndex < pathsWithOverlapsRemoved.Count; polygonIndex++)
                        {
                            Polygon polygon = pathsWithOverlapsRemoved[polygonIndex];

                            if (polygon.Count == 2)
                            {
                                // make sure the path is ordered with the first point the closest to where we are now
                                IntPoint currentPosition = gcodeExport.GetPosition();
                                // if the second point is closer swap them
                                if ((polygon[1] - currentPosition).LengthSquared() < (polygon[0] - currentPosition).LengthSquared())
                                {
                                    // swap them
                                    IntPoint temp = polygon[0];
                                    polygon[0] = polygon[1];
                                    polygon[1] = temp;
                                }
                            }

                            // move to the start of this polygon
                            gcodeExport.WriteMove(polygon[0], travelConfig.speed, 0);

                            // write all the data for the polygon
                            for (int pointIndex = 1; pointIndex < polygon.Count; pointIndex++)
                            {
                                gcodeExport.WriteMove(polygon[pointIndex], speed, polygon[pointIndex - 1].Width);
                            }
                        }
                    }
                    else
                    {
                        int outputCount = path.points.Count;
                        for (int i = 0; i < outputCount; i++)
                        {
                            long lineWidth_um = path.config.lineWidth_um;
                            if (path.points[i].Width != 0)
                            {
                                lineWidth_um = path.points[i].Width;
                            }

                            gcodeExport.WriteMove(path.points[i], speed, lineWidth_um);
                        }
                    }
                }
            }

            gcodeExport.UpdateTotalPrintTime();
        }
        public void WriteQueuedGCode(int layerThickness)
        {
            GCodePathConfig lastConfig    = null;
            int             extruderIndex = gcodeExport.GetExtruderIndex();

            for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++)
            {
                GCodePath path = paths[pathIndex];
                if (extruderIndex != path.extruderIndex)
                {
                    extruderIndex = path.extruderIndex;
                    gcodeExport.SwitchExtruder(extruderIndex);
                }
                else if (path.Retract)
                {
                    gcodeExport.WriteRetraction();
                }
                if (path.config != travelConfig && lastConfig != path.config)
                {
                    gcodeExport.WriteComment("TYPE:{0}".FormatWith(path.config.gcodeComment));
                    lastConfig = path.config;
                }

                double speed = path.config.speed;
                if (path.config.lineWidth_um != 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 &&
                    (gcodeExport.GetPositionXY() - path.points[0].XYPoint).ShorterThen(path.config.lineWidth_um * 2))
                {
                    //Check for lots of small moves and combine them into one large line
                    Point3 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_um * 2))
                    {
                        nextPosition = paths[i].points[0];
                        i++;
                    }
                    if (paths[i - 1].config == travelConfig)
                    {
                        i--;
                    }

                    if (i > pathIndex + 2)
                    {
                        nextPosition = gcodeExport.GetPosition();
                        for (int x = pathIndex; x < i - 1; x += 2)
                        {
                            long   oldLen   = (nextPosition - paths[x].points[0]).Length();
                            Point3 newPoint = (paths[x].points[0] + paths[x + 1].points[0]) / 2;
                            long   newLen   = (gcodeExport.GetPosition() - newPoint).Length();
                            if (newLen > 0)
                            {
                                gcodeExport.WriteMove(newPoint, speed, (int)(path.config.lineWidth_um * oldLen / newLen));
                            }

                            nextPosition = paths[x + 1].points[0];
                        }

                        gcodeExport.WriteMove(paths[i - 1].points[0], speed, path.config.lineWidth_um);
                        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 are still in spiralize mode
                {
                    //If we need to spiralize then raise the head slowly by 1 layer as this path progresses.
                    double   totalLength     = 0;
                    long     z               = gcodeExport.GetPositionZ();
                    IntPoint currentPosition = gcodeExport.GetPositionXY();
                    for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++)
                    {
                        IntPoint nextPosition = path.points[pointIndex].XYPoint;
                        totalLength    += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                    }

                    double length = 0.0;
                    currentPosition = gcodeExport.GetPositionXY();
                    for (int i = 0; i < path.points.Count; i++)
                    {
                        IntPoint nextPosition = path.points[i].XYPoint;
                        length         += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                        Point3 nextExtrusion = path.points[i];
                        nextExtrusion.z = (int)(z + layerThickness * length / totalLength + .5);
                        gcodeExport.WriteMove(nextExtrusion, speed, path.config.lineWidth_um);
                    }
                }
                else
                {
                    // This is test code to remove double drawn small perimeter lines.
                    if (RemoveDoubleDrawPerimeterLines(path, speed))
                    {
                        return;
                    }
                    else
                    {
                        //TrimPerimeterIfNeeded(path);

                        for (int i = 0; i < path.points.Count; i++)
                        {
                            gcodeExport.WriteMove(path.points[i], speed, path.config.lineWidth_um);
                        }
                    }
                }
            }

            gcodeExport.UpdateTotalPrintTime();
        }
Exemple #12
0
        public void ForceMinimumLayerTime(double minTime, int minimumPrintingSpeed)
        {
            IntPoint lastPosition = gcode.GetPositionXY();
            double   travelTime   = 0.0;
            double   extrudeTime  = 0.0;

            for (int n = 0; n < paths.Count; n++)
            {
                GCodePath path = paths[n];
                for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++)
                {
                    IntPoint currentPosition = path.points[pointIndex];
                    double   thisTime        = (lastPosition - currentPosition).LengthMm() / (double)(path.config.speed);
                    if (path.config.lineWidth != 0)
                    {
                        extrudeTime += thisTime;
                    }
                    else
                    {
                        travelTime += thisTime;
                    }

                    lastPosition = currentPosition;
                }
            }

            double totalTime = extrudeTime + travelTime;

            if (totalTime < minTime && extrudeTime > 0.0)
            {
                double minExtrudeTime = minTime - travelTime;
                if (minExtrudeTime < 1)
                {
                    minExtrudeTime = 1;
                }

                double factor = extrudeTime / minExtrudeTime;
                for (int n = 0; n < paths.Count; n++)
                {
                    GCodePath path = paths[n];
                    if (path.config.lineWidth == 0)
                    {
                        continue;
                    }

                    int speed = (int)(path.config.speed * factor);
                    if (speed < minimumPrintingSpeed)
                    {
                        factor = (double)(minimumPrintingSpeed) / (double)(path.config.speed);
                    }
                }

                //Only slow down with the minimum time if that will be slower then a factor already set. First layer slowdown also sets the speed factor.
                if (factor * 100 < getExtrudeSpeedFactor())
                {
                    SetExtrudeSpeedFactor((int)(factor * 100));
                }
                else
                {
                    factor = getExtrudeSpeedFactor() / 100.0;
                }

                if (minTime - (extrudeTime / factor) - travelTime > 0.1)
                {
                    //TODO: Use up this extra time (circle around the print?)
                    this.extraTime = minTime - (extrudeTime / factor) - travelTime;
                }
                this.totalPrintTime = (extrudeTime / factor) + travelTime;
            }
            else
            {
                this.totalPrintTime = totalTime;
            }
        }
        public void WriteQueuedGCode(int layerThickness, int fanSpeedPercent = -1, int bridgeFanSpeedPercent = -1)
        {
            GCodePathConfig lastConfig    = null;
            int             extruderIndex = gcodeExport.GetExtruderIndex();

            for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++)
            {
                GCodePath path = paths[pathIndex];
                if (extruderIndex != path.extruderIndex)
                {
                    extruderIndex = path.extruderIndex;
                    gcodeExport.SwitchExtruder(extruderIndex);
                }
                else if (path.Retract)
                {
                    gcodeExport.WriteRetraction();
                }
                if (path.config != travelConfig && lastConfig != path.config)
                {
                    if (path.config.gcodeComment == "BRIDGE" && bridgeFanSpeedPercent != -1)
                    {
                        gcodeExport.WriteFanCommand(bridgeFanSpeedPercent);
                    }
                    else if (lastConfig?.gcodeComment == "BRIDGE" && bridgeFanSpeedPercent != -1)
                    {
                        gcodeExport.WriteFanCommand(fanSpeedPercent);
                    }

                    gcodeExport.WriteComment("TYPE:{0}".FormatWith(path.config.gcodeComment));
                    lastConfig = path.config;
                }

                double speed = path.config.speed;

                if (path.config.lineWidth_um != 0)
                {
                    // Prevent cooling overrides from affecting bridge moves
                    if (path.config.gcodeComment != "BRIDGE")
                    {
                        speed = speed * extrudeSpeedFactor / 100;
                    }
                }
                else
                {
                    speed = speed * travelSpeedFactor / 100;
                }

                if (path.polygon.Count == 1 &&
                    path.config != travelConfig &&
                    (gcodeExport.GetPositionXY() - path.polygon[0]).ShorterThen(path.config.lineWidth_um * 2))
                {
                    //Check for lots of small moves and combine them into one large line
                    IntPoint nextPosition = path.polygon[0];
                    int      i            = pathIndex + 1;
                    while (i < paths.Count && paths[i].polygon.Count == 1 && (nextPosition - paths[i].polygon[0]).ShorterThen(path.config.lineWidth_um * 2))
                    {
                        nextPosition = paths[i].polygon[0];
                        i++;
                    }
                    if (paths[i - 1].config == travelConfig)
                    {
                        i--;
                    }

                    if (i > pathIndex + 2)
                    {
                        nextPosition = gcodeExport.GetPosition();
                        for (int x = pathIndex; x < i - 1; x += 2)
                        {
                            long     oldLen   = (nextPosition - paths[x].polygon[0]).Length();
                            IntPoint newPoint = (paths[x].polygon[0] + paths[x + 1].polygon[0]) / 2;
                            long     newLen   = (gcodeExport.GetPosition() - newPoint).Length();
                            if (newLen > 0)
                            {
                                gcodeExport.WriteMove(newPoint, speed, (int)(path.config.lineWidth_um * oldLen / newLen));
                            }

                            nextPosition = paths[x + 1].polygon[0];
                        }

                        long lineWidth_um = path.config.lineWidth_um;
                        if (paths[i - 1].polygon[0].Width != 0)
                        {
                            lineWidth_um = paths[i - 1].polygon[0].Width;
                        }

                        gcodeExport.WriteMove(paths[i - 1].polygon[0], speed, lineWidth_um);
                        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 are still in spiralize mode
                {
                    //If we need to spiralize then raise the head slowly by 1 layer as this path progresses.
                    double   totalLength     = 0;
                    long     z               = gcodeExport.GetPositionZ();
                    IntPoint currentPosition = gcodeExport.GetPositionXY();
                    for (int pointIndex = 0; pointIndex < path.polygon.Count; pointIndex++)
                    {
                        IntPoint nextPosition = path.polygon[pointIndex];
                        totalLength    += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                    }

                    double length = 0.0;
                    currentPosition = gcodeExport.GetPositionXY();
                    for (int i = 0; i < path.polygon.Count; i++)
                    {
                        IntPoint nextPosition = path.polygon[i];
                        length         += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                        IntPoint nextExtrusion = path.polygon[i];
                        nextExtrusion.Z = (int)(z + layerThickness * length / totalLength + .5);
                        gcodeExport.WriteMove(nextExtrusion, speed, path.config.lineWidth_um);
                    }
                }
                else
                {
                    // This is test code to remove double drawn small perimeter lines.
                    if (path.config.gcodeComment == "WALL-OUTER" || path.config.gcodeComment == "WALL-INNER")
                    {
                        //string perimeterString = Newtonsoft.Json.JsonConvert.SerializeObject(path);
                        if (perimeterStartEndOverlapRatio < 1)
                        {
                            path = TrimPerimeter(path, perimeterStartEndOverlapRatio);
                        }
                    }

                    int outputCount = path.polygon.Count;
                    for (int i = 0; i < outputCount; i++)
                    {
                        long lineWidth_um = path.config.lineWidth_um;
                        if (path.polygon[i].Width != 0)
                        {
                            lineWidth_um = path.polygon[i].Width;
                        }

                        gcodeExport.WriteMove(path.polygon[i], speed, lineWidth_um);
                    }
                }
            }

            gcodeExport.UpdateTotalPrintTime();
        }