Introduction#
I originally developed this project at Boston University. Reading through the code again having worked professionally for a few years, I found a lot I would clean up. Refactoring this code provided an opportunity to improve the readability and structure while using tools like the uv package manager.

Everyone’s favorite pokemon filled with a connected-fermat-spiral
Background#
The algorithm is defined in the Connected fermat spirals for layered fabrication paper.
Filling a shape with spirals often requires multiple, disjoint spirals. By doubling back on the spiral, the input and output to the spiral can be made to be the same location.

This can be inserted into the external spiral to create one continuous path.

The code follows this pipeline to convert fill objects in an image with connected spirals.
graph LR; A[Image]-->B[Polygon]; B-->C[Contours]; C-->D[Spirals]; D-->E[Connected Spirals]
The conversion to Connected Spirals requires parent-child relationships between each spiral, because each child spiral can only be connected to its parent. The Contours step defines the relationships. These steps all use the Node class to store this relationship information.
Updates from Original Code#
I needed to update the Python version, as the original code was targeting Python 3.8 which is end-of-life. I chose Python 3.12, but was able to quickly test Python 3.11 using uv run --python 3.11.
One significant change was the inclusion of the Node class, which represents a simple tree structure. I was able to use this for both storing the contour and spiral information. Both datatypes require parent-child relationships. This greatly cleaned up the code and allowed more-specific type annotations.
I also made a few “software engineering” changes to the code. These were focused on readability.
- Added docstrings to each file, class, and function.
- Used type hints throughout the code.
- Made variable and function names verbose.
- Used guard clauses instead of nested if statements.
- Limited the excessive comment use (I had commented almost every line) to only when needed.
Future Work#
There are a few path generation items that could be improved:
- Remove self intersections in spiral generation and connection (visible in Pikachu example).
- Improve the uniformity of the space fill.
- Smooth the sharp corners of the path.
The project could also use more unit test coverage, better logging, and an improved entry script.
