Application 1
using System.Text.RegularExpressions; // Library for text patterns manipulation
namespace G_code__Inkscape__simplifier
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent(); // Initialization of application
}
string filePath = ""; // Original G-code file
int maxWidth = 1000; // Variable for text boxes containing file paths
// Method (function) to adjust the size of the text box
private void AdjustTextBoxWidth()
{
var textSize = TextRenderer.MeasureText(textBoxUpload.Text, textBoxUpload.Font);
textBoxUpload.Width = Math.Min(textSize.Width, maxWidth);
}
// Method to close the application
private void btnClose_Click(object sender, EventArgs e)
{
Close(); // Closes the application
}
private void btnUpload_Click(object sender, EventArgs e)
{
// Filter files to only show ".gcode" and ".ngc" files
openFileDialog1.Filter = "G-code files (*.gcode;*.ngc)|*.gcode;*.ngc";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filePath = openFileDialog1.FileName; // Location of the file on the computer
textBoxUpload.Text = filePath; // Displays the location of the file
AdjustTextBoxWidth(); // Calls method
}
}
private void Form1_Shown(object sender, EventArgs e)
{
this.ActiveControl = null;
}
private void btnSimplify_Click(object sender, EventArgs e)
{
// If no file is selected
if (string.IsNullOrEmpty(filePath))
{
textBoxSimplify.Text = "Upload a file first !"; // A message box appears
return;
}
string[] lines = File.ReadAllLines(filePath); // An array reads every line of the file
// Inkscape's G-code format
// Transformation of the original file into a file more easy to read and manipulate for the port/microcontroller
// Removal of useless data
var simplified = lines
.Select(l => l.Trim()) // Removes extra spaces
.Where(l =>
!string.IsNullOrWhiteSpace(l) && // Removes empty lines
!l.StartsWith("(") && // Removes lines starting with "("
!l.StartsWith("M") && // Removes lines starting with "M"
!l.StartsWith("G21") && // Removes lines starting with "G21"
!l.StartsWith("G00 Z") && // Removes lines starting with "G00 Z"
!l.StartsWith("G01 Z") && // Removes lines starting with "G01 Z"
!l.Contains("%")
)
.Select(l => Regex.Replace(l, @"G-?\d+(\.\d+)?", "")) // Removes G values
.Select(l => Regex.Replace(l, @"Z-?\d+(\.\d+)?", "")) // Removes Z values
.Select(l => Regex.Replace(l, @"F-?\d+(\.\d+)?", "")) // Removes F values
.Select(l => Regex.Replace(l, @"\s+", " ").Trim()) // cleanup spaces
.ToArray(); // Converts everything into an array
var output = new List();
var culture = System.Globalization.CultureInfo.InvariantCulture; // Converts values into decimals
foreach (var line in simplified)
{
var xMatch = Regex.Match(line, @"X-?\d+(\.\d+)?"); // Values of X
var yMatch = Regex.Match(line, @"Y-?\d+(\.\d+)?"); // Values of Y
if (xMatch.Success)
{
// Converts values into decimals
double x = double.Parse(xMatch.Value.Substring(1), culture);
output.Add(x.ToString("0.00", culture));
}
if (yMatch.Success)
{
// Converts values into decimals
double y = double.Parse(yMatch.Value.Substring(1), culture);
output.Add(y.ToString("0.00", culture));
}
}
// Create new file name in same folder
string folder = Path.GetDirectoryName(filePath);
string name = Path.GetFileNameWithoutExtension(filePath);
string ext = Path.GetExtension(filePath);
string newFilePath = Path.Combine(folder, name + "_simplified" + ext); // creates a new filename
File.WriteAllLines(newFilePath, output); // Creates a new file
textBoxSimplify.Text = "Done !"; // A message appears
}
}
}
Application 2
using System.IO.Ports; // Library for serial communication
namespace test_com
{
public partial class Form1 : Form
{
SerialPort serialPort = new SerialPort(); // Creation of variable serialPort
// Method to refresh the detected ports
private void RefreshPorts()
{
comboBoxPorts.Items.Clear(); // Clears the current list
string[] ports = SerialPort.GetPortNames(); // Detects every serial ports
Array.Sort(ports); // Sorts the ports alphabetically and numerically
comboBoxPorts.Items.AddRange(ports); // Adds every port name in the dropdown list
// If a port is available, automaticaly connect to it
if (comboBoxPorts.Items.Count > 0)
comboBoxPorts.SelectedIndex = 0;
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string data = serialPort.ReadExisting(); // Reads the serial port
this.Invoke(new Action(() =>
{
// Writes data in the text box and scrolls down to the latest data
textBoxOutput.AppendText(data);
textBoxOutput.SelectionStart = textBoxOutput.Text.Length;
textBoxOutput.ScrollToCaret();
}));
}
catch
{
// Ignores disconnect glitches
}
}
public Form1()
{
InitializeComponent(); // Initialization of application
serialPort.DataReceived += SerialPort_DataReceived; // Reacts to incoming serial data
}
// Method to close the application
private void btnClose_Click(object sender, EventArgs e)
{
Close(); // Closes the application
}
// Method when the application is launched
private void Form1_Load(object sender, EventArgs e)
{
RefreshPorts(); // Calls method
}
// Method to refresh the detected ports
private void btnRefresh_Click(object sender, EventArgs e)
{
RefreshPorts(); // Calls method
}
private void Form1_Shown(object sender, EventArgs e)
{
this.ActiveControl = null;
}
private void btnConnect_Click(object sender, EventArgs e)
{
// Function to disconnect
if (serialPort.IsOpen)
{
serialPort.Close();
btnConnect.Text = "Connect";
return;
}
try
{
// Function if no ports are selected
if (comboBoxPorts.SelectedItem == null)
{
MessageBox.Show("Please select a COM port.", "Warning !"); // A message box appears
return;
}
// Serial port configuration
serialPort.PortName = comboBoxPorts.SelectedItem.ToString();
serialPort.BaudRate = 115200;
serialPort.NewLine = "\n";
serialPort.Open();
btnConnect.Text = "Disconnect";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // A message box appears
}
}
private void btnSend_Click(object sender, EventArgs e)
{
// Function if no ports are selected
if (!serialPort.IsOpen)
{
MessageBox.Show("Port not open!"); // A message box appears
return;
}
string msg = textBoxSend.Text; // Store the typed data
serialPort.WriteLine(msg); // Sends the stored data to the port
}
}
}
Final application
using System.IO.Ports; // Library for serial communication
using System.Text.RegularExpressions; // Library for text patterns manipulation
namespace G_code__Inkscape__to_sand_table
{
public partial class Form1 : Form
{
string filePath = ""; // Original G-code file
string newFilePath = ""; // Modified G-code file
int maxWidth = 700; // Variable for text boxes containing file paths
SerialPort serialPort = new SerialPort(); // Creation of variable serialPort
string[] gcodeLines; // Array of G-code lines
int sendIndex = 0; // Variable for the position in the G-code array
TaskCompletionSource okWaiter; // Boolean that waits for "OK" from port/microcontroller
public Form1()
{
InitializeComponent(); // Initialization of application
serialPort.DataReceived += SerialPort_DataReceived; // Reacts to incoming serial data
}
// Method (function) to adjust the size of the text box
private void AdjustTextBoxWidth1()
{
// Measures the screen space for the text
var textSize = TextRenderer.MeasureText(textBoxUpload.Text, textBoxUpload.Font);
// Sets text box width with a limit
textBoxUpload.Width = Math.Min(textSize.Width, maxWidth);
}
// Method to adjust the size of the text box
private void AdjustTextBoxWidth2()
{
// Measures the screen space for the text
var textSize = TextRenderer.MeasureText(textBoxSimplify.Text, textBoxSimplify.Font);
// Sets text box width with a limit
textBoxSimplify.Width = Math.Min(textSize.Width, maxWidth);
}
// Method to refresh the detected ports
private void RefreshPorts()
{
comboBoxPorts.Items.Clear(); // Clears the current list
string[] ports = SerialPort.GetPortNames(); // Detects every serial ports
Array.Sort(ports); // Sorts the ports alphabetically and numerically
comboBoxPorts.Items.AddRange(ports); // Adds every port name in the dropdown list
// If a port is available, automaticaly connect to it
if (comboBoxPorts.Items.Count > 0)
comboBoxPorts.SelectedIndex = 0;
}
// Method to treat the received data from the port/microcontroller
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string data = serialPort.ReadExisting(); // Reads the serial port
this.Invoke(new Action(() =>
{
// Writes data in the text box and scrolls down to the latest data
textBoxOutput.AppendText(data);
textBoxOutput.SelectionStart = textBoxOutput.Text.Length;
textBoxOutput.ScrollToCaret();
// Checks for "OK" from port/microcontroller
if (data.Contains("OK"))
{
okWaiter?.TrySetResult(true);
}
}));
}
catch
{
// Ignores disconnect glitches
}
}
// Method to close the application
private void btnClose_Click(object sender, EventArgs e)
{
Close(); // Closes the application
}
private void Form1_Shown(object sender, EventArgs e)
{
this.ActiveControl = null;
}
// Method when the application is launched
private void Form1_Load(object sender, EventArgs e)
{
RefreshPorts(); // Calls method
}
// Method to upload a G-code file
private void btnUpload_Click(object sender, EventArgs e)
{
// Filter files to only show ".gcode" and ".ngc" files
openFileDialog1.Filter = "G-code files (*.gcode;*.ngc)|*.gcode;*.ngc";
// Opens a window to choose a file
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filePath = openFileDialog1.FileName; // Location of the file on the computer
textBoxUpload.Text = filePath; // Displays the location of the file
AdjustTextBoxWidth1(); // Calls method
}
}
private void btnSimplify_Click(object sender, EventArgs e)
{
// If no file is selected
if (string.IsNullOrEmpty(filePath))
{
MessageBox.Show("Please upload a file first.", "Warning !"); // A message box appears
return;
}
string[] lines = File.ReadAllLines(filePath); // An array reads every line of the file
// Inkscape's G-code format
// Transformation of the original file into a file more easy to read and manipulate for the port/microcontroller
// Removal of useless data
var simplified = lines
.Select(l => l.Trim()) // Removes extra spaces
.Where(l =>
!string.IsNullOrWhiteSpace(l) && // Removes empty lines
Regex.IsMatch(l, @"^G0(0|1)\b") && // Keeps every "G00" and "G01" lines
!Regex.IsMatch(l, @"^G0(0|1)\s+Z") // Removes every "G00 Z" and "G01 Z" lines
)
.Select(l => Regex.Replace(l, @"^G0(0|1)\s*|\s*(Z|F)\s*\[.*?\]", "")) // Removes G00 and G01
.Select(l => Regex.Replace(l, @"\s+", " ").Trim()) // Removes extra spaces to leave one
.ToArray(); // Converts everything into an array
// Removal of useless data and sorting of remaining data
var result = lines
.SelectMany(l =>
{
var x = Regex.Match(l, @"X\[(.*?)\*"); // Values of X
var y = Regex.Match(l, @"Y\[(.*?)\*"); // Values of Y
// Returns nothing if X or Y is missing
if (!x.Success || !y.Success)
return Enumerable.Empty();
// Converts values into decimals
var culture = System.Globalization.CultureInfo.InvariantCulture;
double xVal = double.Parse(x.Groups[1].Value, culture);
double yVal = double.Parse(y.Groups[1].Value, culture);
// Converts values into integers
return new[]
{
((int)xVal).ToString(culture),
((int)yVal).ToString(culture)
};
})
.ToArray(); // Converts everything into an array
// Create new file name in same folder
string folder = Path.GetDirectoryName(filePath);
string name = Path.GetFileNameWithoutExtension(filePath);
string ext = Path.GetExtension(filePath);
newFilePath = Path.Combine(folder, name + "_simplified" + ext); // creates a new filename
File.WriteAllLines(newFilePath, result); // Creates a new file
textBoxSimplify.Text = "New file created at : " + newFilePath; // Displays the location of the file
AdjustTextBoxWidth2(); // Calls method
}
// Method to refresh the detected ports
private void buttonRefresh_Click(object sender, EventArgs e)
{
RefreshPorts(); // Calls method
}
// Method to connect to the selected port
private void btnConnect_Click(object sender, EventArgs e)
{
// Function to disconnect
if (serialPort.IsOpen)
{
serialPort.Close();
btnConnect.Text = "Connect";
return;
}
try
{
// Function if no ports are selected
if (comboBoxPorts.SelectedItem == null)
{
MessageBox.Show("Please select a COM port.", "Warning !"); // A message box appears
return;
}
// Serial port configuration
serialPort.PortName = comboBoxPorts.SelectedItem.ToString();
serialPort.BaudRate = 115200;
serialPort.NewLine = "\n";
serialPort.Open();
btnConnect.Text = "Disconnect";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // A message box appears
}
}
// Method to start the communication of the G-code
private async void btnStartCom_Click(object sender, EventArgs e)
{
// Function if no ports are selected
if (!serialPort.IsOpen)
{
MessageBox.Show("Connect to port first!", "Warning !"); // A message box appears
return;
}
// Function if no there are no files uploaded
if (string.IsNullOrEmpty(newFilePath))
{
MessageBox.Show("Upload a file first!", "Warning !"); // A message box appears
return;
}
gcodeLines = File.ReadAllLines(newFilePath); // Reads the modified G-code file
sendIndex = 0; // Position in the file
// Runs until all lines are sent
while (sendIndex < gcodeLines.Length)
{
// Takes 2 lines
string line1 = gcodeLines[sendIndex]; // Current line
string line2 = (sendIndex + 1 < gcodeLines.Length) ? gcodeLines[sendIndex + 1] : ""; // Next line
serialPort.WriteLine(line1); // Send line 1
if (!string.IsNullOrWhiteSpace(line2)) // Send line 2
serialPort.WriteLine(line2);
sendIndex += 2; // Moves to the next 2 lines
// Waits for "OK"
okWaiter = new TaskCompletionSource();
await okWaiter.Task;
}
MessageBox.Show("G-code sent successfully!", "Success !"); // A message box appears
}
// Method to clear the text box
private void btnClear_Click(object sender, EventArgs e)
{
textBoxOutput.Clear(); // Clears the text box
}
}
}