Ejemplo n.º 1
0
 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
 /// <summary>
 /// Performs the action the plot GCode code action required based on the current context
 /// </summary>
 /// <param name="graphicsObj">a graphics object on which to plot</param>
 /// <param name="stateMachine">the ggcode plot state machine</param>
 /// <param name="errorString">the error string we return on fail</param>
 /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
 /// <param name="wantEndPointMarkers">if true we draw the endpoints of the gcodes
 /// in a different color</param>
 /// <returns>z success, nz fail</returns>
 public virtual PlotActionEnum PerformPlotGCodeAction(Graphics graphicsObj, GCodeFileStateMachine stateMachine, bool wantEndPointMarkers, ref int errorValue, ref string errorString)
 {
     // ignore this
     errorValue  = 0;
     errorString = "";
     return(PlotActionEnum.PlotAction_Continue);
 }
Ejemplo n.º 2
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// We cannot always accept the number of tabs that have been applied. This
        /// tests this here
        /// </summary>
        /// <returns>list of GCodeCmd objects or null for fail</returns>
        public int CalcAdjustedNumberOfTabs(GCodeFileStateMachine stateMachine)
        {
            int adjustedNumTabs;

            // calc the length of a tab in isoplot units
            float TabLenInIsoPlotUnits = TabLength * stateMachine.IsoPlotPointsPerAppUnit;

            // figure out our adjusted number of tabs
            adjustedNumTabs = 0;
            if (NumberOfTabs <= 0)
            {
                adjustedNumTabs = 0;
            }
            else
            {
                float accumulatedTabLen = 0;
                float halfSegLen        = this.CalcIsoSegmentLength(stateMachine) / 2;
                // add our Number of tabs in ensuring the total sum of the
                // tab lengths is not greater than half the total length
                for (int i = 0; i < NumberOfTabs; i++)
                {
                    accumulatedTabLen += TabLenInIsoPlotUnits;
                    if (accumulatedTabLen >= halfSegLen)
                    {
                        break;
                    }
                    // we can safely add this tab
                    adjustedNumTabs++;
                }
            }
            return(adjustedNumTabs);
        }
Ejemplo n.º 3
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// The coords in the GCodeCmds are stored in isoPlot format (ints) this
        /// makes it simple to plot it. The output GCode file needs real world
        /// coordinates such as that used in the Gerber file. This proc performs
        /// the conversion.
        ///
        /// This one is for the X coordinate since the X offset can differ from Y
        ///
        /// </summary>
        /// <param name="stateMachine">the statemachine</param>
        /// <param name="xCoordToConvert">the coord to convert</param>
        public float ConvertIsoPlotCoordToGCodeOutputCoord_X(GCodeFileStateMachine stateMachine, int xCoordToConvert)
        {
            // basically we divide by the isoPlot scaling to get plot values. Note that the xCoordToConvert
            // will have been shifed so that all values are non negative. This puts the origin in the lower left
            // hand corner. If the user wanted the GCode output to be defined relative to the center of the plot
            // we must SUBTRACT it from the value here
            float interimX = (xCoordToConvert / stateMachine.IsoPlotPointsPerAppUnit) - stateMachine.GCodeOutputPlotOriginAdjust_X + (stateMachine.AbsoluteOffset_X / stateMachine.IsoPlotPointsPerAppUnit);

            // are we mirroring around a veritical axis?
            if (stateMachine.MirrorOnConversionToGCode == IsoFlipModeEnum.X_Flip)
            {
                interimX = (interimX * -1);
                // if we are not offsetting the X origin this means the origin must be at 0,0. After mirroring our
                // origin will be at 0,0 but all the coords will be negative from that. This effectively makes the gcode
                // start point in the lower right corner. If we at 2x the X center point adjust we can put it all back
                // properly
                if (stateMachine.GCodeOutputPlotOriginAdjust_X == 0)
                {
                    // note stateMachine.GCodeOutputPlotOriginAdjust_X and stateMachine.GCodeMirrorAxisPlotCoord_X are both
                    // the mid points of the gcode plot
                    interimX = interimX + (2 * stateMachine.GCodeMirrorAxisPlotCoord_X);
                }
            }

            return(interimX);
        }
Ejemplo n.º 4
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the gcode plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <param name="wantEndPointMarkers">if true we draw the endpoints of the gcodes
        /// in a different color</param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override PlotActionEnum PerformPlotGCodeAction(Graphics graphicsObj, GCodeFileStateMachine stateMachine, bool wantEndPointMarkers, ref int errorValue, ref string errorString)
        {
            Brush workingBrush = null;

            if (stateMachine == null)
            {
                errorValue  = 999;
                errorString = "PerformPlotGCodeAction (Line) stateMachine == null";
                return(PlotActionEnum.PlotAction_FailWithError);
            }

            // we only plot this on cuts or touchdowns
            if (((zMoveHeight == GCodeZMoveHeightEnum.GCodeZMoveHeight_ZCoordForCut) ||
                 (zMoveHeight == GCodeZMoveHeightEnum.GCodeZMoveHeight_ZCoordForAlt1Cut)) == false)
            {
                return(PlotActionEnum.PlotAction_Continue);
            }
            // if the drill width <=0 we do not plot
            if (drillDiameter <= 0)
            {
                return(PlotActionEnum.PlotAction_Continue);
            }

            // get the brush
            workingBrush = stateMachine.PlotBorderBrush;

            // now draw in a circle of appropriate diameter
            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x0, y0, drillDiameter, drillDiameter);

            return(PlotActionEnum.PlotAction_Continue);
        }
Ejemplo n.º 5
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the GCode lines for this object as they would be written to the text file. Will
        /// never return a null value. Can often return more than one line if the
        /// current context in the stateMachine requires it
        /// </summary>
        /// <param name="stateMachine">the stateMachine</param>
        public override string GetGCodeCmd(GCodeFileStateMachine stateMachine)
        {
            StringBuilder sb            = new StringBuilder();
            float         zCoordForMove = -1;

            if (stateMachine == null)
            {
                LogMessage("GetGCodeCmd: stateMachine == null");
                return("M5 ERROR: stateMachine==null");
            }

            // set the height we wish to move at
            if (ZMoveHeight == GCodeZMoveHeightEnum.GCodeZMoveHeight_ZCoordForClear)
            {
                zCoordForMove = stateMachine.ZCoordForClear;
            }
            else if (ZMoveHeight == GCodeZMoveHeightEnum.GCodeZMoveHeight_ZCoordForCut)
            {
                zCoordForMove = stateMachine.ZCoordForCut;
            }
            else if (ZMoveHeight == GCodeZMoveHeightEnum.GCodeZMoveHeight_ZCoordForAlt1Cut)
            {
                zCoordForMove = stateMachine.ZCoordForAlt1Cut;
            }
            else
            {
                zCoordForMove = stateMachine.ZCoordForMove;
            }

            // set z axis depth now - we always write it out
            if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
            {
                sb.Append(stateMachine.BuildNextLineNumberString() + " ");
            }
            if (wantLinearMove == true)
            {
                sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_ZAXIS + zCoordForMove.ToString());
                stateMachine.LastGCodeZCoord = zCoordForMove;
                // do we need to adjust the feedrate?
                if (stateMachine.LastFeedRate != stateMachine.CurrentZFeedrate)
                {
                    // yes we do
                    sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentZFeedrate.ToString());
                    // remember this now
                    stateMachine.LastFeedRate = stateMachine.CurrentZFeedrate;
                }
            }
            else
            {
                sb.Append(GCODEWORD_MOVERAPID + " " + GCODEWORD_ZAXIS + zCoordForMove.ToString());
                stateMachine.LastGCodeZCoord = zCoordForMove;
                // no feedrates on MOVERAPID, these are set by the machine controller
            }

            sb.Append(stateMachine.LineTerminator);
            return(sb.ToString());
        }
Ejemplo n.º 6
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// The coords in the GCodeCmds are stored in isoPlot format (ints) this
        /// makes it simple to plot it. The output GCode file needs real world
        /// coordinates such as that used in the Gerber file. This proc performs
        /// the conversion.
        ///
        /// This one is for the Y coordinate since the X offset can differ from Y
        ///
        /// </summary>
        /// <param name="stateMachine">the statemachine</param>
        /// <param name="yCoordToConvert">the coord to convert</param>
        public float ConvertIsoPlotCoordToGCodeOutputCoord_Y(GCodeFileStateMachine stateMachine, int yCoordToConvert)
        {
            // basically we divide by the isoPlot scaling to get plot values. Note that the xCoordToConvert
            // will have been shifed so that all values are non negative. This puts the origin in the lower left
            // hand corner. If the user wanted the GCode output to be defined relative to the center of the plot
            // we must SUBTRACT it from the value here
            float interimY = (yCoordToConvert / stateMachine.IsoPlotPointsPerAppUnit) - stateMachine.GCodeOutputPlotOriginAdjust_Y + (stateMachine.AbsoluteOffset_Y / stateMachine.IsoPlotPointsPerAppUnit);

            return(interimY);
        }
Ejemplo n.º 7
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the GCode lines for this object as they would be written to the text file. Will
        /// never return a null value. Can often return more than one line if the
        /// current context in the stateMachine requires it
        /// </summary>
        /// <param name="stateMachine">the stateMachine</param>
        public override string GetGCodeCmd(GCodeFileStateMachine stateMachine)
        {
            StringBuilder sb = new StringBuilder();

            float zCoordForMove = -1;

            if (stateMachine == null)
            {
                LogMessage("GetGCodeCmd: stateMachine == null");
                return("M5 ERROR: stateMachine==null");
            }

            // set the height we wish to move at
            if (RapidMoveHeight == GCodeRapidMoveHeightEnum.GCodeRapidMoveHeight_ZCoordForClear)
            {
                zCoordForMove = stateMachine.ZCoordForClear;
            }
            else
            {
                zCoordForMove = stateMachine.ZCoordForMove;
            }

            // Is our Z Axis correctly set?
            if (Math.Round(stateMachine.LastGCodeZCoord, 3) != Math.Round(zCoordForMove, 3))
            {
                // no it is not, send it to the move depth
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                sb.Append(GCODEWORD_MOVERAPID + " " + GCODEWORD_ZAXIS + zCoordForMove.ToString());
                stateMachine.LastGCodeZCoord = zCoordForMove;
                sb.Append(stateMachine.LineTerminator);
            }

            float gX0OffsetCompensated_Raw = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_X(stateMachine, x0), 3);
            float gY0OffsetCompensated_Raw = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_Y(stateMachine, y0), 3);

            float gX0OffsetCompensated_Rounded = (float)Math.Round(gX0OffsetCompensated_Raw, 3);
            float gY0OffsetCompensated_Rounded = (float)Math.Round(gY0OffsetCompensated_Raw, 3);


            // Now move quickly to the start, we know our Z is now ok and above the pcb
            if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
            {
                sb.Append(stateMachine.BuildNextLineNumberString() + " ");
            }
            sb.Append(GCODEWORD_MOVERAPID + " " + GCODEWORD_XAXIS + gX0OffsetCompensated_Rounded.ToString() + " " + GCODEWORD_YAXIS + gY0OffsetCompensated_Rounded.ToString());

            stateMachine.LastGCodeXCoord = gX0OffsetCompensated_Rounded;
            stateMachine.LastGCodeYCoord = gY0OffsetCompensated_Rounded;
            sb.Append(stateMachine.LineTerminator);

            return(sb.ToString());
        }
Ejemplo n.º 8
0
 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
 /// <summary>
 /// Gets the GCode line as it would be written to the text file. Will
 /// never return a null value
 /// </summary>
 /// <param name="stateMachine">the stateMachine</param>
 public override string GetGCodeCmd(GCodeFileStateMachine stateMachine)
 {
     if (stateMachine == null)
     {
         LogMessage("GetGCodeCmd: stateMachine == null");
         return("M5 ERROR: stateMachine==null");
     }
     if (CommentIsPresent == true)
     {
         return(GCODEWORD_COMMENTOPEN + CommentText + GCODEWORD_COMMENTCLOSE + stateMachine.LineTerminator);
     }
     else
     {
         return(stateMachine.LineTerminator);
     }
 }
Ejemplo n.º 9
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the GCode line as it would be written to the text file. Will
        /// never return a null value
        /// </summary>
        /// <param name="stateMachine">the stateMachine</param>
        public override string GetGCodeCmd(GCodeFileStateMachine stateMachine)
        {
            if (stateMachine == null)
            {
                LogMessage("GetGCodeCmd: stateMachine == null");
                return("T ERROR: stateMachine==null");
            }

            StringBuilder sb = new StringBuilder();

            // for a tool change we must stop the spindle or EMC emits a really
            // odd "cannot change tools with cutter radius compensation" error
            if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
            {
                sb.Append(stateMachine.BuildNextLineNumberString() + " ");
            }
            sb.Append(GCODEWORD_SPINDLESTOP);
            sb.Append(stateMachine.LineTerminator);

            if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
            {
                sb.Append(stateMachine.BuildNextLineNumberString() + " ");
            }
            sb.Append(GCODEWORD_TOOLSELECT + toolNumber.ToString());
            if (CommentIsPresent == true)
            {
                sb.Append(" " + GCODEWORD_COMMENTOPEN + CommentText + GCODEWORD_COMMENTCLOSE);
            }
            sb.Append(stateMachine.LineTerminator);

            // now force the tool change
            if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
            {
                sb.Append(stateMachine.BuildNextLineNumberString() + " ");
            }
            sb.Append(GCODEWORD_TOOLCHANGE);
            sb.Append(stateMachine.LineTerminator);

            if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
            {
                sb.Append(stateMachine.BuildNextLineNumberString() + " ");
            }
            sb.Append(GCODEWORD_SPINDLESTART_CW);
            sb.Append(stateMachine.LineTerminator);

            return(sb.ToString());
        }
Ejemplo n.º 10
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the length of the isoplot segment (in application units)
        /// </summary>
        public float CalcIsoSegmentLength(GCodeFileStateMachine stateMachine)
        {
            float fX0;
            float fY0;
            float fX1;
            float fY1;

            if (stateMachine == null)
            {
                return(0);
            }
            fX0 = ((float)X0);
            fY0 = ((float)Y0);
            fX1 = ((float)X1);
            fY1 = ((float)Y1);
            isoSegmentLength = (float)Math.Sqrt(((fX1 - fX0) * (fX1 - fX0)) + ((fY1 - fY0) * (fY1 - fY0)));
            return(isoSegmentLength);
        }
Ejemplo n.º 11
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the gcode plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <param name="wantEndPointMarkers">if true we draw the endpoints of the gcodes
        /// in a different color</param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override PlotActionEnum PerformPlotGCodeAction(Graphics graphicsObj, GCodeFileStateMachine stateMachine, bool wantEndPointMarkers, ref int errorValue, ref string errorString)
        {
            Pen   workingPen   = null;
            Brush workingBrush = null;

            if (stateMachine == null)
            {
                errorValue  = 999;
                errorString = "PerformPlotGCodeAction (Line) stateMachine == null";
                return(PlotActionEnum.PlotAction_FailWithError);
            }

            if (DoNotEmitToGCode == true)
            {
                return(PlotActionEnum.PlotAction_Continue);
            }

            // GetPen, it will have been set up to have the proper width and color
            workingPen   = stateMachine.PlotBorderPen;
            workingBrush = stateMachine.PlotBorderBrush;

            //DebugTODO("remove this");
            //if (DebugID == 3) workingPen = Pens.Red;
            //if (DebugID == 1) workingPen = Pens.Green;
            //if (DebugID == 6) workingPen = Pens.Blue;
            //if (DebugID == 4) workingPen = Pens.DarkOrange;

            //if (DebugID != 3)
            //{
            //    return PlotActionEnum.PlotAction_Continue;
            //}

            // Draw the line
            graphicsObj.DrawLine(workingPen, x0, y0, x1, y1);
            // now draw in the circular end points of the line
            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x0, y0, workingPen.Width, workingPen.Width);
            MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, x1, y1, workingPen.Width, workingPen.Width);

            return(PlotActionEnum.PlotAction_Continue);
        }
Ejemplo n.º 12
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the GCode line as it would be written to the text file. Will
        /// never return a null value
        /// </summary>
        /// <param name="stateMachine">the stateMachine</param>
        public override string GetGCodeCmd(GCodeFileStateMachine stateMachine)
        {
            if (stateMachine == null)
            {
                LogMessage("GetGCodeCmd: stateMachine == null");
                return("M5 ERROR: stateMachine==null");
            }

            StringBuilder sb = new StringBuilder();

            if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
            {
                sb.Append(stateMachine.BuildNextLineNumberString() + " ");
            }
            sb.Append(CommandWord);
            if (CommentIsPresent == true)
            {
                sb.Append(" " + GCODEWORD_COMMENTOPEN + CommentText + GCODEWORD_COMMENTCLOSE);
            }
            sb.Append(stateMachine.LineTerminator);
            return(sb.ToString());
        }
Ejemplo n.º 13
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the GCode lines for this object as they would be written to the text file. Will
        /// never return a null value. Can often return more than one line if the
        /// current context in the stateMachine requires it
        /// </summary>
        /// <param name="stateMachine">the stateMachine</param>
        public override string GetGCodeCmd(GCodeFileStateMachine stateMachine)
        {
            StringBuilder sb = new StringBuilder();

            if (stateMachine == null)
            {
                LogMessage("GetGCodeCmd: stateMachine == null");
                return("M5 ERROR: stateMachine==null");
            }

            // calc some values
            float gX0OffsetCompensated_Raw     = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_X(stateMachine, X0), 3);
            float gX0OffsetCompensated_Rounded = (float)Math.Round(gX0OffsetCompensated_Raw, 3);

            float gY0OffsetCompensated_Raw     = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_Y(stateMachine, Y0), 3);
            float gY0OffsetCompensated_Rounded = (float)Math.Round(gY0OffsetCompensated_Raw, 3);

            // do we want line numbers
            if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
            {
                sb.Append(stateMachine.BuildNextLineNumberString() + " ");
            }
            // Now set the start position
            sb.Append(GCODEWORD_SETPOSITION + " ");
            sb.Append(GCODEWORD_XAXIS + gX0OffsetCompensated_Rounded.ToString() + " ");
            sb.Append(GCODEWORD_YAXIS + gY0OffsetCompensated_Rounded.ToString());
            if (CommentIsPresent == true)
            {
                sb.Append(" " + GCODEWORD_COMMENTOPEN + CommentText + GCODEWORD_COMMENTCLOSE);
            }
            sb.Append(stateMachine.LineTerminator);

            stateMachine.LastGCodeXCoord = gX0OffsetCompensated_Rounded;
            stateMachine.LastGCodeYCoord = gY0OffsetCompensated_Rounded;

            return(sb.ToString());
        }
Ejemplo n.º 14
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Converts the contents of the isoPlotSegment to an appropriate sequence of GCodeCmd objects
        /// </summary>
        /// <returns>list of GCodeCmd objects or null for fail</returns>
        public override List <GCodeCmd> GetGCodeCmds(GCodeFileStateMachine stateMachine)
        {
            GCodeCmd_Arc arcObj = null;

            List <GCodeCmd> retList = new List <GCodeCmd>();

            // build the arc now
            if (ReverseOnConversionToGCode == true)
            {
                // NOTE we use the chainedStart_X as point x1,y1 here.
                arcObj = new GCodeCmd_Arc(x0, y0, ChainedStart_X, ChainedStart_Y, xCenter, yCenter, radius, wantClockWise, isMultiQuadrantArc, this.PointsAddedCount, this.DebugID);
                arcObj.ReverseOnConversionToGCode = true;
            }
            else
            {
                // NOTE we use the chainedStart_X as point x0,y0 here.
                arcObj = new GCodeCmd_Arc(ChainedStart_X, ChainedStart_Y, x1, y1, xCenter, yCenter, radius, wantClockWise, isMultiQuadrantArc, this.PointsAddedCount, this.DebugID);
                arcObj.ReverseOnConversionToGCode = false;
            }
            arcObj.DoNotEmitToGCode = DoNotEmitToGCode;
            // return it
            retList.Add(arcObj);
            return(retList);
        }
Ejemplo n.º 15
0
 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
 /// <summary>
 /// Completely resets this class
 /// </summary>
 public void Reset()
 {
     stateMachine = new GCodeFileStateMachine();
     SourceLines  = new List <GCodeCmd>();
 }
Ejemplo n.º 16
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the GCode lines for this object as they would be written to the text file. Will
        /// never return a null value. Can often return more than one line if the
        /// current context in the stateMachine requires it
        /// </summary>
        /// <param name="stateMachine">the stateMachine</param>
        public override string GetGCodeCmd(GCodeFileStateMachine stateMachine)
        {
            StringBuilder sb = new StringBuilder();

            if (stateMachine == null)
            {
                LogMessage("GetGCodeCmd: stateMachine == null");
                return("M5 ERROR: stateMachine==null");
            }

            if (DoNotEmitToGCode == true)
            {
                return(sb.ToString());
            }

            float gX0OffsetCompensated_Raw = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_X(stateMachine, x0), 3);
            float gY0OffsetCompensated_Raw = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_Y(stateMachine, y0), 3);
            float gX1OffsetCompensated_Raw = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_X(stateMachine, x1), 3);
            float gY1OffsetCompensated_Raw = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_Y(stateMachine, y1), 3);

            float gX0OffsetCompensated_Rounded = (float)Math.Round(gX0OffsetCompensated_Raw, 3);
            float gY0OffsetCompensated_Rounded = (float)Math.Round(gY0OffsetCompensated_Raw, 3);
            float gX1OffsetCompensated_Rounded = (float)Math.Round(gX1OffsetCompensated_Raw, 3);
            float gY1OffsetCompensated_Rounded = (float)Math.Round(gY1OffsetCompensated_Raw, 3);

            // are we drawing this value in reverse?
            if (this.ReverseOnConversionToGCode == true)
            {
                float tmpX = gX0OffsetCompensated_Rounded;
                float tmpY = gY0OffsetCompensated_Rounded;
                gX0OffsetCompensated_Rounded = gX1OffsetCompensated_Rounded;
                gY0OffsetCompensated_Rounded = gY1OffsetCompensated_Rounded;
                gX1OffsetCompensated_Rounded = tmpX;
                gY1OffsetCompensated_Rounded = tmpY;
            }

            float gXLastGCodeCoord_Rounded = (float)Math.Round(stateMachine.LastGCodeXCoord, 3);
            float gYLastGCodeCoord_Rounded = (float)Math.Round(stateMachine.LastGCodeYCoord, 3);

            // are we currently on our start coord?
            if ((gX0OffsetCompensated_Rounded == gXLastGCodeCoord_Rounded) && (gY0OffsetCompensated_Rounded == gYLastGCodeCoord_Rounded))
            {
                // yes we are, we do not need to move the tool head there. Is our Z Axis correctly set?
                if (Math.Round(stateMachine.LastGCodeZCoord, 3) != Math.Round(stateMachine.ZCoordForCut, 3))
                {
                    // no it is not, send it down to to the CUT depth
                    if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                    {
                        sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                    }
                    sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_ZAXIS + stateMachine.ZCoordForCut.ToString());
                    stateMachine.LastGCodeZCoord = stateMachine.ZCoordForCut;
                    // do we need to adjust the feedrate?
                    if (stateMachine.LastFeedRate != stateMachine.CurrentZFeedrate)
                    {
                        // yes we do
                        sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentZFeedrate.ToString());
                        // remember this now
                        stateMachine.LastFeedRate = stateMachine.CurrentZFeedrate;
                    }
                    sb.Append(stateMachine.LineTerminator);
                }

                // now move the tool head, cutting as we go
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_XAXIS + gX1OffsetCompensated_Rounded.ToString() + " " + GCODEWORD_YAXIS + gY1OffsetCompensated_Rounded.ToString());
                stateMachine.LastGCodeXCoord = gX1OffsetCompensated_Rounded;
                stateMachine.LastGCodeYCoord = gY1OffsetCompensated_Rounded;
                // do we need to adjust the feedrate?
                if (stateMachine.LastFeedRate != stateMachine.CurrentXYFeedrate)
                {
                    // yes we do
                    sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentXYFeedrate.ToString());
                    // remember this now
                    stateMachine.LastFeedRate = stateMachine.CurrentXYFeedrate;
                }
                sb.Append(stateMachine.LineTerminator);
            }
            else
            {
                // no, we are not on the start coord. Is our Z Axis correctly set?
                if ((((Math.Round(stateMachine.LastGCodeZCoord, 3) == Math.Round(stateMachine.ZCoordForMove, 3)) || (Math.Round(stateMachine.LastGCodeZCoord, 3) == Math.Round(stateMachine.ZCoordForClear, 3)))) == false)
                {
                    // no it is not, pull it up to the MOVE distance
                    if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                    {
                        sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                    }
                    sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_ZAXIS + stateMachine.ZCoordForMove.ToString());
                    stateMachine.LastGCodeZCoord = stateMachine.ZCoordForMove;
                    // do we need to adjust the feedrate?
                    if (stateMachine.LastFeedRate != stateMachine.CurrentZFeedrate)
                    {
                        // yes we do
                        sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentZFeedrate.ToString());
                        // remember this now
                        stateMachine.LastFeedRate = stateMachine.CurrentZFeedrate;
                    }
                    sb.Append(stateMachine.LineTerminator);
                }

                // Now move quickly to the start, we know our Z is now be ok and above the pcb
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                sb.Append(GCODEWORD_MOVERAPID + " " + GCODEWORD_XAXIS + gX0OffsetCompensated_Rounded.ToString() + " " + GCODEWORD_YAXIS + gY0OffsetCompensated_Rounded.ToString());
                stateMachine.LastGCodeXCoord = gX0OffsetCompensated_Rounded;
                stateMachine.LastGCodeYCoord = gY0OffsetCompensated_Rounded;
                sb.Append(stateMachine.LineTerminator);

                // now put our Z down to the cut depth
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_ZAXIS + stateMachine.ZCoordForCut.ToString());
                stateMachine.LastGCodeZCoord = stateMachine.ZCoordForCut;
                // do we need to adjust the feedrate?
                if (stateMachine.LastFeedRate != stateMachine.CurrentZFeedrate)
                {
                    // yes we do
                    sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentZFeedrate.ToString());
                    // remember this now
                    stateMachine.LastFeedRate = stateMachine.CurrentZFeedrate;
                }
                sb.Append(stateMachine.LineTerminator);

                // now move to the end of the line, cutting as we go
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_XAXIS + gX1OffsetCompensated_Rounded.ToString() + " " + GCODEWORD_YAXIS + gY1OffsetCompensated_Rounded.ToString());
                stateMachine.LastGCodeXCoord = gX1OffsetCompensated_Rounded;
                stateMachine.LastGCodeYCoord = gY1OffsetCompensated_Rounded;
                // do we need to adjust the feedrate?
                if (stateMachine.LastFeedRate != stateMachine.CurrentXYFeedrate)
                {
                    // yes we do
                    sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentXYFeedrate.ToString());
                    // remember this now
                    stateMachine.LastFeedRate = stateMachine.CurrentXYFeedrate;
                }
                sb.Append(stateMachine.LineTerminator);
            }
            //DebugTODO("for diagnostics only");
            //sb.Append(stateMachine.LineTerminator);
            return(sb.ToString());
        }
Ejemplo n.º 17
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);
        }
Ejemplo n.º 18
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 abstract List <GCodeCmd> GetGCodeCmds(GCodeFileStateMachine stateMachine);
Ejemplo n.º 19
0
 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
 /// <summary>
 /// Gets the GCode line as it would be written to the text file. Will
 /// never return a null value
 /// </summary>
 /// <param name="stateMachine">the statemachine string</param>
 public abstract string GetGCodeCmd(GCodeFileStateMachine stateMachine);
Ejemplo n.º 20
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the GCode lines for this object as they would be written to the text file. Will
        /// never return a null value. Can often return more than one line if the
        /// current context in the stateMachine requires it
        /// </summary>
        /// <param name="stateMachine">the stateMachine</param>
        public override string GetGCodeCmd(GCodeFileStateMachine stateMachine)
        {
            StringBuilder sb = new StringBuilder();

            string gcodeWordArcDirection = GCodeCmd.GCODEWORD_MOVEINCIRCLECCW;
            float  xCenterOffset         = -1;
            float  yCenterOffset         = -1;
            double radius;
            double theta;
            float  xTrueEndPoint;
            float  yTrueEndPoint;
            float  xEndDistance;
            float  yEndDistance;

            if (stateMachine == null)
            {
                LogMessage("GetGCodeCmd: stateMachine == null");
                return("M5 ERROR: stateMachine==null");
            }

            if (DoNotEmitToGCode == true)
            {
                return(sb.ToString());
            }

            // set our arc direction code word
            if (arcDirection == GCodeCmd_ArcDirectionEnum.GCodeArcDirection_CCW)
            {
                gcodeWordArcDirection = GCodeCmd.GCODEWORD_MOVEINCIRCLECCW;
            }
            else
            {
                gcodeWordArcDirection = GCodeCmd.GCODEWORD_MOVEINCIRCLECW;
            }

            // we need to reverse the direction if we are flipping
            if (stateMachine.MirrorOnConversionToGCode == IsoFlipModeEnum.X_Flip)
            {
                gcodeWordArcDirection = GetReversedArcDirection(gcodeWordArcDirection);
            }

            float gX0OffsetCompensated_Raw      = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_X(stateMachine, x0), 3);
            float gY0OffsetCompensated_Raw      = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_Y(stateMachine, y0), 3);
            float gX1OffsetCompensated_Raw      = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_X(stateMachine, x1), 3);
            float gY1OffsetCompensated_Raw      = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_Y(stateMachine, y1), 3);
            float gXCenterOffsetCompensated_Raw = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_X(stateMachine, xCenter), 3);
            float gYCenterOffsetCompensated_Raw = (float)Math.Round(ConvertIsoPlotCoordToGCodeOutputCoord_Y(stateMachine, yCenter), 3);

            float gX0OffsetCompensated_Rounded = (float)Math.Round(gX0OffsetCompensated_Raw, 3);
            float gY0OffsetCompensated_Rounded = (float)Math.Round(gY0OffsetCompensated_Raw, 3);
            float gX1OffsetCompensated_Rounded = (float)Math.Round(gX1OffsetCompensated_Raw, 3);
            float gY1OffsetCompensated_Rounded = (float)Math.Round(gY1OffsetCompensated_Raw, 3);

            // are we drawing this value in reverse?
            if (this.ReverseOnConversionToGCode == true)
            {
                float tmpX = gX0OffsetCompensated_Rounded;
                float tmpY = gY0OffsetCompensated_Rounded;
                gX0OffsetCompensated_Rounded = gX1OffsetCompensated_Rounded;
                gY0OffsetCompensated_Rounded = gY1OffsetCompensated_Rounded;
                gX1OffsetCompensated_Rounded = tmpX;
                gY1OffsetCompensated_Rounded = tmpY;
                // do this again
                gcodeWordArcDirection = GetReversedArcDirection(gcodeWordArcDirection);
            }


            float gXCenterOffsetCompensated_Rounded = (float)Math.Round(gXCenterOffsetCompensated_Raw, 4);
            float gYCenterOffsetCompensated_Rounded = (float)Math.Round(gYCenterOffsetCompensated_Raw, 4);

            float gXLastGCodeCoord_Rounded = (float)Math.Round(stateMachine.LastGCodeXCoord, 3);
            float gYLastGCodeCoord_Rounded = (float)Math.Round(stateMachine.LastGCodeYCoord, 3);

            // sb.Append("(ZZZZZ---->GO2Arc)");
            sb.Append(stateMachine.LineTerminator);

            // are we currently on our start coord?
            if ((gX0OffsetCompensated_Rounded == gXLastGCodeCoord_Rounded) && (gY0OffsetCompensated_Rounded == gYLastGCodeCoord_Rounded))
            {
                // yes we are, we do not need to move the tool head there. Is our Z Axis correctly set?
                if (Math.Round(stateMachine.LastGCodeZCoord, 3) != Math.Round(stateMachine.ZCoordForCut, 3))
                {
                    // no it is not, send it down to to the CUT depth
                    if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                    {
                        sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                    }
                    sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_ZAXIS + stateMachine.ZCoordForCut.ToString());
                    stateMachine.LastGCodeZCoord = stateMachine.ZCoordForCut;
                    // do we need to adjust the feedrate?
                    if (stateMachine.LastFeedRate != stateMachine.CurrentZFeedrate)
                    {
                        // yes we do
                        sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentZFeedrate.ToString());
                        // remember this now
                        stateMachine.LastFeedRate = stateMachine.CurrentZFeedrate;
                    }
                    sb.Append(stateMachine.LineTerminator);
                }

                // now move the tool head, cutting as we go
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                // we must calc our offsets to the center, the g?CenterOffsetCompensated_Rounded are actually the center coordinates
                xCenterOffset = gXCenterOffsetCompensated_Rounded - gX0OffsetCompensated_Rounded;
                yCenterOffset = gYCenterOffsetCompensated_Rounded - gY0OffsetCompensated_Rounded;

                // The way the G02,G03 commands work is they have a start point, an offset to the center
                // and the endpoint of the arc. It must be true that the endpoint of the arc is actually on
                // the arc itself. If this is not the case then most machine controllers will throw an error.

                // Given the new chain calculation method this problem does not appear to exist. If needed
                // the commented out code below tells what to do

                // assume the true endpoints are the ones we got
                xTrueEndPoint = gX1OffsetCompensated_Rounded;
                yTrueEndPoint = gY1OffsetCompensated_Rounded;

/* not operational any more, and did not work well
 *              // The endpoint error can happen due to the way we interpolate things that our endpoint is a bit off the arc
 *              // so we calculate the best endpoint actually on the arc and use that in the G02/G03 command
 *              // then we add a little compensating linear move (at the same Z position) to get us to the
 *              // point we need to end at. Usually this little "step" in the arc etc is so small it is invisible
 *
 *              // we need the radius, calculated off the start point
 *              radius = MiscGraphicsUtils.GetDistanceBetweenTwoPoints(gX0OffsetCompensated_Raw, gY0OffsetCompensated_Raw, gXCenterOffsetCompensated_Rounded, gYCenterOffsetCompensated_Rounded);
 */

                // now emit the GCode with the true endpoint
                sb.Append(gcodeWordArcDirection + " " + GCODEWORD_XAXIS + xTrueEndPoint.ToString() + " " + GCODEWORD_YAXIS + yTrueEndPoint.ToString() + " " + GCODEWORD_XARCCENTER + xCenterOffset.ToString() + " " + GCODEWORD_YARCCENTER + yCenterOffset.ToString());
                // do we need to adjust the feedrate?
                if (stateMachine.LastFeedRate != stateMachine.CurrentXYFeedrate)
                {
                    // yes we do
                    sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentXYFeedrate.ToString());
                    // remember this now
                    stateMachine.LastFeedRate = stateMachine.CurrentXYFeedrate;
                }
                sb.Append(stateMachine.LineTerminator);

                stateMachine.LastGCodeXCoord = gX1OffsetCompensated_Rounded;
                stateMachine.LastGCodeYCoord = gY1OffsetCompensated_Rounded;
            }
            else
            {
                // no, we are not on the start coord. Is our Z Axis correctly set?
                if ((((Math.Round(stateMachine.LastGCodeZCoord, 3) == Math.Round(stateMachine.ZCoordForMove, 3)) || (Math.Round(stateMachine.LastGCodeZCoord, 3) == Math.Round(stateMachine.ZCoordForClear, 3)))) == false)
                {
                    // no it is not, pull it up to the MOVE distance
                    if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                    {
                        sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                    }
                    sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_ZAXIS + stateMachine.ZCoordForMove.ToString());
                    stateMachine.LastGCodeZCoord = stateMachine.ZCoordForMove;
                    // do we need to adjust the feedrate?
                    if (stateMachine.LastFeedRate != stateMachine.CurrentZFeedrate)
                    {
                        // yes we do
                        sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentZFeedrate.ToString());
                        // remember this now
                        stateMachine.LastFeedRate = stateMachine.CurrentZFeedrate;
                    }
                    sb.Append(stateMachine.LineTerminator);
                }

                // Now move quickly to the start, we know our Z is now be ok and above the pcb
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                sb.Append(GCODEWORD_MOVERAPID + " " + GCODEWORD_XAXIS + gX0OffsetCompensated_Rounded.ToString() + " " + GCODEWORD_YAXIS + gY0OffsetCompensated_Rounded.ToString());
                stateMachine.LastGCodeXCoord = gX0OffsetCompensated_Rounded;
                stateMachine.LastGCodeYCoord = gY0OffsetCompensated_Rounded;
                sb.Append(stateMachine.LineTerminator);

                // now put our Z down to the cut depth
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_ZAXIS + stateMachine.ZCoordForCut.ToString());
                stateMachine.LastGCodeZCoord = stateMachine.ZCoordForCut;
                // do we need to adjust the feedrate?
                if (stateMachine.LastFeedRate != stateMachine.CurrentZFeedrate)
                {
                    // yes we do
                    sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentZFeedrate.ToString());
                    // remember this now
                    stateMachine.LastFeedRate = stateMachine.CurrentZFeedrate;
                }
                sb.Append(stateMachine.LineTerminator);

                // now move to the end of the arc, cutting as we go
                if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                {
                    sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                }
                // we must calc our offsets to the center
                xCenterOffset = (float)Math.Round(gXCenterOffsetCompensated_Rounded - stateMachine.LastGCodeXCoord, 4);
                yCenterOffset = (float)Math.Round(gYCenterOffsetCompensated_Rounded - stateMachine.LastGCodeYCoord, 4);

                // The way the G02,G03 commands work is they have a start point, an offset to the center
                // and the endpoint of the arc. It must be true that the endpoint of the arc is actually on
                // the arc itself. If this is not the case then most machine controllers will throw an error
                // it can happen, due to the way we interpolate things that our endpoint is a bit off the arc
                // so we calculate the best endpoint actually on the arc and use that in the G02/G03 command
                // then we add a little compensating linear move (at the same Z position) to get us to the
                // point we need to end at. Usually this little "step" in the arc etc is so small it is invisible

                // we need the radius
                radius = Math.Sqrt((xCenterOffset * xCenterOffset) + (yCenterOffset * yCenterOffset));

                // we need the xdistance and ydistances of the end point to the center
                xEndDistance = (float)Math.Round(gX1OffsetCompensated_Rounded - gXCenterOffsetCompensated_Rounded, 4);
                yEndDistance = (float)Math.Round(gY1OffsetCompensated_Rounded - gYCenterOffsetCompensated_Rounded, 4);

                if (xEndDistance != 0)
                {
                    // we need the angle
                    theta = Math.Atan2(yEndDistance, xEndDistance);
                    // calc the true end points
                    xTrueEndPoint = (float)Math.Round(gXCenterOffsetCompensated_Rounded + (radius * Math.Cos(theta)), 4);
                    yTrueEndPoint = (float)Math.Round(gYCenterOffsetCompensated_Rounded + (radius * Math.Sin(theta)), 4);
                }
                else
                {
                    // assume the true endpoints are the ones we got
                    xTrueEndPoint = gX1OffsetCompensated_Rounded;
                    yTrueEndPoint = gY1OffsetCompensated_Rounded;
                }

                // now emit the GCode with the true endpoint
                sb.Append(gcodeWordArcDirection + " " + GCODEWORD_XAXIS + xTrueEndPoint.ToString() + " " + GCODEWORD_YAXIS + yTrueEndPoint.ToString() + " " + GCODEWORD_XARCCENTER + xCenterOffset.ToString() + " " + GCODEWORD_YARCCENTER + yCenterOffset.ToString());
                // do we need to adjust the feedrate?
                if (stateMachine.LastFeedRate != stateMachine.CurrentXYFeedrate)
                {
                    // yes we do
                    sb.Append(" " + GCODEWORD_FEEDRATE + stateMachine.CurrentXYFeedrate.ToString());
                    // remember this now
                    stateMachine.LastFeedRate = stateMachine.CurrentXYFeedrate;
                }
                sb.Append(stateMachine.LineTerminator);

                // now do we need to add a little linear run so we actually end up on the
                // true XY end point
                if ((xTrueEndPoint != gX1OffsetCompensated_Rounded) || (yTrueEndPoint != gY1OffsetCompensated_Rounded))
                {
                    if (stateMachine.GCodeFileManager.ShowGCodeCmdNumbers == true)
                    {
                        sb.Append(stateMachine.BuildNextLineNumberString() + " ");
                    }
                    sb.Append(GCODEWORD_MOVEINLINE + " " + GCODEWORD_XAXIS + gX1OffsetCompensated_Rounded.ToString() + " " + GCODEWORD_YAXIS + gY1OffsetCompensated_Rounded.ToString());
                    sb.Append(stateMachine.LineTerminator);
                    //  DebugTODO("remove this line");
                    //  sb.Append("(YYYYYY---->xCenter=" + X1CenterOffsetCompensated.ToString() + " Ycenter=" + Y1CenterOffsetCompensated.ToString()+")");
                    //  sb.Append(stateMachine.LineTerminator);
                    //  sb.Append("(YYYYYY---->AutoGenerated Compensation)");
                    //  sb.Append(stateMachine.LineTerminator);
                }
                stateMachine.LastGCodeXCoord = gX1OffsetCompensated_Rounded;
                stateMachine.LastGCodeYCoord = gY1OffsetCompensated_Rounded;
            }

            //DebugTODO("for diagnostics only");
            //sb.Append(stateMachine.LineTerminator);

            return(sb.ToString());
        }
Ejemplo n.º 21
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Performs the action the plot requires based on the current context. Note
        /// that the coordinates stored in GCodeCmds in here are not in isoPlot coords.
        /// They coords are are in
        /// </summary>
        /// <param name="graphicsObj">a graphics object on which to plot</param>
        /// <param name="stateMachine">the gcode plot state machine</param>
        /// <param name="errorString">the error string we return on fail</param>
        /// <param name="errorValue">the error value we return on fail, z success, nz fail </param>
        /// <param name="wantEndPointMarkers">if true we draw the endpoints of the gcodes
        /// in a different color</param>
        /// <returns>an enum value indicating what next action to take</returns>
        public override PlotActionEnum PerformPlotGCodeAction(Graphics graphicsObj, GCodeFileStateMachine stateMachine, bool wantEndPointMarkers, ref int errorValue, ref string errorString)
        {
            Pen   workingPen   = null;
            Brush workingBrush = null;

            if (DoNotEmitToGCode == true)
            {
                return(PlotActionEnum.PlotAction_Continue);
            }

            // get the current X,Y coordinates, these will already be scaled, origin compensated and flipped
            float startXCoord = x0;
            float startYCoord = y0;

            // get the end X,Y coordinate
            float endXCoord = x1;
            float endYCoord = y1;

            // get the arc center point, by adding on the specified offsets. Note we do not involve
            // the end coords here. These are calculated off the start coords
            float arcCenterXCoord = xCenter;
            float arcCenterYCoord = yCenter;

            // get our points
            PointF startPoint  = new PointF(startXCoord, startYCoord);
            PointF endPoint    = new PointF(endXCoord, endYCoord);
            PointF centerPoint = new PointF(arcCenterXCoord, arcCenterYCoord);

            //DebugMessage("PG startPoint=" + startPoint.ToString() + ", endPoint=" + endPoint.ToString() + ", centerPoint=" + centerPoint.ToString() + ", radius=" + radius);

            // A NOTE on the direction of angles here. Gerber can specifiy clockwise or counter clockwise. .NET only wants its angles specified counter
            // clockwise when it draws. GCode can go either way. However, the arcs drawn here are segments of a larger arc (or cicle) and these are
            // built out of isoplot segments. The isoplot segment collector always goes around arcs in a counter clockwise direction. This essentially
            // converts any clockwise arcs into counter clockwise ones.

            // this means that all start points, end points and sweep angles are ALWAYS listed as CounterClockwise here even if the original gerber was
            // clockwise. This means we do not have to do any conversion for the display even if the original angle was clockwise.

            // get our start and sweep angles
            MiscGraphicsUtils.GetCounterClockwiseStartAndSweepAnglesFrom2PointsAndCenter(startPoint, endPoint, centerPoint, out float startAngleInDegrees, out float sweepAngleInDegrees);

            //DebugMessage("  PGa startAngleInDegrees=" + startAngleInDegrees.ToString() + ", sweepAngleInDegrees=" + sweepAngleInDegrees.ToString());

            // are we dealing with a sweep angle of 0 degrees?
            if (sweepAngleInDegrees == 0)
            {
                // yes, this actually may be a full circle or it may just be a tiny little arc segment with an angle so small
                // that it cannot be drawn. We can get an idea by looking at the number of isoPlotCells the arc uses. A small
                // number indicates that we are actually a circle
                if (IsoPlotCellsInObject >= ARBITRARY_MIN_NUMBER_OF_CELLS_FOR_0_DEGREE_ARC)
                {
                    sweepAngleInDegrees = 360;
                }
            }

            // GetPen, it will have been set up to have the proper width and color
            workingPen   = stateMachine.PlotBorderPen;
            workingBrush = stateMachine.PlotBorderBrush;

            // create an enclosing rectangle
            RectangleF boundingRect = new RectangleF(arcCenterXCoord - radius, arcCenterYCoord - radius, 2 * radius, 2 * radius);

            //DebugTODO("remove this");
            //if (DebugID == 23) workingPen = Pens.Red;
            //if (DebugID == 25) workingPen = Pens.Green;
            //if (DebugID == 20) workingPen = Pens.Blue;
            //if (DebugID != 9)
            //{
            //    return PlotActionEnum.PlotAction_Continue;
            //}

            // Draw arc
            graphicsObj.DrawArc(workingPen, boundingRect, startAngleInDegrees, sweepAngleInDegrees);

            // if we did not do nothing or a full circle draw these in
            if (((sweepAngleInDegrees == 0) || (sweepAngleInDegrees == 360)) == false)
            {
                // now draw in the circular end points of the line
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, startXCoord, startYCoord, workingPen.Width, workingPen.Width);
                MiscGraphicsUtils.FillEllipseCenteredOnPoint(graphicsObj, workingBrush, endXCoord, endYCoord, workingPen.Width, workingPen.Width);
            }

            return(PlotActionEnum.PlotAction_Continue);
        }