Ejemplo n.º 1
0
 public void QueuePolygons(Polygons polygons, GCodePathConfig config)
 {
     foreach (var polygon in polygons)
     {
         QueuePolygon(polygon, 0, config);
     }
 }
Ejemplo n.º 2
0
        public GCodePath QueueFanCommand(int fanSpeedPercent, GCodePathConfig config)
        {
            var path = GetNewPath(config);

            path.FanPercent = fanSpeedPercent;
            return(path);
        }
Ejemplo n.º 3
0
        public void QueueExtrusionMove(IntPoint destination, GCodePathConfig config)
        {
            GetLatestPathWithConfig(config).Polygon.Add(new IntPoint(destination, CurrentZ));
            LastPosition = destination;

            //ValidatePaths();
        }
Ejemplo n.º 4
0
 public GCodePath(GCodePath copyPath)
 {
     this.config        = copyPath.config;
     this.Done          = copyPath.Done;
     this.ExtruderIndex = copyPath.ExtruderIndex;
     this.Retract       = copyPath.Retract;
     this.Polygon       = new Polygon(copyPath.Polygon);
 }
Ejemplo n.º 5
0
        public void QueueFanCommand(int fanSpeedPercent, GCodePathConfig config)
        {
            var path = GetNewPath(config);

            path.FanPercent = fanSpeedPercent;

            queuedFanSpeeds.Add(path);
        }
Ejemplo n.º 6
0
 public GCodePath(GCodePath copyPath)
 {
     this.config        = copyPath.config;
     this.done          = copyPath.done;
     this.extruderIndex = copyPath.extruderIndex;
     this.Retract       = copyPath.Retract;
     this.points        = new Polygon(copyPath.points);
 }
Ejemplo n.º 7
0
        private GCodePath GetNewPath(GCodePathConfig config)
        {
            GCodePath path = new GCodePath();

            paths.Add(path);
            path.Retract       = RetractType.None;
            path.ExtruderIndex = currentExtruderIndex;
            path.Done          = false;
            path.Config        = config;

            return(path);
        }
Ejemplo n.º 8
0
        private GCodePath GetLatestPathWithConfig(GCodePathConfig config)
        {
            if (paths.Count > 0 &&
                paths[paths.Count - 1].config == config &&
                !paths[paths.Count - 1].Done)
            {
                return(paths[paths.Count - 1]);
            }

            var path = GetNewPath(config);

            return(path);
        }
Ejemplo n.º 9
0
        private GCodePath GetLatestPathWithConfig(GCodePathConfig config, bool forceUniquePath = false)
        {
            if (!forceUniquePath &&
                paths.Count > 0 &&
                paths[paths.Count - 1].Config == config &&
                !paths[paths.Count - 1].Done)
            {
                return(paths[paths.Count - 1]);
            }

            var path = GetNewPath(config);

            return(path);
        }
Ejemplo n.º 10
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));
        }
Ejemplo n.º 11
0
        public void writePolygonsByOptimizer(Polygons polygons, GCodePathConfig config)
        {
            PathOrderOptimizer orderOptimizer = new PathOrderOptimizer(lastPosition);

            orderOptimizer.AddPolygons(polygons);

            orderOptimizer.Optimize(config);

            for (int i = 0; i < orderOptimizer.bestPolygonOrderIndex.Count; i++)
            {
                int polygonIndex = orderOptimizer.bestPolygonOrderIndex[i];
                writePolygon(polygons[polygonIndex], orderOptimizer.startIndexInPolygon[polygonIndex], config);
            }
        }
Ejemplo n.º 12
0
        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));
        }
Ejemplo n.º 13
0
        public void QueuePolygon(Polygon polygon, int startIndex, GCodePathConfig config)
        {
            IntPoint currentPosition = polygon[startIndex];

            if (!config.spiralize &&
                (LastPosition.X != currentPosition.X ||
                 LastPosition.Y != currentPosition.Y))
            {
                QueueTravel(currentPosition);
            }

            if (config.closedLoop)
            {
                for (int positionIndex = 1; positionIndex < polygon.Count; positionIndex++)
                {
                    IntPoint destination = polygon[(startIndex + positionIndex) % polygon.Count];
                    QueueExtrusionMove(destination, config);
                    currentPosition = destination;
                }

                // We need to actually close the polygon so go back to the first point
                if (polygon.Count > 2)
                {
                    QueueExtrusionMove(polygon[startIndex], config);
                }
            }
            else             // we are not closed
            {
                if (startIndex == 0)
                {
                    for (int positionIndex = 1; positionIndex < polygon.Count; positionIndex++)
                    {
                        IntPoint destination = polygon[positionIndex];
                        QueueExtrusionMove(destination, config);
                        currentPosition = destination;
                    }
                }
                else
                {
                    for (int positionIndex = polygon.Count - 1; positionIndex >= 1; positionIndex--)
                    {
                        IntPoint destination = polygon[(startIndex + positionIndex) % polygon.Count];
                        QueueExtrusionMove(destination, config);
                        currentPosition = destination;
                    }
                }
            }
        }
Ejemplo n.º 14
0
        public bool QueueInterfaceSupportLayer(ConfigSettings config,
                                               LayerGCodePlanner gcodeLayer,
                                               int layerIndex,
                                               GCodePathConfig supportInterfaceConfig)
        {
            var foundSupport = false;

            // interface
            Polygons interfaceOutlines = InterfaceLayers[layerIndex];

            if (interfaceOutlines.Count > 0)
            {
                List <Polygons> interfaceIslands = interfaceOutlines.ProcessIntoSeparateIslands();

                foreach (Polygons interfaceIsland in interfaceIslands)
                {
                    var allSupport = new Polygons();

                    // force a retract if changing islands
                    if (config.RetractWhenChangingIslands)
                    {
                        gcodeLayer.ForceRetract();
                    }

                    var infillOffset = -config.ExtrusionWidth_um + config.InfillExtendIntoPerimeter_um;

                    // make a border if layer 0
                    // make a border if layer 0
                    if (config.GenerateSupportPerimeter || layerIndex == 0)
                    {
                        allSupport.AddRange(interfaceIsland.Offset(config.ExtrusionWidth_um / 2));
                    }

                    var supportLines = new Polygons();
                    Infill.GenerateLineInfill(config, interfaceIsland.Offset(infillOffset), supportLines, config.InfillStartingAngle + 90, config.ExtrusionWidth_um);
                    allSupport.AddRange(supportLines);

                    var pathFinder = new PathFinder(interfaceIsland, config.ExtrusionWidth_um * 3 / 2);

                    if (gcodeLayer.QueuePolygonsByOptimizer(allSupport, pathFinder, supportInterfaceConfig, 0))
                    {
                        foundSupport = true;
                    }
                }
            }

            return(foundSupport);
        }
Ejemplo n.º 15
0
        public GCodePlanner(GCodeExport gcode, int travelSpeed, int retractionMinimumDistance)
        {
            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 = retractionMinimumDistance;
        }
Ejemplo n.º 16
0
        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;
        }
Ejemplo n.º 17
0
        public bool QueuePolygonByOptimizer(Polygon polygon, PathFinder pathFinder, GCodePathConfig config, int layerIndex)
        {
            PathOrderOptimizer orderOptimizer = new PathOrderOptimizer(LastPosition);

            orderOptimizer.AddPolygon(polygon);

            orderOptimizer.Optimize(pathFinder, layerIndex, config);

            for (int i = 0; i < orderOptimizer.bestIslandOrderIndex.Count; i++)
            {
                int polygonIndex = orderOptimizer.bestIslandOrderIndex[i];
                QueuePolygon(polygon, orderOptimizer.startIndexInPolygon[polygonIndex], config);
            }

            return(true);
        }
Ejemplo n.º 18
0
        public void writePolygon(Polygon polygon, int startIndex, GCodePathConfig config)
        {
            IntPoint currentPosition = polygon[startIndex];

            writeTravel(currentPosition);
            for (int i = 1; i < polygon.Count; i++)
            {
                IntPoint destination = polygon[(startIndex + i) % polygon.Count];
                writeExtrusionMove(destination, config);
                currentPosition = destination;
            }

            if (polygon.Count > 2)
            {
                writeExtrusionMove(polygon[startIndex], config);
            }
        }
Ejemplo n.º 19
0
        public void writePolygonsByOptimizer(Polygons polygons, GCodePathConfig config)
        {
            PathOrderOptimizer orderOptimizer = new PathOrderOptimizer(lastPosition);

            for (int i = 0; i < polygons.Count; i++)
            {
                orderOptimizer.addPolygon(polygons[i]);
            }

            orderOptimizer.optimize();

            for (int i = 0; i < orderOptimizer.polyOrder.Count; i++)
            {
                int polygonIndex = orderOptimizer.polyOrder[i];
                writePolygon(polygons[polygonIndex], orderOptimizer.polyStart[polygonIndex], config);
            }
        }
Ejemplo n.º 20
0
        GCodePath getLatestPathWithConfig(GCodePathConfig config)
        {
            if (paths.Count > 0 &&
                paths[paths.Count - 1].config == config &&
                !paths[paths.Count - 1].done)
            {
                return(paths[paths.Count - 1]);
            }

            paths.Add(new GCodePath());
            GCodePath ret = paths[paths.Count - 1];

            ret.Retract       = false;
            ret.config        = config;
            ret.extruderIndex = currentExtruderIndex;
            ret.done          = false;
            return(ret);
        }
Ejemplo n.º 21
0
        public void QueuePolygonsByOptimizer(Polygons polygons, GCodePathConfig config)
        {
            if (polygons.Count == 0)
            {
                return;
            }

            PathOrderOptimizer orderOptimizer = new PathOrderOptimizer(LastPosition);

            orderOptimizer.AddPolygons(polygons);

            orderOptimizer.Optimize(config);

            for (int i = 0; i < orderOptimizer.bestIslandOrderIndex.Count; i++)
            {
                int polygonIndex = orderOptimizer.bestIslandOrderIndex[i];
                QueuePolygon(polygons[polygonIndex], orderOptimizer.startIndexInPolygon[polygonIndex], config);
            }
        }
Ejemplo n.º 22
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();
            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));
        }
Ejemplo n.º 23
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));
        }
Ejemplo n.º 24
0
        public void EnsureWipeTowerIsSolid(int layerIndex, GCodePlanner gcodeLayer, GCodePathConfig fillConfig, ConfigSettings config)
        {
            if (layerIndex >= LastLayerWithChange(config) ||
                extrudersThatHaveBeenPrimed == null)
            {
                return;
            }

            // print all of the extruder loops that have not already been printed
            for (int extruderIndex = 0; extruderIndex < config.MaxExtruderCount(); extruderIndex++)
            {
                if (!extrudersThatHaveBeenPrimed[extruderIndex])
                {
                    // write the loops for this extruder, but don't change to it. We are just filling the prime tower.
                    PrimeOnWipeTower(extruderIndex, 0, gcodeLayer, fillConfig, config);
                }

                // clear the history of printer extruders for the next layer
                extrudersThatHaveBeenPrimed[extruderIndex] = false;
            }
        }
Ejemplo n.º 25
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].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();
        }
Ejemplo n.º 26
0
		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);
				}
			}
		}
Ejemplo n.º 27
0
        public bool QueueInterfaceSupportLayer(ConfigSettings config, LayerGCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportInterfaceConfig)
        {
            // interface
            bool     outputPaths = false;
            Polygons currentInterfaceOutlines2 = InterfaceLayers[layerIndex].Offset(-config.ExtrusionWidth_um / 2);

            if (currentInterfaceOutlines2.Count > 0)
            {
                List <Polygons> interfaceIslands = currentInterfaceOutlines2.ProcessIntoSeparateIslands();

                foreach (Polygons interfaceOutline in interfaceIslands)
                {
                    // force a retract if changing islands
                    if (config.RetractWhenChangingIslands)
                    {
                        gcodeLayer.ForceRetract();
                    }

                    // make a border if layer 0
                    if (layerIndex == 0)
                    {
                        Polygons infillOutline = interfaceOutline.Offset(-supportInterfaceConfig.lineWidth_um / 2);
                        Polygons outlines      = Clipper.CleanPolygons(infillOutline, config.ExtrusionWidth_um / 4);
                        if (gcodeLayer.QueuePolygonsByOptimizer(outlines, null, supportInterfaceConfig, 0))
                        {
                            outputPaths = true;
                        }
                    }

                    Polygons supportLines = new Polygons();
                    Infill.GenerateLineInfill(config, interfaceOutline, supportLines, config.InfillStartingAngle + 90, config.ExtrusionWidth_um);
                    if (gcodeLayer.QueuePolygonsByOptimizer(supportLines, null, supportInterfaceConfig, 0))
                    {
                        outputPaths = true;
                    }
                }
            }

            return(outputPaths);
        }
Ejemplo n.º 28
0
        public void QueueInterfaceSupportLayer(ConfigSettings config, GCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportInterfaceConfig)
        {
            // interface
            Polygons currentInterfaceOutlines = interfaceLayers[layerIndex].Offset(-config.ExtrusionWidth_um / 2);

            if (currentInterfaceOutlines.Count > 0)
            {
                Polygons supportLines = new Polygons();
                Infill.GenerateLineInfill(config, currentInterfaceOutlines, supportLines, config.InfillStartingAngle + 90, config.ExtrusionWidth_um);
                gcodeLayer.QueuePolygonsByOptimizer(supportLines, supportInterfaceConfig);
            }
        }
Ejemplo n.º 29
0
        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);
            }
        }
Ejemplo n.º 30
0
 public void writeExtrusionMove(IntPoint destination, GCodePathConfig config)
 {
     getLatestPathWithConfig(config).points.Add(destination);
     lastPosition = destination;
 }
Ejemplo n.º 31
0
		public void QueueNormalSupportLayer(ConfigSettings config, GCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportNormalConfig, GCodePathConfig supportInterfaceConfig)
		{
			// normal support
			Polygons currentSupportOutlines = supportOutlines[layerIndex];
			currentSupportOutlines = currentSupportOutlines.Offset(-supportNormalConfig.lineWidth_um / 2);
			List<Polygons> supportIslands = currentSupportOutlines.ProcessIntoSeparatIslands();

			foreach (Polygons islandOutline in supportIslands)
			{
				Polygons islandInfillLines = new Polygons();
				// render a grid of support
				if (config.generateSupportPerimeter)
				{
					gcodeLayer.QueuePolygonsByOptimizer(islandOutline, supportNormalConfig);
				}
				Polygons infillOutline = islandOutline.Offset(-supportNormalConfig.lineWidth_um / 2);
				switch (config.supportType)
				{
					case ConfigConstants.SUPPORT_TYPE.GRID:
						Infill.GenerateGridInfill(config, infillOutline, ref islandInfillLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
						break;

					case ConfigConstants.SUPPORT_TYPE.LINES:
						Infill.GenerateLineInfill(config, infillOutline, ref islandInfillLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
						break;
				}
				gcodeLayer.QueuePolygonsByOptimizer(islandInfillLines, supportNormalConfig);
			}

			// interface
			Polygons currentInterfaceOutlines = interfaceLayers[layerIndex].Offset(-config.extrusionWidth_um / 2);
			if (currentInterfaceOutlines.Count > 0)
			{
				Polygons supportLines = new Polygons();
				Infill.GenerateLineInfill(config, currentInterfaceOutlines, ref supportLines, config.infillStartingAngle + 90, config.extrusionWidth_um);
				gcodeLayer.QueuePolygonsByOptimizer(supportLines, supportInterfaceConfig);
			}
		}
Ejemplo n.º 32
0
		public void QueueAirGappedBottomLayer(ConfigSettings config, GCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportNormalConfig)
		{
			// normal support
			Polygons currentAirGappedBottoms = airGappedBottomOutlines[layerIndex];
			currentAirGappedBottoms = currentAirGappedBottoms.Offset(-config.extrusionWidth_um / 2);
			List<Polygons> supportIslands = currentAirGappedBottoms.ProcessIntoSeparatIslands();

			foreach (Polygons islandOutline in supportIslands)
			{
				Polygons islandInfillLines = new Polygons();
				// render a grid of support
				gcodeLayer.QueuePolygonsByOptimizer(islandOutline, supportNormalConfig);
				Polygons infillOutline = islandOutline.Offset(-config.extrusionWidth_um / 2);
				switch (config.supportType)
				{
					case ConfigConstants.SUPPORT_TYPE.GRID:
						Infill.GenerateGridInfill(config, infillOutline, ref islandInfillLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
						break;

					case ConfigConstants.SUPPORT_TYPE.LINES:
						Infill.GenerateLineInfill(config, infillOutline, ref islandInfillLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
						break;
				}
				gcodeLayer.QueuePolygonsByOptimizer(islandInfillLines, supportNormalConfig);
			}
		}
Ejemplo n.º 33
0
 public void QueueExtrusionMove(IntPoint destination, GCodePathConfig config)
 {
     GetLatestPathWithConfig(config).points.Add(new Point3(destination, CurrentZ));
     LastPosition = destination;
 }
Ejemplo n.º 34
0
        public void QueuePolygon(Polygon polygon, int startIndex, GCodePathConfig config)
        {
            IntPoint currentPosition = polygon[startIndex];

            if (!config.spiralize
                && (LastPosition.X != currentPosition.X
                || LastPosition.Y != currentPosition.Y))
            {
                QueueTravel(currentPosition);
            }

            if (config.closedLoop)
            {
                for (int positionIndex = 1; positionIndex < polygon.Count; positionIndex++)
                {
                    IntPoint destination = polygon[(startIndex + positionIndex) % polygon.Count];
                    QueueExtrusionMove(destination, config);
                    currentPosition = destination;
                }

                // We need to actually close the polygon so go back to the first point
                if (polygon.Count > 2)
                {
                    QueueExtrusionMove(polygon[startIndex], config);
                }
            }
            else // we are not closed
            {
                if (startIndex == 0)
                {
                    for (int positionIndex = 1; positionIndex < polygon.Count; positionIndex++)
                    {
                        IntPoint destination = polygon[positionIndex];
                        QueueExtrusionMove(destination, config);
                        currentPosition = destination;
                    }
                }
                else
                {
                    for (int positionIndex = polygon.Count - 1; positionIndex >= 1; positionIndex--)
                    {
                        IntPoint destination = polygon[(startIndex + positionIndex) % polygon.Count];
                        QueueExtrusionMove(destination, config);
                        currentPosition = destination;
                    }
                }
            }
        }
Ejemplo n.º 35
0
		private void QueuePolygonsConsideringSupport(int layerIndex, GCodePlanner gcodeLayer, Polygons polygonsToWrite, GCodePathConfig fillConfig, SupportWriteType supportWriteType)
		{
			if (config.generateSupport 
				&& layerIndex > 0
				&& !config.continuousSpiralOuterPerimeter)
			{
				Polygons supportOutlines = slicingData.support.GetRequiredSupportAreas(layerIndex);

				if (supportWriteType == SupportWriteType.UnsupportedAreas)
				{
					if (supportOutlines.Count > 0)
					{
						Polygons polygonsNotOnSupport;
						// don't write the bottoms that are sitting on supported areas (they will be written at air gap distance later).
						polygonsToWrite = PolygonsHelper.ConvertToLines(polygonsToWrite);

						polygonsNotOnSupport = polygonsToWrite.CreateLineDifference(supportOutlines);
						gcodeLayer.QueuePolygonsByOptimizer(polygonsNotOnSupport, fillConfig);
					}
					else
					{
						gcodeLayer.QueuePolygonsByOptimizer(polygonsToWrite, fillConfig);
					}
				}
				else
				{
					if (supportOutlines.Count > 0)
					{
						if (supportOutlines.Count > 0)
						{
							// write the bottoms that are sitting on supported areas.
							Polygons polygonsOnSupport;
							polygonsToWrite = PolygonsHelper.ConvertToLines(polygonsToWrite);

							polygonsOnSupport = supportOutlines.CreateLineIntersections(polygonsToWrite);
							// ensure that all the segments have only 2 points
							foreach(Polygon poly in polygonsOnSupport)
							{
								while(poly.Count > 2)
								{
									// This is an error and I'm not sure why it happened. It needs to be investigated. // LBB 2016 01 12
									poly.RemoveAt(poly.Count - 1);
								}
							}

							gcodeLayer.QueuePolygonsByOptimizer(polygonsOnSupport, fillConfig);
						}
						else
						{
							gcodeLayer.QueuePolygonsByOptimizer(polygonsToWrite, fillConfig);
						}
					}
				}
			}
			else if (supportWriteType == SupportWriteType.UnsupportedAreas)
			{
				gcodeLayer.QueuePolygonsByOptimizer(polygonsToWrite, fillConfig);
			}
		}
Ejemplo n.º 36
0
 public void QueuePolygons(Polygons polygons, GCodePathConfig config)
 {
     foreach(var polygon in polygons)
     {
         QueuePolygon(polygon, 0, config);
     }
 }
Ejemplo n.º 37
0
        private bool QueueClosetsInset(Polygons insetsConsider, bool limitDistance, GCodePathConfig pathConfig, int layerIndex, GCodePlanner gcodeLayer)
        {
            long maxDist_um = long.MaxValue;
            if (limitDistance)
            {
                maxDist_um = config.ExtrusionWidth_um * 4;
            }

            int polygonPrintedIndex = -1;

            for (int polygonIndex = 0; polygonIndex < insetsConsider.Count; polygonIndex++)
            {
                Polygon currentPolygon = insetsConsider[polygonIndex];
                int bestPoint = PathOrderOptimizer.GetClosestIndex(currentPolygon, gcodeLayer.LastPosition);
                if (bestPoint > -1)
                {
                    long distance = (currentPolygon[bestPoint] - gcodeLayer.LastPosition).Length();
                    if (distance < maxDist_um)
                    {
                        maxDist_um = distance;
                        polygonPrintedIndex = polygonIndex;
                    }
                }
            }

            if (polygonPrintedIndex > -1)
            {
                QueuePolygonsConsideringSupport(layerIndex, gcodeLayer, new Polygons() { insetsConsider[polygonPrintedIndex] }, pathConfig, SupportWriteType.UnsupportedAreas);
                insetsConsider.RemoveAt(polygonPrintedIndex);
                return true;
            }

            // Return the original limitDistance value if we didn't match a polygon
            return limitDistance;
        }
Ejemplo n.º 38
0
 public void WriteExtrusionMove(IntPoint destination, GCodePathConfig config)
 {
     GetLatestPathWithConfig(config).points.Add(destination);
     lastPosition = destination;
 }
Ejemplo n.º 39
0
        public void Optimize(GCodePathConfig config = null)
        {
            bool canTravelForwardOrBackward = config != null && !config.closedLoop;
            // Find the point that is closest to our current position (start position)
            bool[] polygonHasBeenAdded = new bool[polygons.Count];
            for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
            {
                Polygon currentPolygon = polygons[polygonIndex];
                if (canTravelForwardOrBackward || currentPolygon.Count < 3)
                {
                    startIndexInPolygon.Add(0);
                }
                else // This is a closed loop.
                {
                    //int bestPointIndex = GetBestEdgeIndex(currentPolygon);
                    int bestPointIndex = GetClosestIndex(currentPolygon, startPosition);
                    startIndexInPolygon.Add(bestPointIndex);
                }
            }

            IntPoint currentPosition = startPosition;
            // We loop over the polygon list twice, at each inner loop we only pick one polygon.
            for (int polygonIndexOuterLoop = 0; polygonIndexOuterLoop < polygons.Count; polygonIndexOuterLoop++)
            {
                int bestPolygonIndex = -1;
                double bestDist = double.MaxValue;
                for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
                {
                    if (polygonHasBeenAdded[polygonIndex] || polygons[polygonIndex].Count < 1)
                    {
                        continue;
                    }

                    // If there are only 2 points (a single line) or the path is marked as travel both ways, we are willing to start from the start or the end.
                    if (polygons[polygonIndex].Count == 2 || canTravelForwardOrBackward)
                    {
                        double distToSart = (polygons[polygonIndex][0] - currentPosition).LengthSquared();
                        if (distToSart < bestDist)
                        {
                            bestPolygonIndex = polygonIndex;
                            bestDist = distToSart;
                            startIndexInPolygon[polygonIndex] = 0;
                        }

                        double distToEnd = (polygons[polygonIndex][polygons[polygonIndex].Count - 1] - currentPosition).LengthSquared();
                        if (distToEnd < bestDist)
                        {
                            bestPolygonIndex = polygonIndex;
                            bestDist = distToEnd;
                            startIndexInPolygon[polygonIndex] = 1;
                        }
                    }
                    else
                    {
                        double dist = (polygons[polygonIndex][startIndexInPolygon[polygonIndex]] - currentPosition).LengthSquared();
                        if (dist < bestDist)
                        {
                            bestPolygonIndex = polygonIndex;
                            bestDist = dist;
                        }
                    }
                }

                if (bestPolygonIndex > -1)
                {
                    if (polygons[bestPolygonIndex].Count == 2 || canTravelForwardOrBackward)
                    {
                        // get the point that is opposite from the one we started on
                        int startIndex = startIndexInPolygon[bestPolygonIndex];
                        if (startIndex == 0)
                        {
                            currentPosition = polygons[bestPolygonIndex][polygons[bestPolygonIndex].Count - 1];
                        }
                        else
                        {
                            currentPosition = polygons[bestPolygonIndex][0];
                        }
                    }
                    else
                    {
                        currentPosition = polygons[bestPolygonIndex][startIndexInPolygon[bestPolygonIndex]];
                    }
                    polygonHasBeenAdded[bestPolygonIndex] = true;
                    bestPolygonOrderIndex.Add(bestPolygonIndex);
                }
            }

            currentPosition = startPosition;
            foreach (int bestPolygonIndex in bestPolygonOrderIndex)
            {
                int bestStartPoint = -1;
                double bestDist = double.MaxValue;
                if (canTravelForwardOrBackward)
                {
                    bestDist = (polygons[bestPolygonIndex][0] - currentPosition).LengthSquared();
                    bestStartPoint = 0;

                    // check if the end is better
                    int endIndex = polygons[bestPolygonIndex].Count - 1;
                    double dist = (polygons[bestPolygonIndex][endIndex] - currentPosition).LengthSquared();
                    if (dist < bestDist)
                    {
                        bestStartPoint = endIndex;
                        bestDist = dist;
                    }
                }
                else
                {
                    for (int pointIndex = 0; pointIndex < polygons[bestPolygonIndex].Count; pointIndex++)
                    {
                        double dist = (polygons[bestPolygonIndex][pointIndex] - currentPosition).LengthSquared();
                        if (dist < bestDist)
                        {
                            bestStartPoint = pointIndex;
                            bestDist = dist;
                        }
                    }
                }
                startIndexInPolygon[bestPolygonIndex] = bestStartPoint;
                if (polygons[bestPolygonIndex].Count == 2 || canTravelForwardOrBackward)
                {
                    if (bestStartPoint == 0)
                    {
                        currentPosition = polygons[bestPolygonIndex][polygons[bestPolygonIndex].Count - 1];
                    }
                    else
                    {
                        currentPosition = polygons[bestPolygonIndex][0];
                    }
                }
                else
                {
                    currentPosition = polygons[bestPolygonIndex][bestStartPoint];
                }
            }
        }
Ejemplo n.º 40
0
        public void QueueNormalSupportLayer(ConfigSettings config, GCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportNormalConfig)
        {
            // normal support
            Polygons currentSupportOutlines = supportOutlines[layerIndex];
            currentSupportOutlines = currentSupportOutlines.Offset(-supportNormalConfig.lineWidth_um / 2);
            List<Polygons> supportIslands = currentSupportOutlines.ProcessIntoSeparatIslands();

            foreach (Polygons islandOutline in supportIslands)
            {
                // force a retract if changing islands
                if (config.RetractWhenChangingIslands)
                {
                    gcodeLayer.ForceRetract();
                }

                Polygons islandInfillLines = new Polygons();
                // render a grid of support
                if (config.GenerateSupportPerimeter)
                {
                    Polygons outlines = Clipper.CleanPolygons(islandOutline, config.ExtrusionWidth_um / 4);
                    gcodeLayer.QueuePolygonsByOptimizer(outlines, supportNormalConfig);
                }

                Polygons infillOutline = islandOutline.Offset(-supportNormalConfig.lineWidth_um / 2);

                if (layerIndex == 0)
                {
                    // on the first layer print this as solid
                    Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.ExtrusionWidth_um);
                }
                else
                {
                    switch (config.SupportType)
                    {
                        case ConfigConstants.SUPPORT_TYPE.GRID:
                            Infill.GenerateGridInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um);
                            break;

                        case ConfigConstants.SUPPORT_TYPE.LINES:
                            Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um);
                            break;
                    }
                }

                gcodeLayer.QueuePolygonsByOptimizer(islandInfillLines, supportNormalConfig);
            }
        }
Ejemplo n.º 41
0
        private void QueuePolygonsConsideringSupport(int layerIndex, GCodePlanner gcodeLayer, Polygons polygonsToWrite, GCodePathConfig fillConfig, SupportWriteType supportWriteType)
        {
            bool oldLoopValue = fillConfig.closedLoop;

            if (config.GenerateSupport
                && layerIndex > 0
                && !config.ContinuousSpiralOuterPerimeter)
            {
                Polygons supportOutlines = slicingData.support.GetRequiredSupportAreas(layerIndex).Offset(fillConfig.lineWidth_um/2);

                if (supportWriteType == SupportWriteType.UnsupportedAreas)
                {
                    if (supportOutlines.Count > 0)
                    {
                        // don't write the bottoms that are sitting on supported areas (they will be written at air gap distance later).
                        Polygons polygonsToWriteAsLines = PolygonsHelper.ConvertToLines(polygonsToWrite);

                        Polygons polygonsNotOnSupport = polygonsToWriteAsLines.CreateLineDifference(supportOutlines);
                        fillConfig.closedLoop = false;
                        gcodeLayer.QueuePolygonsByOptimizer(polygonsNotOnSupport, fillConfig);
                    }
                    else
                    {
                        gcodeLayer.QueuePolygonsByOptimizer(polygonsToWrite, fillConfig);
                    }
                }
                else
                {
                    if (supportOutlines.Count > 0)
                    {
                        if (supportOutlines.Count > 0)
                        {
                            // write the bottoms that are sitting on supported areas.
                            Polygons polygonsToWriteAsLines = PolygonsHelper.ConvertToLines(polygonsToWrite);

                            Polygons polygonsOnSupport = supportOutlines.CreateLineIntersections(polygonsToWriteAsLines);
                            fillConfig.closedLoop = false;
                            gcodeLayer.QueuePolygonsByOptimizer(polygonsOnSupport, fillConfig);
                        }
                        else
                        {
                            gcodeLayer.QueuePolygonsByOptimizer(polygonsToWrite, fillConfig);
                        }
                    }
                }
            }
            else if (supportWriteType == SupportWriteType.UnsupportedAreas)
            {
                gcodeLayer.QueuePolygonsByOptimizer(polygonsToWrite, fillConfig);
            }

            fillConfig.closedLoop = oldLoopValue;
        }
Ejemplo n.º 42
0
        public void QueueInterfaceSupportLayer(ConfigSettings config, GCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportInterfaceConfig)
        {
            // interface
            Polygons currentInterfaceOutlines2 = interfaceLayers[layerIndex].Offset(-config.ExtrusionWidth_um / 2);
            if (currentInterfaceOutlines2.Count > 0)
            {
                List<Polygons> interfaceIslands = currentInterfaceOutlines2.ProcessIntoSeparatIslands();

                foreach (Polygons interfaceOutline in interfaceIslands)
                {
                    // force a retract if changing islands
                    if (config.RetractWhenChangingIslands)
                    {
                        gcodeLayer.ForceRetract();
                    }

                    Polygons supportLines = new Polygons();
                    Infill.GenerateLineInfill(config, interfaceOutline, supportLines, config.InfillStartingAngle + 90, config.ExtrusionWidth_um);
                    gcodeLayer.QueuePolygonsByOptimizer(supportLines, supportInterfaceConfig);
                }
            }
        }
Ejemplo n.º 43
0
        public void EnsureWipeTowerIsSolid(int layerIndex, GCodePlanner gcodeLayer, GCodePathConfig fillConfig, ConfigSettings config)
        {
            if(layerIndex >= LastLayerWithChange(config)
                || extrudersThatHaveBeenPrimed == null)
            {
                return;
            }

            // print all of the extruder loops that have not already been printed
            for (int extruderIndex = 0; extruderIndex < config.MaxExtruderCount(); extruderIndex++)
            {
                if (!extrudersThatHaveBeenPrimed[extruderIndex])
                {
                    // write the loops for this extruder, but don't change to it. We are just filling the prime tower.
                    PrimeOnWipeTower(extruderIndex, 0, gcodeLayer, fillConfig, config);
                }

                // clear the history of printer extruders for the next layer
                extrudersThatHaveBeenPrimed[extruderIndex] = false;
            }
        }
Ejemplo n.º 44
0
        public void QueueNormalSupportLayer(ConfigSettings config, GCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportNormalConfig)
        {
            // normal support
            Polygons currentSupportOutlines = supportOutlines[layerIndex];

            currentSupportOutlines = currentSupportOutlines.Offset(-supportNormalConfig.lineWidth_um / 2);
            List <Polygons> supportIslands = currentSupportOutlines.ProcessIntoSeparatIslands();

            foreach (Polygons islandOutline in supportIslands)
            {
                Polygons islandInfillLines = new Polygons();
                // render a grid of support
                if (config.GenerateSupportPerimeter)
                {
                    Polygons outlines = Clipper.CleanPolygons(islandOutline, config.ExtrusionWidth_um / 4);
                    gcodeLayer.QueuePolygonsByOptimizer(outlines, supportNormalConfig);
                }

                Polygons infillOutline = islandOutline.Offset(-supportNormalConfig.lineWidth_um / 2);

                if (layerIndex == 0)
                {
                    // on the first layer print this as solid
                    Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.ExtrusionWidth_um);
                }
                else
                {
                    switch (config.SupportType)
                    {
                    case ConfigConstants.SUPPORT_TYPE.GRID:
                        Infill.GenerateGridInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um);
                        break;

                    case ConfigConstants.SUPPORT_TYPE.LINES:
                        Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um);
                        break;
                    }
                }

                gcodeLayer.QueuePolygonsByOptimizer(islandInfillLines, supportNormalConfig);
            }
        }
Ejemplo n.º 45
0
        public void PrimeOnWipeTower(int extruderIndex, int layerIndex, GCodePlanner gcodeLayer, GCodePathConfig fillConfig, ConfigSettings config)
        {
            if (config.WipeTowerSize_um < 1
                || extrudersThatHaveBeenPrimed == null
                || layerIndex > LastLayerWithChange(config) + 1)
            {
                return;
            }

            //If we changed extruder, print the wipe/prime tower for this nozzle;
            Polygons fillPolygons = new Polygons();
            GenerateWipeTowerInfill(extruderIndex, this.wipeTower, fillPolygons, fillConfig.lineWidth_um, config);
            gcodeLayer.QueuePolygons(fillPolygons, fillConfig);

            extrudersThatHaveBeenPrimed[extruderIndex] = true;
        }
Ejemplo n.º 46
0
        public void QueueAirGappedBottomLayer(ConfigSettings config, LayerGCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportNormalConfig)
        {
            // normal support
            Polygons currentAirGappedBottoms = AirGappedBottomOutlines[layerIndex];

            currentAirGappedBottoms = currentAirGappedBottoms.Offset(-config.ExtrusionWidth_um / 2);
            List <Polygons> supportIslands = currentAirGappedBottoms.ProcessIntoSeparateIslands();

            foreach (Polygons islandOutline in supportIslands)
            {
                // force a retract if changing islands
                if (config.RetractWhenChangingIslands)
                {
                    gcodeLayer.ForceRetract();
                }

                Polygons islandInfillLines = new Polygons();
                // render a grid of support
                if (config.GenerateSupportPerimeter)
                {
                    Polygons outlines = Clipper.CleanPolygons(islandOutline, config.ExtrusionWidth_um / 4);
                    gcodeLayer.QueuePolygonsByOptimizer(outlines, null, supportNormalConfig, 0);
                }
                Polygons infillOutline = islandOutline.Offset(-config.ExtrusionWidth_um / 2);
                switch (config.SupportType)
                {
                case ConfigConstants.SUPPORT_TYPE.GRID:
                    Infill.GenerateGridInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um);
                    break;

                case ConfigConstants.SUPPORT_TYPE.LINES:
                    Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um);
                    break;
                }
                gcodeLayer.QueuePolygonsByOptimizer(islandInfillLines, null, supportNormalConfig, 0);
            }
        }
Ejemplo n.º 47
0
        public void QueuePolygonsByOptimizer(Polygons polygons, GCodePathConfig config)
        {
            PathOrderOptimizer orderOptimizer = new PathOrderOptimizer(LastPosition);
            orderOptimizer.AddPolygons(polygons);

            orderOptimizer.Optimize(config);

            for (int i = 0; i < orderOptimizer.bestIslandOrderIndex.Count; i++)
            {
                int polygonIndex = orderOptimizer.bestIslandOrderIndex[i];
                QueuePolygon(polygons[polygonIndex], orderOptimizer.startIndexInPolygon[polygonIndex], config);
            }
        }
Ejemplo n.º 48
0
        public bool QueueNormalSupportLayer(ConfigSettings config, LayerGCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportNormalConfig)
        {
            // normal support
            Polygons currentSupportOutlines = SparseSupportOutlines[layerIndex];

            currentSupportOutlines = currentSupportOutlines.Offset(-supportNormalConfig.lineWidth_um / 2);
            List <Polygons> supportIslands = currentSupportOutlines.ProcessIntoSeparateIslands();

            bool outputPaths = false;

            foreach (Polygons islandOutline in supportIslands)
            {
                // force a retract if changing islands
                if (config.RetractWhenChangingIslands)
                {
                    gcodeLayer.ForceRetract();
                }

                Polygons islandInfillLines = new Polygons();
                // render a grid of support
                if (config.GenerateSupportPerimeter || layerIndex == 0)
                {
                    Polygons outlines = Clipper.CleanPolygons(islandOutline, config.ExtrusionWidth_um / 4);
                    if (gcodeLayer.QueuePolygonsByOptimizer(outlines, null, supportNormalConfig, 0))
                    {
                        outputPaths = true;
                    }
                }

                Polygons infillOutline = islandOutline.Offset(-(int)supportNormalConfig.lineWidth_um);

                if (layerIndex == 0)
                {
                    // on the first layer print this as solid
                    Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.ExtrusionWidth_um);
                }
                else
                {
                    switch (config.SupportType)
                    {
                    case ConfigConstants.SUPPORT_TYPE.GRID:
                        Infill.GenerateGridInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um);
                        break;

                    case ConfigConstants.SUPPORT_TYPE.LINES:
                        Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um);
                        break;
                    }
                }

                PathFinder pathFinder = null;
                if (config.AvoidCrossingPerimeters)
                {
                    pathFinder = new PathFinder(infillOutline, -config.ExtrusionWidth_um / 2, useInsideCache: config.AvoidCrossingPerimeters);
                }
                var oldPathFinder = gcodeLayer.PathFinder;
                gcodeLayer.PathFinder = pathFinder;
                if (gcodeLayer.QueuePolygonsByOptimizer(islandInfillLines, null, supportNormalConfig, 0))
                {
                    outputPaths |= true;
                }
                gcodeLayer.PathFinder = oldPathFinder;
            }

            return(outputPaths);
        }
Ejemplo n.º 49
0
        private GCodePath GetLatestPathWithConfig(GCodePathConfig config)
        {
            if (paths.Count > 0
                && paths[paths.Count - 1].config == config
                && !paths[paths.Count - 1].done)
            {
                return paths[paths.Count - 1];
            }

            paths.Add(new GCodePath());
            GCodePath ret = paths[paths.Count - 1];
            ret.Retract = false;
            ret.config = config;
            ret.extruderIndex = currentExtruderIndex;
            ret.done = false;
            return ret;
        }