using OpenNest.CNC; using OpenNest.Geometry; namespace OpenNest.Converters { public static class ConvertMode { /// /// Converts the program to absolute coordinates. /// Does NOT check program mode before converting. /// public static void ToAbsolute(Program pgm) { var pos = new Vector(0, 0); for (int i = 0; i < pgm.Codes.Count; ++i) { var code = pgm.Codes[i]; if (code is SubProgramCall subCall && subCall.Program != null) { // Sub-program is placed at Offset in this program's frame. // After it runs, the tool is at Offset + (sub's end in its own frame). pos = ComputeEndPosition(subCall.Program, subCall.Offset); continue; } if (code is Motion motion) { motion.Offset(pos.X, pos.Y); pos = motion.EndPoint; } } } /// /// Converts the program to incremental coordinates. /// Does NOT check program mode before converting. /// public static void ToIncremental(Program pgm) { var pos = new Vector(0, 0); for (int i = 0; i < pgm.Codes.Count; ++i) { var code = pgm.Codes[i]; if (code is SubProgramCall subCall && subCall.Program != null) { // Sub-program is placed at Offset in this program's frame, // regardless of where the tool was before the call. pos = ComputeEndPosition(subCall.Program, subCall.Offset); continue; } if (code is Motion motion) { var pos2 = motion.EndPoint; motion.Offset(-pos.X, -pos.Y); pos = pos2; } } } /// /// Computes the tool position after executing , /// given that the program's frame origin is at /// in the caller's frame. Walks nested sub-program calls recursively. /// private static Vector ComputeEndPosition(Program pgm, Vector startPos) { var pos = startPos; for (int i = 0; i < pgm.Codes.Count; ++i) { var code = pgm.Codes[i]; if (code is SubProgramCall subCall && subCall.Program != null) { // Nested sub's frame origin in the caller's frame is startPos + Offset. pos = ComputeEndPosition(subCall.Program, startPos + subCall.Offset); continue; } if (code is Motion motion) { if (pgm.Mode == Mode.Incremental) pos = pos + motion.EndPoint; else pos = startPos + motion.EndPoint; } } return pos; } } }