Beispiel #1
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Converts the contents of the isoPlotSegment to an appropriate GCodeCmd object
        /// </summary>
        /// <returns>list of GCodeCmd objects or null for fail</returns>
        public override List <GCodeCmd> GetGCodeCmds(GCodeFileStateMachine stateMachine)
        {
            int             adjustedNumTabs;
            GCodeCmd_Line   lineObj        = null;
            GCodeCmd_Line   lineObjSegment = null;
            List <GCodeCmd> retList        = new List <GCodeCmd>();
            float           fX0;
            float           fY0;
            float           fX1;
            float           fY1;
            List <PointF>   ptListMidCenters = new List <PointF>();

            // build the line now
            if (ReverseOnConversionToGCode == true)
            {
                // NOTE we use the chainedStart_X as point x1,y1 here.
                lineObj = new GCodeCmd_Line(x0, y0, ChainedStart_X, ChainedStart_Y, this.PointsAddedCount, this.DebugID);
                fX0     = (float)x0;
                fY0     = (float)y0;
                fX1     = (float)ChainedStart_X;
                fY1     = (float)ChainedStart_Y;
                lineObj.ReverseOnConversionToGCode = true;
            }
            else
            {
                // NOTE we use the chainedStart_X as point x0,y0 here.
                lineObj = new GCodeCmd_Line(ChainedStart_X, ChainedStart_Y, x1, y1, this.PointsAddedCount, this.DebugID);
                fX0     = (float)ChainedStart_X;
                fY0     = (float)ChainedStart_Y;
                fX1     = (float)x1;
                fY1     = (float)y1;
                lineObj.ReverseOnConversionToGCode = false;
            }
            lineObj.DoNotEmitToGCode = DoNotEmitToGCode;

            //DebugMessage("IsoSegmentLength=" + IsoSegmentLength(stateMachine).ToString());

            // figure out our adjusted number of tabs
            adjustedNumTabs = 0;
            if (NumberOfTabs <= 0)
            {
                adjustedNumTabs = 0;
            }
            else
            {
                adjustedNumTabs = CalcAdjustedNumberOfTabs(stateMachine);
            }

            //DebugMessage("NumberOfTabs=" + NumberOfTabs.ToString());
            //DebugMessage("adjustedNumTabs=" + adjustedNumTabs.ToString());
            //DebugMessage("TabLength=" + TabLength.ToString());

            // do we need to break the line to add tabs?
            if ((NumberOfTabs <= 0) || (adjustedNumTabs <= 0) || (TabLength <= 0))
            {
                // no we do not, add it and return it as a single line in a list
                retList.Add(lineObj);
                return(retList);
            }

            // calc the length of a tab in isoplot units
            float TabLenInIsoPlotUnits = TabLength * stateMachine.IsoPlotPointsPerAppUnit;
            // we use half of half of the Isolation width to compensate for the width of the bit
            float millRadiusCompensatedTabLenInIsoPlotUnits = TabLenInIsoPlotUnits + ((stateMachine.IsolationWidth * stateMachine.IsoPlotPointsPerAppUnit) / 2);
            // this is the amount of a segment repressented by a tab
            float pctOfSegmentInASingleTab = millRadiusCompensatedTabLenInIsoPlotUnits / IsoSegmentLength;
            // we deduct half a tab width from the midpoint to calc the new start and end points
            float pctOfSegmentInASingleHalfTab = pctOfSegmentInASingleTab / 2;

            // set this now
            int numSegments = adjustedNumTabs + 1;

            // figure out the set of points starting and ending each line segment
            // add the original line start point
            ptListMidCenters.Add(new PointF(fX0, fY0));

            // this is based on the line partitioning algorythm courtesy of Tom Sirgedas
            // https://stackoverflow.com/questions/3542402/partition-line-into-equal-parts
            for (float i = 1; i < numSegments; i++)
            {
                float weightedAverage    = (i / numSegments);
                float workingNearSidePct = pctOfSegmentInASingleHalfTab;
                float workingFarSidePct  = pctOfSegmentInASingleHalfTab;

                // calc the start of the segment
                float startX = fX0 * (1 - (weightedAverage - workingNearSidePct)) + fX1 * (weightedAverage - workingNearSidePct);
                float startY = fY0 * (1 - (weightedAverage - workingNearSidePct)) + fY1 * (weightedAverage - workingNearSidePct);
                // calc the end of the segment
                float endX = fX0 * (1 - (weightedAverage + workingFarSidePct)) + fX1 * (weightedAverage + workingFarSidePct);
                float endY = fY0 * (1 - (weightedAverage + workingFarSidePct)) + fY1 * (weightedAverage + workingFarSidePct);
                // add the point about this center
                ptListMidCenters.Add(new PointF(startX, startY));
                ptListMidCenters.Add(new PointF(endX, endY));
            }

            // add the original line end point
            ptListMidCenters.Add(new PointF(fX1, fY1));

            // by this point we have a list of points, each pair represents a line we should draw
            // now we go through the points list and build our lines from them
            for (int i = 0; i < ptListMidCenters.Count; i += 2)
            {
                float startX = ptListMidCenters[i].X;
                float startY = ptListMidCenters[i].Y;
                float endX   = ptListMidCenters[i + 1].X;
                float endY   = ptListMidCenters[i + 1].Y;

                // convert to ints
                int startXInt = (int)Math.Round(startX, 0);
                int startYInt = (int)Math.Round(startY, 0);
                int endXInt   = (int)Math.Round(endX, 0);
                int endYInt   = (int)Math.Round(endY, 0);

                // create a new line, give it a debugID based off the original full length one, and copy other info in as well
                lineObjSegment = new GCodeCmd_Line(startXInt, startYInt, endXInt, endYInt, this.PointsAddedCount, (int)((this.DebugID * DEFAULT_NEW_DEBUG_ID_MULTIPLIER) + i));
                lineObjSegment.ReverseOnConversionToGCode = this.ReverseOnConversionToGCode;
                // add it
                retList.Add(lineObjSegment);
            }

            // was the original line object reversed? If so we have to reverse the order of the segments
            if (this.ReverseOnConversionToGCode == true)
            {
                retList.Reverse();
            }

            // return this
            return(retList);
        }
Beispiel #2
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Generates the gcode to mill a pocket in the surface. We use this for
        /// BedFlattening
        /// </summary>
        /// <remarks>the gcode file is assumed to have been populated with the standard headers.
        /// We just add our lines onto the end.</remarks>
        /// <param name="lX">low x coord</param>
        /// <param name="lY">low y coord</param>
        /// <param name="hX">high x coord</param>
        /// <param name="hY">high y coord</param>
        /// <param name="millWidth">the diameter of the mill doing the pocketing</param>
        /// <param name="overlapScaleFactor">the amount of overlap we require. Expressed as decimal fraction. 0.25 =25%</param>
        /// <param name="errStr">the error string</param>
        public int GeneratePocketGCode(float isoPlotPointsPerAppUnit, float lX, float lY, float hX, float hY, float millWidth, float overlapScaleFactor, ref string errStr)
        {
            int                i      = 0;
            GCodeCmd_ZMove     zLine  = null;
            GCodeCmd_RapidMove rmLine = null;
            GCodeCmd_Line      gcLine = null;
            GCodeCmd_Comment   coLine = null;

            errStr = "";
            float centerX;
            float centerY;
            float lXCutCoord;
            float lYCutCoord;
            float hXCutCoord;
            float hYCutCoord;
            float lastXCoord;
            float lastYCoord;

            // test these
            if (isoPlotPointsPerAppUnit <= 0)
            {
                LogMessage("GeneratePocketGCode: isoPlotPointsPerAppUnit<=0");
                errStr = "isoPlotPointsPerAppUnit is invalid.";
                return(1023);
            }

            if ((lX == float.MaxValue) ||
                (lY == float.MaxValue) ||
                (hX == float.MinValue) ||
                (hY == float.MinValue))
            {
                LogMessage("GeneratePocketGCode: One or more of the lX,lY,hXor hY coordinates are invalid.");
                errStr = "The X and Y coordinates of the pocket rectangle are invalid.";
                return(1024);
            }
            // do we enclose an area?
            if ((lX == hX) || (lY == hY))
            {
                LogMessage("GeneratePocketGCode: The lX,lY,hXor hY coordinates do not enclose an area.");
                errStr = "The X and Y coordinates of the pocket rectangle do not enclose an area.";
                return(1025);
            }
            // are we inverted
            if ((lX > hX) || (lY > hY))
            {
                LogMessage("GeneratePocketGCode: The lX,lY,hXor hY coordinates are inverted.");
                errStr = "The X and Y coordinates of the pocket rectangle are inverted.";
                return(1026);
            }
            // more checks
            if (millWidth < 0)
            {
                LogMessage("GeneratePocketGCode: The millWidth is invalid.");
                errStr = "The millWidth is invalid.";
                return(1027);
            }
            // more checks
            if ((overlapScaleFactor > 1) || (overlapScaleFactor < 0))
            {
                LogMessage("GeneratePocketGCode: The overlapScaleFactor is invalid.");
                errStr = "The overlapScaleFactor is invalid.";
                return(1028);
            }
            if (StateMachine.CurrentZFeedrate <= 0)
            {
                LogMessage("GeneratePocketGCode: The zFeedRate is invalid.");
                errStr = "The zFeedRate is invalid.";
                return(1029);
            }
            if (StateMachine.CurrentXYFeedrate <= 0)
            {
                LogMessage("GeneratePocketGCode: The xyFeedRate is invalid.");
                errStr = "The xyFeedRate is invalid.";
                return(1030);
            }
            if (StateMachine.ZCoordForCut > StateMachine.ZCoordForClear)
            {
                LogMessage("GeneratePocketGCode: The zCutLevel > zClearLevel. This cannot be correct.");
                errStr = "The zCutLevel > zClearLevel. This cannot be correct.";
                return(1031);
            }
            // test to see if the pocket can be cut with this mill
            if ((millWidth >= (hX - lX)) || (millWidth >= (hY - lY)))
            {
                LogMessage("GeneratePocketGCode: The mill diameter is bigger than the pocket area.");
                errStr = "The mill diameter is bigger than the pocket area. Pocket cannot be cut with this mill.";
                return(1031);
            }

            // calculate the center point
            centerX = (((hX - lX) / 2f) + lX) * isoPlotPointsPerAppUnit;
            centerY = (((hY - lY) / 2f) + lY) * isoPlotPointsPerAppUnit;

            // the first offset distance is the millWidth, after that we adjust by
            float incrementalDistance = (millWidth * overlapScaleFactor) * isoPlotPointsPerAppUnit;

            coLine = new GCodeCmd_Comment("... start ...");
            this.AddLine(coLine);

            // figure out the new corner coordinates - compensating for milling
            // bit diameter
            lXCutCoord = (lX + (millWidth / 2)) * isoPlotPointsPerAppUnit;
            lYCutCoord = (lY + (millWidth / 2)) * isoPlotPointsPerAppUnit;
            hXCutCoord = (hX - (millWidth / 2)) * isoPlotPointsPerAppUnit;
            hYCutCoord = (hY - (millWidth / 2)) * isoPlotPointsPerAppUnit;

            // G00 rapid move tool head to the destX,destY
            rmLine = new GCodeCmd_RapidMove((int)hXCutCoord, (int)hYCutCoord);
            this.AddLine(rmLine);

            // G01 - put the bit into the work piece
            zLine = new GCodeCmd_ZMove(GCodeCmd_ZMove.GCodeZMoveHeightEnum.GCodeZMoveHeight_ZCoordForCut);
            zLine.WantLinearMove = true;
            this.AddLine(zLine);

            // do the vertical down leg
            gcLine = new GCodeCmd_Line((int)hXCutCoord, (int)hYCutCoord, (int)hXCutCoord, (int)lYCutCoord);
            this.AddLine(gcLine);

            // do the low horizontal leg
            gcLine = new GCodeCmd_Line((int)hXCutCoord, (int)lYCutCoord, (int)lXCutCoord, (int)lYCutCoord);
            this.AddLine(gcLine);

            // do the vertical up leg
            gcLine = new GCodeCmd_Line((int)lXCutCoord, (int)lYCutCoord, (int)lXCutCoord, (int)hYCutCoord);
            this.AddLine(gcLine);

            // do the high horizontal leg
            gcLine = new GCodeCmd_Line((int)lXCutCoord, (int)hYCutCoord, (int)hXCutCoord, (int)hYCutCoord);
            this.AddLine(gcLine);
            lastXCoord = hXCutCoord;
            lastYCoord = hYCutCoord;

            // now do the rest of the pocket passes. This is encoded as a for loop
            // because I do not like endless loops. MAX_POCKETING_PASSES should be
            // pretty high so that it is not reached unless the finish tests fail
            for (i = 0; i < MAX_POCKETING_PASSES; i++)
            {
                // figure out the new corner coordinates - compensating for milling
                // bit diameter
                lXCutCoord = lXCutCoord + incrementalDistance;
                lYCutCoord = lYCutCoord + incrementalDistance;
                hXCutCoord = hXCutCoord - incrementalDistance;
                hYCutCoord = hYCutCoord - incrementalDistance;

                // perform tests
                if ((lXCutCoord >= centerX) || (lYCutCoord >= centerY) || (hXCutCoord <= centerX) || (hYCutCoord <= centerY))
                {
                    // we are on the last cut - just figure out which is the longer dimension
                    // and run a single cut down that
                    if ((lX - lY) > (hX - hY))
                    {
                        // we have to move to the new start position
                        gcLine = new GCodeCmd_Line((int)lastXCoord, (int)lastYCoord, (int)hXCutCoord, (int)lYCutCoord);
                        this.AddLine(gcLine);
                        // vertical is the longer dimension, hold X constant, run down Y
                        gcLine = new GCodeCmd_Line((int)hXCutCoord, (int)hYCutCoord, (int)hXCutCoord, (int)lYCutCoord);
                        this.AddLine(gcLine);
                        lastXCoord = hXCutCoord;
                        lastYCoord = hYCutCoord;
                    }
                    else
                    {
                        // we have to move to the new start position
                        gcLine = new GCodeCmd_Line((int)lastXCoord, (int)lastYCoord, (int)hXCutCoord, (int)hYCutCoord);
                        this.AddLine(gcLine);
                        // horizontal is the longer dimension, hold Y constant, run down X
                        gcLine = new GCodeCmd_Line((int)hXCutCoord, (int)hYCutCoord, (int)lXCutCoord, (int)hYCutCoord);
                        this.AddLine(gcLine);
                        lastXCoord = hXCutCoord;
                        lastYCoord = hYCutCoord;
                    }
                    // leave now
                    break;
                }

                coLine = new GCodeCmd_Comment("... pass ...");
                this.AddLine(coLine);

                // we have to move to the new start position
                gcLine = new GCodeCmd_Line((int)lastXCoord, (int)lastYCoord, (int)hXCutCoord, (int)hYCutCoord);
                this.AddLine(gcLine);

                // do the vertical down leg, this will also move it to (hXCutCoord, hYCutCoord)
                gcLine = new GCodeCmd_Line((int)hXCutCoord, (int)hYCutCoord, (int)hXCutCoord, (int)lYCutCoord);
                this.AddLine(gcLine);

                // do the low horizontal leg
                gcLine = new GCodeCmd_Line((int)hXCutCoord, (int)lYCutCoord, (int)lXCutCoord, (int)lYCutCoord);
                this.AddLine(gcLine);

                // do the vertical up leg
                gcLine = new GCodeCmd_Line((int)lXCutCoord, (int)lYCutCoord, (int)lXCutCoord, (int)hYCutCoord);
                this.AddLine(gcLine);

                // do the high horizontal leg
                gcLine = new GCodeCmd_Line((int)lXCutCoord, (int)hYCutCoord, (int)hXCutCoord, (int)hYCutCoord);
                this.AddLine(gcLine);
                lastXCoord = hXCutCoord;
                lastYCoord = hYCutCoord;
            }

            // one last test
            if (i >= MAX_POCKETING_PASSES)
            {
                LogMessage("GeneratePocketGCode: The the maximum number of pocketing passes was reached.");
                errStr = "The the maximum number of pocketing passes was reached. The gcode file is not correct. Please see the logs.";
                return(1036);
            }
            coLine = new GCodeCmd_Comment("... end ...");
            this.AddLine(coLine);

            return(0);
        }