示例#1
0
        /// <summary>
        /// Traverse the instructions backwards until a movement is found,
        /// return as Point3D
        /// </summary>
        /// <param name="instructions">a list of gcode instructions</param>
        /// <returns>previous point as a Point3D or Empty</returns>
        private static Point3D GetPreviousPoint(IList <GCodeInstruction> instructions)
        {
            var prevPoint = Point3D.Empty;

            if (instructions.Count == 0)
            {
                return(prevPoint);
            }

            GCodeInstruction prevInstruction   = null;
            bool             foundLastMovement = false;
            int index = 1;

            while (!foundLastMovement)
            {
                prevInstruction = instructions[instructions.Count - index];

                if (prevInstruction.CommandType == CommandType.CWArc ||
                    prevInstruction.CommandType == CommandType.CCWArc ||
                    prevInstruction.CommandType == CommandType.NormalMove ||
                    prevInstruction.CommandType == CommandType.RapidMove)
                {
                    foundLastMovement = true;
                }

                if (index == instructions.Count)
                {
                    // warning, no previous movements found
                    break;
                }

                index++;
            }

            // merge previous coordinates with newer ones to maintain correct point coordinates
            if (prevInstruction.X.HasValue || prevInstruction.Y.HasValue || prevInstruction.Z.HasValue)
            {
                if (prevInstruction.X.HasValue)
                {
                    prevPoint.X = prevInstruction.X.Value;
                }
                if (prevInstruction.Y.HasValue)
                {
                    prevPoint.Y = prevInstruction.Y.Value;
                }
                if (prevInstruction.Z.HasValue)
                {
                    prevPoint.Z = prevInstruction.Z.Value;
                }
            }

            return(prevPoint);
        }
示例#2
0
        public bool EqualsXYZ(GCodeInstruction other)
        {
            if (other == null)
            {
                return(false);
            }

            if (X.HasValue && other.X.HasValue && X.Value == other.X.Value &&
                Y.HasValue && other.Y.HasValue && Y.Value == other.Y.Value &&
                Z.HasValue && other.Z.HasValue && Z.Value == other.Z.Value)
            {
                return(true);
            }

            return(false);
        }
示例#3
0
        /// <summary>
        /// Split a gcode file into tiles
        /// </summary>
        /// <param name="instructions">list of gcode instructions</param>
        /// <param name="splitPoint">Point3D describing the split coordinates</param>
        /// <param name="angle">Whether the split should happen in an angle</param>
        /// <param name="zClearance">z-height (clearance) to use in added rapid moves</param>
        /// <returns>List of tiles</returns>
        /// <remarks>
        /// Porteed from the G-Code_Ripper-0.14 Python App
        /// Method: def split_code(self,code2split,shift=[0,0,0],angle=0.0)
        /// </remarks>
        public static List <List <GCodeInstruction> > Split(List <GCodeInstruction> instructions, Point3D splitPoint, float angle, float zClearance)
        {
            // G0 (Rapid), G1 (linear), G2 (clockwise arc) or G3 (counterclockwise arc).
            CommandType command = CommandType.Other;

            const float xsplit = 0.0f;             // xsplit is always zero, because the whole coordinate system is shifted to origin
            var         app    = new List <List <GCodeInstruction> >();

            app.Add(new List <GCodeInstruction>());
            app.Add(new List <GCodeInstruction>());

            var flag_side = Position.None;
            int thisSide  = -1;
            int otherSide = -1;

            float currentFeedrate = 0.0f;

            var currentPos  = Point3D.Empty;                    // current position as read
            var previousPos = Point3D.Empty;                    // current position as read
            var centerPos   = Point3D.Empty;                    // center position as read

            var currentPosAtOrigin  = Point3D.Empty;            // current position, shifted
            var previousPosAtOrigin = Point3D.Empty;            // last position, shifted
            var centerPosAtOrigin   = Point3D.Empty;            // center position, shifted

            var A = Point3D.Empty;
            var B = Point3D.Empty;
            var C = Point3D.Empty;
            var D = Point3D.Empty;
            var E = Point3D.Empty;

            var cross = new List <Point3D>();                   // number of intersections found

                        #if DEBUG
            Debug.WriteLine("Split point: {0}, angle: {1} z-clearance: {2}", splitPoint, angle, zClearance);
                        #endif

            int numInstructions = 1;
            foreach (var instruction in instructions)
            {
                // store move type
                command = instruction.CommandType;

                // merge previous coordinates with newer ones to maintain correct point coordinates
                if ((instruction.X.HasValue || instruction.Y.HasValue || instruction.Z.HasValue ||
                     instruction.F.HasValue))
                {
                    if (instruction.X.HasValue && instruction.X.Value != currentPos.X)
                    {
                        currentPos.X = instruction.X.Value;
                    }
                    if (instruction.Y.HasValue && instruction.Y.Value != currentPos.Y)
                    {
                        currentPos.Y = instruction.Y.Value;
                    }
                    if (instruction.Z.HasValue && instruction.Z.Value != currentPos.Z)
                    {
                        currentPos.Z = instruction.Z.Value;
                    }
                    if (instruction.F.HasValue && instruction.F.Value != currentFeedrate)
                    {
                        currentFeedrate = instruction.F.Value;
                    }
                }

                if (command == CommandType.NormalMove ||
                    command == CommandType.CWArc ||
                    command == CommandType.CCWArc)
                {
                    // shift and rotate so that we can work with the coordinate system at origin (0, 0)
                    currentPosAtOrigin  = SetOffsetAndRotation(currentPos, splitPoint, angle);
                    previousPosAtOrigin = SetOffsetAndRotation(previousPos, splitPoint, angle);

                    // store center point
                    if (instruction.I.HasValue && instruction.J.HasValue)
                    {
                        centerPos = new Point3D(previousPos.X + instruction.I.Value,
                                                previousPos.Y + instruction.J.Value,
                                                currentPos.Z);

                        centerPosAtOrigin = SetOffsetAndRotation(centerPos, splitPoint, angle);
                    }

                    // determine what side the move belongs to
                    if (previousPosAtOrigin.X > xsplit + SELF_ZERO)
                    {
                        flag_side = Position.R;
                    }
                    else if (previousPosAtOrigin.X < xsplit - SELF_ZERO)
                    {
                        flag_side = Position.L;
                    }
                    else
                    {
                        if (command == CommandType.NormalMove)
                        {
                            if (currentPosAtOrigin.X >= xsplit)
                            {
                                flag_side = Position.R;
                            }
                            else
                            {
                                flag_side = Position.L;
                            }
                        }
                        else if (command == CommandType.CWArc)
                        {
                            if (Math.Abs(previousPosAtOrigin.Y - centerPosAtOrigin.Y) < SELF_ZERO)
                            {
                                if (centerPosAtOrigin.X > xsplit)
                                {
                                    flag_side = Position.R;
                                }
                                else
                                {
                                    flag_side = Position.L;
                                }
                            }
                            else
                            {
                                if (previousPosAtOrigin.Y >= centerPosAtOrigin.Y)
                                {
                                    flag_side = Position.R;
                                }
                                else
                                {
                                    flag_side = Position.L;
                                }
                            }
                        }
                        else                             //(mvtype == 3) {
                        {
                            if (Math.Abs(previousPosAtOrigin.Y - centerPosAtOrigin.Y) < SELF_ZERO)
                            {
                                if (centerPosAtOrigin.X > xsplit)
                                {
                                    flag_side = Position.R;
                                }
                                else
                                {
                                    flag_side = Position.L;
                                }
                            }
                            else
                            {
                                if (previousPosAtOrigin.Y >= centerPosAtOrigin.Y)
                                {
                                    flag_side = Position.L;
                                }
                                else
                                {
                                    flag_side = Position.R;
                                }
                            }
                        }
                    }

                    if (flag_side == Position.R)
                    {
                        thisSide  = 1;
                        otherSide = 0;
                    }
                    else
                    {
                        thisSide  = 0;
                        otherSide = 1;
                    }

                    // Handle normal moves
                    if (command == CommandType.NormalMove)
                    {
                        A     = UnsetOffsetAndRotation(previousPosAtOrigin, splitPoint, angle);
                        C     = UnsetOffsetAndRotation(currentPosAtOrigin, splitPoint, angle);
                        cross = GetLineIntersect(previousPosAtOrigin, currentPosAtOrigin, xsplit);

                        if (cross.Count > 0)
                        {
                            // Line crosses boundary
                            B = UnsetOffsetAndRotation(cross[0], splitPoint, angle);
                            app[thisSide].AddRange(GCodeInstruction.GetInstructions(command, A, B, currentFeedrate, splitPoint, thisSide, GetPreviousPoint(app[thisSide]), zClearance));
                            app[otherSide].AddRange(GCodeInstruction.GetInstructions(command, B, C, currentFeedrate, splitPoint, otherSide, GetPreviousPoint(app[otherSide]), zClearance));
                        }
                        else
                        {
                            // Lines doesn't intersect

                            // check if this point is the same as centerpoint
                            // if so add it to both sides
                            // TODO: check if this works in all cases?
                            if (currentPos.X == splitPoint.X)
                            {
                                app[thisSide].AddRange(GCodeInstruction.GetInstructions(command, A, C, currentFeedrate, splitPoint, thisSide, GetPreviousPoint(app[thisSide]), zClearance));
                                app[otherSide].AddRange(GCodeInstruction.GetInstructions(command, A, C, currentFeedrate, splitPoint, otherSide, GetPreviousPoint(app[otherSide]), zClearance));
                            }
                            else
                            {
                                app[thisSide].AddRange(GCodeInstruction.GetInstructions(command, A, C, currentFeedrate, splitPoint, thisSide, GetPreviousPoint(app[thisSide]), zClearance));
                            }
                        }
                    }

                    // Handle Arc moves
                    if (command == CommandType.CWArc || command == CommandType.CCWArc)
                    {
                        A     = UnsetOffsetAndRotation(previousPosAtOrigin, splitPoint, angle);
                        C     = UnsetOffsetAndRotation(currentPosAtOrigin, splitPoint, angle);
                        D     = UnsetOffsetAndRotation(centerPosAtOrigin, splitPoint, angle);
                        cross = GetArcIntersects(previousPosAtOrigin, currentPosAtOrigin, centerPosAtOrigin, xsplit, command);

                        if (cross.Count > 0)
                        {
                            // Arc crosses boundary at least once
                            B = UnsetOffsetAndRotation(cross[0], splitPoint, angle);

                            // Check length of arc before writing
                            if (Transformation.Distance(B, A) > SELF_ACCURACY)
                            {
                                app[thisSide].AddRange(GCodeInstruction.GetInstructions(command, A, B, D, currentFeedrate, splitPoint, thisSide, GetPreviousPoint(app[thisSide]), zClearance));
                            }

                            if (cross.Count == 1)                               // Arc crosses boundary only once
                            // Check length of arc before writing
                            {
                                if (Transformation.Distance(C, B) > SELF_ACCURACY)
                                {
                                    app[otherSide].AddRange(GCodeInstruction.GetInstructions(command, B, C, D, currentFeedrate, splitPoint, otherSide, GetPreviousPoint(app[otherSide]), zClearance));
                                }
                            }

                            if (cross.Count == 2)                               // Arc crosses boundary twice
                            {
                                E = UnsetOffsetAndRotation(cross[1], splitPoint, angle);

                                // Check length of arc before writing
                                if (Transformation.Distance(E, B) > SELF_ACCURACY)
                                {
                                    app[otherSide].AddRange(GCodeInstruction.GetInstructions(command, B, E, D, currentFeedrate, splitPoint, otherSide, GetPreviousPoint(app[otherSide]), zClearance));
                                }

                                // Check length of arc before writing
                                if (Transformation.Distance(C, E) > SELF_ACCURACY)
                                {
                                    app[thisSide].AddRange(GCodeInstruction.GetInstructions(command, E, C, D, currentFeedrate, splitPoint, thisSide, GetPreviousPoint(app[thisSide]), zClearance));
                                }
                            }
                        }
                        else
                        {
                            // Arc does not cross boundary
                            app[thisSide].AddRange(GCodeInstruction.GetInstructions(command, A, C, D, currentFeedrate, splitPoint, thisSide, GetPreviousPoint(app[thisSide]), zClearance));
                        }
                    }
                }
                else
                {
                    // if not any normal or arc moves, store the instruction in both lists
                    // rapid moves are also handled here
                    if (instruction.CommandType != CommandType.RapidMove)
                    {
                        app[0].Add(instruction);
                        app[1].Add(instruction);
                    }
                }

                                #if DEBUG
                if (command == CommandType.RapidMove)
                {
                    Debug.WriteLine("{0} [{1}={2}], [{3}={4}]", command, previousPos, previousPosAtOrigin, currentPos, currentPosAtOrigin);
                }
                if (command == CommandType.NormalMove)
                {
                    Debug.WriteLine("{0} [{1}={2}], [{3}={4}] {5}", command, previousPos, previousPosAtOrigin, currentPos, currentPosAtOrigin, currentFeedrate);
                }
                if (command == CommandType.CWArc || command == CommandType.CCWArc)
                {
                    Debug.WriteLine("{0} [{1}={2}], [{3}={4}] [{5}={6}] {7}", command, previousPos, previousPosAtOrigin, currentPos, currentPosAtOrigin, centerPos, centerPosAtOrigin, currentFeedrate);
                }
                                #endif

                // store current position
                previousPos = currentPos;

                // count number of instructions processed
                numInstructions++;
            }

            // add a last raise Z
            // raise Z to Z clearance (= G0 Za)
            var lastRaiseBitInstruction = new GCodeInstruction(CommandType.RapidMove, null, null, zClearance, null);
            app[0].Add(lastRaiseBitInstruction);
            app[1].Add(lastRaiseBitInstruction);

            return(app);
        }
示例#4
0
        /// <summary>
        /// Minimize gcode by removing coordinates that is a repeat of the previous coordinate
        /// </summary>
        /// <param name="instructions">instructions</param>
        /// <returns>minimized gcode</returns>
        public static List <GCodeInstruction> GetMinimizeGCode(List <GCodeInstruction> instructions)
        {
            var cleanedList     = new List <GCodeInstruction>();
            var prevInstruction = new GCodeInstruction(CommandType.RapidMove, new Point3D(), 0);

            CommandType mvtype = CommandType.Other;

            float lastX = 0.0f;
            float lastY = 0.0f;
            float lastZ = 0.0f;
            float lastF = 0.0f;

            foreach (GCodeInstruction currentInstruction in instructions)
            {
                if (currentInstruction.Equals(prevInstruction))
                {
                    continue;
                }

                // store move type
                mvtype = currentInstruction.CommandType;

                if (mvtype == CommandType.RapidMove ||
                    mvtype == CommandType.NormalMove ||
                    mvtype == CommandType.CWArc ||
                    mvtype == CommandType.CCWArc)
                {
                    // merge previous coordinates with newer ones to maintain correct point coordinates
                    if ((currentInstruction.X.HasValue || currentInstruction.Y.HasValue || currentInstruction.Z.HasValue ||
                         currentInstruction.F.HasValue))
                    {
                        if ((currentInstruction.X.HasValue && prevInstruction.X.HasValue &&
                             currentInstruction.X.Value == prevInstruction.X.Value) ||
                            currentInstruction.X.HasValue && currentInstruction.X.Value == lastX)
                        {
                            // X is similar
                            currentInstruction.X = (float?)null;
                        }
                        if ((currentInstruction.Y.HasValue && prevInstruction.Y.HasValue &&
                             currentInstruction.Y.Value == prevInstruction.Y.Value) ||
                            currentInstruction.Y.HasValue && currentInstruction.Y.Value == lastY)
                        {
                            // Y is similar
                            currentInstruction.Y = (float?)null;
                        }
                        if ((currentInstruction.Z.HasValue && prevInstruction.Z.HasValue &&
                             currentInstruction.Z.Value == prevInstruction.Z.Value) ||
                            currentInstruction.Z.HasValue && currentInstruction.Z.Value == lastZ)
                        {
                            // Z is similar
                            currentInstruction.Z = (float?)null;
                        }
                        if ((currentInstruction.F.HasValue && prevInstruction.F.HasValue &&
                             currentInstruction.F.Value == prevInstruction.F.Value) ||
                            currentInstruction.F.HasValue && currentInstruction.F.Value == lastF)
                        {
                            // F is similar
                            currentInstruction.F = (float?)null;
                        }
                    }

                    // store latest movement instructions as previous instrucion
                    prevInstruction = currentInstruction;

                    // at all times store the latest X, Y, Z and feedrate
                    if (currentInstruction.X.HasValue)
                    {
                        lastX = currentInstruction.X.Value;
                    }
                    if (currentInstruction.Y.HasValue)
                    {
                        lastY = currentInstruction.Y.Value;
                    }
                    if (currentInstruction.Z.HasValue)
                    {
                        lastZ = currentInstruction.Z.Value;
                    }
                    if (currentInstruction.F.HasValue)
                    {
                        lastF = currentInstruction.F.Value;
                    }
                }

                cleanedList.Add(currentInstruction);
            }

            return(cleanedList);
        }