svg2gcode Progress Update

6 minute read Published 9 September 2021

A review of major changes and what's next

svg2gcode is a tool for converting vector graphics to G-Code: a language widely used for numerically controlled machines like pen plotters.

SVG of a black 5-point star with gold trim and a bold white letter V in the center Example vector graphic

Picture of a Prusa Mini+ 3D printer with a plastic attachment holding a pen Picture of a 5-point star drawn by a pen plotter using a blue pen A pen plotter attachment is used to draw the SVG on a 3D printer

Quoting Thomas Kole on Twitter:

Itโ€™s written in rust and was super easy to compile for the [Raspberry] Pi. I first tried a python implementation, but this is orders of magnitude faster. Itโ€™s crazy fast.

I initially released svg2gcode in 2019 as part of a project to build a pen plotter. The Inkscape extension we tried to use for that was overly complicated so I set out to build a standalone tool from scratch. The project has changed considerably since then โ€“ there are several noteworthy features which Iโ€™ll discuss below.

Removing barriers to use๐Ÿ”—

After talking to a few users over email, I realized that there were significant barriers preventing wider use of svg2gcode:

Web interface๐Ÿ”—

I created a web app for svg2gcode to address these challenges:

Screenshot of the web app showing file selection, a settings menu, and a button to generate G-Code

The web interface is functionally equivalent to the CLI tool. There are some added ergonomics like saving settings to Web Storage and on-the-fly validation:

Screenshot of the settings modal for the web app showing different validation states (pass/fail) and an option to save settings

It is written purely in Rust with the Yew framework. The code is compiled to WebAssembly using Trunk, a web application bundler. The UI uses Spectre.css. This allowed me to make it:

Continuous deployment is done using GitHub Actions. Pushing a commit triggers workflow jobs to build, test, and publish the latest changes to GitHub Pages:

Screenshot of the list of GitHub actions workflows configured for the svg2gcode repository on GitHub

Prebuilt binaries๐Ÿ”—

For those comfortable with the CLI but not too familiar with Rust, I set up prebuilt binary downloads. The Rust Release Binary action publishes binaries for platforms with x86-64 processors running Linux, Windows or OS X.

Custom G-Code Sequences๐Ÿ”—

Users can now specify a G-Code sequence to run at the beginning/end of a program and when the tool is turned on/off. This makes it possible to target just about any machine that accepts G-Code.

Enabling this involved a pretty comprehensive overhaul of how the tool handles G-Code. Most of the logic was pulled out into the g-code crate: an all-in-one library for parsing, formatting, and outputting G-Code.

Each sequence is parsed into a tokenized representation. If this fails, the tool stops early and an error message is displayed using codespan:

error: could not parse gcode
  โ”Œโ”€ begin_sequence:1:27
1 โ”‚ G0 X0 Y0 (unclosed comment
  โ”‚                           ^ expected closing parenthesis

These tokens are inserted into the output where appropriate. For instance, the tool on/off sequences are inserted at the start/end of each path segment:

> svg2gcode --on '(tool on)' --off '(tool off)' examparse, format, and emitples/Vanderbilt_Commodores_logo.svg

G0 X59.02125187621354 Y114.1597945756128(tool on)
G1 X44.163311191869035 Y73.15496298711147 F300
G1 X59.02125187621354 Y114.1597945756128 F300;svg > g > g > path
(tool off)

Circular Interpolation๐Ÿ”—

When converting to G-Code, the tool must do something called curve flattening: curves are converted into a series of connected line segments within a given tolerance. The tolerance is kept small enough that there is no discernible difference between the original and flattened curves in the end product. We can see the difference close up using a G-Code viewer:

A circle Left side of the visualized G-Code for a circle showing line segments A close-up visualization of the G-Code for this circle reveals the line segments

While flattening to line segments works well, some machines also support circular arc segments: given start/end points and a radius, the machine interpolates along a circular arc between the two. Circular arc segments are much better at approximating curves. Output file size is decreased by a lot and the machine can better control velocity and acceleration while executing the program.

I implemented circular interpolation following Kaewsaiha & Dejdumrongโ€™s paper Modeling of Bรฉzier Curves Using a Combination of Linear and Circular Arc Approximations.

Left side of the visualized G-Code for a circle with circular interpolation enabled, showing a truer approximation A truer approximation with circular interpolation enabled

Aside from that I ironed out some bugs with the logic for geometric transformations on elliptical arcs. Vitaly Putzinโ€™s svgpath was a really good reference for this.

Whatโ€™s next?๐Ÿ”—

I have a whole laundry list of ideas to take svg2gcode even further. To name a few:


Builds and packaging:

New platforms:

But I only have so much time! ๐Ÿ˜…

If you have questions or want to contribute, check out svg2gcode on GitHub. If you liked using svg2gcode or want to bounce ideas off me, letโ€™s chat!