public bool EqualCoordinates(Point3DBlock other) { if (other != null && this.X == other.X && this.Y == other.Y && this.Z == other.Z) { return(true); } return(false); }
/// <summary> /// Split the list of gcode instructions into gcode blocks. /// Splits on G0 commands that includes either X and/or Y. /// Returns everything before the first G0, all G0 blocks and everything after last block /// </summary> /// <param name="instructions">list of gcode instructions</param> /// <returns>GCode split object</returns> public static GCodeGroupObject GroupGCodeInstructions(List <GCodeInstruction> instructions) { // list that will be returned var allG0 = new List <Point3DBlock>(); var priorToG0 = new List <GCodeInstruction>(); var afterLastG0 = new List <GCodeInstruction>(); // temporary list var tempNotG0 = new List <GCodeInstruction>(); float lastX = 0.0f; float lastY = 0.0f; foreach (var currentInstruction in instructions) { // Check if this line is a G0 command with an X or Y coordinate if (currentInstruction.CommandType == CommandType.RapidMove && (currentInstruction.X.HasValue || currentInstruction.Y.HasValue)) { // If x or y here is false we need to use the last coordinate // from a previous G0 or G1 as that is where the machine would be // or force to 0 if (!currentInstruction.X.HasValue) { currentInstruction.X = lastX; } if (!currentInstruction.Y.HasValue) { currentInstruction.Y = lastY; } // allG0 already has entries, // therefore we need to add all the temporary notG0's // to the followingLines for the previous entry in allG0 if (allG0.Count > 0) { var lastElement = allG0.Last(); lastElement.GCodeInstructions.AddRange(tempNotG0); } // Add this G0 to allG0 with itself (the G0) as the first entry in followingLines var point = new Point3DBlock(currentInstruction.X.Value, currentInstruction.Y.Value); point.GCodeInstructions.Add(currentInstruction); allG0.Add(point); // Empty notG0 so it's ready for next block tempNotG0.Clear(); } else { // Add this line to notG0 since it's not a G0 with X or Y coordinates tempNotG0.Add(currentInstruction); } // if allG0 at this point is zero, it means we haven't // detected the first G0 group yet. // add to the priorToG0 group if (allG0.Count == 0) { priorToG0.Add(currentInstruction); } // store position state if (currentInstruction.X.HasValue) { lastX = currentInstruction.X.Value; } if (currentInstruction.Y.HasValue) { lastY = currentInstruction.Y.Value; } } // if allG0 at this point is zero, we were unable to parse any // movement instructions, return empty split object if (allG0.Count == 0) { return(null); } // add notG0 to the followingLines for the last entry in allG0 // this gets the lines after the last G0 in the file // we also need to check if the commands here are not G0, G1, G2, G3, or G4 // because in this case they should be left at the end of the file, not put into the parent G0 block foreach (var currentInstruction in tempNotG0) { // check if this line is a G0, G1, G2 or G3 if (currentInstruction.CanRender) { // this should be added to the parent G0 block allG0.Last().GCodeInstructions.Add(currentInstruction); } else { // this should be added to the end of the file as it was already there afterLastG0.Add(currentInstruction); } } // add header and footer as special blocks var gcodeBlocks = new GCodeGroupObject(); gcodeBlocks.G0Sections = allG0; gcodeBlocks.PriorToFirstG0Section = priorToG0; gcodeBlocks.AfterLastG0Section = afterLastG0; return(gcodeBlocks); }
/// <summary> /// Sort the list of Point3DBlock by Z-height so that the cutting is incremental /// </summary> /// <param name="bestPath">Original sequence of the point3d elements</param> /// <param name="points">Point elements</param> /// <returns>sorted sequence of the point3d elements</returns> public static List <int> SortBlocksByZDepth(List <int> bestPath, List <IPoint2D> points) { var sortedBestPath = new List <int>(); Point3DBlock previousBlock = null; var blocksWithSameXY = new List <Point3DBlock>(); if (points != null && points.Count > 0 && points[0] is Point3DBlock) { for (int i = 0; i < bestPath.Count; i++) { // retrieve correct block using best path index var block = points[bestPath[i]] as Point3DBlock; // if we have blocks available and // we have reached a new block (i.e. different X and Y coordinate) // store it and clear the blocks if (blocksWithSameXY.Count > 0 && !block.EqualXYCoordinates(previousBlock) ) { // sort the blocks with same xy by z coordinate var sortedByZ = blocksWithSameXY.OrderByDescending(s => s.Z); // add to return index var indexes = sortedByZ.Select(o => o.BestPathIndex); sortedBestPath.AddRange(indexes); // reset block blocksWithSameXY.Clear(); } else { // can this happen? } // store original index block.BestPathIndex = bestPath[i]; // retrieve z and store float z = RetrieveZ(block.GCodeInstructions); if (!float.IsNaN(z)) { block.Z = z; // add blocksWithSameXY.Add(block); } // store previous block previousBlock = block; } } // also store the last block collection // if we have blocks available and // we have reached a new block (i.e. different X and Y coordinate) // store it and clear the blocks if (blocksWithSameXY.Count > 0) { // sort the blocks with same xy by z coordinate var sortedByZ = blocksWithSameXY.OrderByDescending(s => s.Z); // add to return index var indexes = sortedByZ.Select(o => o.BestPathIndex); sortedBestPath.AddRange(indexes); // reset block blocksWithSameXY.Clear(); } return(sortedBestPath); }