Our project was to build a Spirograph machine that draws geometric patterns on rotating paper using two joints and a pen holder. The joints are controlled by stepper motors, which move the pen at different angles. The pen holder is equipped with a spring-like 3D printing mechanism that regulates the pressure on the paper. The paper is rotated by another stepper motor, which is slowed down by a gearbox. The paper plate rotates exactly once per drawing, while the joints rotate much faster.
We used various techniques and tools for this project, such as 3D printing, aluminum profiles, plexiglass, stepper motors and drivers, a self-designed circuit board, and a display. We also programmed a simulation that shows us what the finished drawing will look like based on the speeds of the joints and the paper plate.
The key steps of our project were:
- Creating a concept sketch and selecting suitable motors and materials.
- Controlling the stepper motors with stepper drivers and overcoming initial challenges.
- Building the machine's rough structure using aluminum profiles (using the Item Engineering tool).
- Mechanical design in Inventor.
- Developing an electrical schematic in KiCad.
- Creating a PCB layout in KiCad and ordering and assembling the PCB.
- Assembling the real machine with a display, power supply, socket, 3D printed joints, and pen holder.
- Calculating the motion equations for the joints and the paper plate.
- Programming a simulation using G-Code.
- Wiring the components and commissioning the machine.
Our project was a great success from which we learned a lot. We not only built a functional Spirograph machine but also gained experience with various technologies.
- ๐ Table of Contents
- ๐ Overview
- โ๏ธ Features
- ๐ Project Structure
- ๐งฉ Modules
- ๐ Getting Started
- ๐บ Roadmap
- ๐ค Contributing
- ๐ License
- ๐ Acknowledgments
Root
File | Summary |
---|---|
module-info.java | This code defines the module dependencies necessary for the KaroDesigner application, including Java Desktop, logging, JSON, and RSyntaxTextArea libraries. |
Application.java | This code defines an interface for an application with two methods: "start" to start the application and "stop" to stop it. It also declares exceptions for IO operations. |
DrawMachineSim.java | This code represents the main class of a drawing application. It initializes the UI elements, handles themes and hotkeys, and loads the application configuration. The application can be started and stopped, and provides access to various components such as the menu bar and design handler. |
DrawMachineSimLoader.java | The code is a starting point for a drawing machine simulation. It sets up the application and starts it by creating an instance of the DrawMachineSim class and calling its start() method. |
MainWindow.java | The code represents a main window for a drawing machine application. It initializes the JFrame with a title, icon, menu bar, and view. It also centers the window on the screen and provides resizing functionality. The class extends JFrame and includes methods for initialization and centering the window. |
View.java | This code represents a View class that sets up the user interface components for a drawing application, including a file hub and a workspace. It uses a design handler to manage design-related functionality. |
Action.java | This code defines an interface called Action. It has a single method called run, which takes a generic type parameter and has no return value. The purpose of this interface is to define a contract for actions to be performed on an object of type T. |
Buildable.java | The code defines an interface called Buildable with a generic parameter. The interface includes a single method called build, which returns an object of type T. |
FileUpdateScheduler.java | This code defines an abstract class called FileUpdateScheduler that extends ThreadScheduler. It provides functionality to list all files in a given directory and check if there have been any changes in the directory. |
KeyAction.java | This code defines an interface called KeyAction, which extends the Action interface and specifies a generic type of KeyStroke. It is used in the net.gotzi.drawmachine.api package and is designed for handling keystroke actions in a GUI environment using Swing. |
Loadable.java | This code defines the Loadable interface, which requires implementing classes to provide a "load" method. This method is responsible for loading data or resources into the implementing class. |
MouseAction.java | The code defines an interface called MouseAction that extends the Action interface for handling mouse events in a drawing machine API. |
Process.java | The code defines an abstract class called Process that encapsulates common functionalities for process objects. It provides a way to get the result of the process and manages a successful flag for the process. |
ThreadScheduler.java | This code is a ThreadScheduler abstract class that provides essential functionalities for managing threads. It allows starting and stopping a thread, sleeping for a specified amount of time, and checking if the thread is stopped. |
VerticalLabelUI.java | The code defines the VerticalLabelUI class, which is a custom UI for Swing JLabels that allows the text and icon to be displayed vertically. The class provides methods for calculating the preferred size, painting the label, and handling text and icon alignment. It supports clockwise and counterclockwise rotation options. |
VerticalTabbedPane.java | The code defines a class called VerticalTabbedPane, extending JTabbedPane. It creates a vertical tabbed pane by setting the tab placement to the left. The addTab() method adds a new tab with a specified title and component. It also creates a vertical label for the tab title and sets it as the tab component. The createVerticalLabel() method creates a JLabel with vertical text orientation. |
SimCompletedInfo.java | The code defines a Java record called SimCompletedInfo that encapsulates the calculation time and travel distance of a simulation. |
SimEditorValues.java | The code defines a data structure (record) called "SimEditorValues" that represents the values used in a simulation editor. These values include various points, arm lengths, and lengths for a drawmachine simulation. |
SimPoint.java | The code defines a record class called SimPoint that represents a point in a simulation. It overrides the equals, hashCode, and toString methods to provide customized behavior for comparing and displaying instances of SimPoint. |
SimProgramInfo.java | The code defines a record class called SimProgramInfo that holds information about a simulated program. It includes a SimEditorValues object representing saved editor values and a GCode object representing the generated G-code. |
SimRenderState.java | The code defines a Java record called SimRenderState, which represents the state of a simulation at a given time with a timestamp and a time value. |
SimState.java | This code defines a record called SimState, which has two fields: "timestamp" and "time". This record is used to store information about the current state of a simulation. |
SimValues.java | The code defines the SimValues record, which represents the simulation values for a drawing machine. It includes points and lengths related to the DC gear and stepper motors, as well as an intersection value and a GCode object for generating the machine instructions. |
Builder.java | This code defines an abstract class called Builder that extends a Process class and implements the Buildable interface. It takes two generic parameters (T and S) and encapsulates the core functionality for building objects. |
HotKeyBuilder.java | The HotKeyBuilder class is responsible for loading hotkeys from a configuration file and building a HotKeyHandler object that can handle user-defined hotkeys. It reads the hotkeys from a properties file, assigns them to key strokes, and adds them to the HotKeyHandler. Finally, it returns the HotKeyHandler object. |
DimensionConstants.java | This code is a utility class that loads dimension properties from a file and stores them in a map for easy access. It provides functionality to retrieve a Dimension object using a given key. |
UnderLayPanel.java | The UnderLayPanel class is a JPanel that acts as a border around a specified component. It allows you to set the thickness of each border direction (north, east, south, west) and customize the color of the border. It also provides a method to set the opaque property of the panel and its border panels. |
HorizontalSplitLayout.java | The code represents a layout manager called HorizontalSplitLayout. It splits a container horizontally into two components with customizable sizes. The layout is updated whenever the container is resized, adjusting the position and dimensions of the components accordingly. |
SplitLayout.java | This code defines an abstract class for a split layout in a user interface. It provides a way to divide the available space between two components and set their sizes. It extends the LayoutManager2 interface and requires the implementation of its methods. |
VerticalSplitLayout.java | The code implements a VerticalSplitLayout for dividing a container into two components. It allows setting the size of the components based on their position within the container. The layout is determined based on size1 and size2 values. The code also provides methods for layouting and dimension preferences. |
IMapLayout.java | The code defines an interface for a map layout, providing methods to reset and repaint the view. |
MapCopyPanel.java | The core functionality of the code is to create a map copy panel with the ability to paint on it using a specified action. The panel includes a canvas, and when the paint action is set, it will be executed to draw on the panel using the provided graphics object. |
MapLayout.java | The MapLayout class is responsible for managing the layout and behavior of a map display. It handles mouse events for dragging and scrolling the map, as well as handling layout positions. It includes functionalities such as resizing the map image, updating the scroll bar, and resetting the map view. |
MapPanel.java | The code defines a MapPanel class that extends JPanel and is used to display a map. It has functionality for rendering a simulation, handling mouse events, and updating the state of the simulation. The class also has methods to access the SimRenderer, dimension, and map layout. |
PencilOutOfCanvas.java | The code defines an exception class called PencilOutOfCanvas that extends Throwable. It displays an error message in a JOptionPane when the pencil goes out of the canvas during drawing on a GUI component. |
ThreadInterrupt.java | This code defines the ThreadInterrupt class, a custom RuntimeException. It is used to display error information in a JOptionPane dialog box, taking a parent component and a message string as input. |
UnsupportedAction.java | This code defines a class called UnsupportedAction that shows an error message using a standard Java Swing JOptionPane when an unsupported action occurs. The showErrorInfo method takes a parent component and a message as parameters, and displays the message as an error dialog. |
UnsupportedValue.java | The code defines a class called "UnsupportedValue" that displays an error message to the user using a Java Swing JOptionPane. It takes a component and a message as parameters, and shows the message as an error dialog box. |
MouseCursorHandler.java | The code defines a MouseCursorHandler class that allows changing the cursor style when the mouse enters or exits a component. It utilizes the DrawMachineSim library and sets the cursor based on the provided Cursor object. |
ChangeDesign.java | This code defines an interface called ChangeDesign that requires implementing classes to have a method that can change the color of a design. It uses the java.awt.Color class to represent the color parameter. |
ChangeManualDesign.java | This code defines an interface called "ChangeManualDesign" that allows for the manual redesign of a Swing component. The "redesign" method takes a JComponent as an argument and is responsible for making changes to the appearance or layout of the component. |
DesignColor.java | This code declares a public enum DesignColor, consisting of a single value "SECONDARY". |
DesignColorChanges.java | This code defines a handler class for managing design color changes. It provides functionalities to register and deregister design changes, redefine all changes with a new color, and set/get the default color. The class extends ArrayList and stores instances of ChangeDesign. |
DesignHandler.java | The DesignHandler class provides functionality for managing design colors and performing manual design changes on Java components. It allows registering and deregistering design colors, and provides methods to perform manual color changes on objects. The class follows a singleton pattern, ensuring only one instance of DesignHandler exists. |
HotKey.java | This code defines an enum class called HotKey that represents different hotkeys. Each hotkey has a key string and an associated action to be performed. The actions are executed on a DrawMachineSim object. The available hotkeys are RESET_SIM_VIEW to reset the view and SAVE_SIM_PROGRAM to save the program. |
HotKeyHandler.java | The HotKeyHandler class is responsible for handling hotkey events in the DrawMachineSim application. It allows the user to define hotkeys and associate them with custom actions to be performed when the hotkey is pressed. The class receives the root pane of the draw machine window and an instance of the DrawMachineSim class, and provides a method to add a new hotkey with a specified key name, keystroke, and action. When the hotkey is pressed, the associated action is executed. |
IHotKeyHandler.java | This code defines an interface for a HotKeyHandler, which provides a method to add a hotkey with a specific key combination and action to be performed in the context of a DrawMachineSim object. |
SimProgramLoader.java | The SimProgramLoader class provides functionality to unload and load simulation program information from/to JSON format. It can convert program details into a JSON string, and vice versa. Additionally, it includes a method to retrieve default simulation program information. |
Canvas.java | The Canvas class represents an image canvas with specified width, height, and color. It allows for resetting the canvas by setting all pixels to white, and setting individual pixels with the current color. It also sets the pixels surrounding the specified point to the same color. |
SimDataCollector.java | The SimDataCollector class is responsible for collecting data in a simulation. It retrieves program information and simulator values, such as editor values and G-code, from the SimSimulationTab and SimGCodeTab components. It then returns this data in the form of SimProgramInfo and SimValues objects. This class is also used to set the relevant tabs for data collection. |
SimInfo.java | The code defines a class called SimInfo which encapsulates information about a simulation. It includes the simulation values, step factor, speed, and fast mode indicator. It provides getters for accessing these values. |
SimRenderer.java | The SimRenderer class is responsible for rendering the simulation on a canvas. It controls the simulation logic based on the simulation parameters and updates the canvas accordingly. It can run the simulation in normal mode or fast mode. It also provides functions to stop the simulation and reset the canvas. |
Simulation.java | This code defines the interface "Simulation" which provides methods to run, stop, reset, and update the state of a simulation. It also includes methods to check the timestamp, running status, and fast mode of the simulation. |
SimView.java | The SimView class is the main visual component of a simulation. It provides a graphical interface with a main view and a monitor view. It allows for running and stopping the simulation, updating the state of the simulation, and resetting the view and canvas. It also provides functions to retrieve the timestamp, check if fast mode is enabled, and check if the simulation is running. |
Renderer.java | This code defines an interface called "Renderer" which has two main functions: "render" to initiate rendering of simulation information, and "stop" to stop the rendering process. It takes in two parameters: "simInfo" containing simulation data, and "simInfoParameters" providing additional parameters for rendering. |
SimGCodeLoader.java | The SimGCodeLoader class is responsible for parsing and loading GCode instructions for a simulated drawing machine. It compiles the GCode instructions, calculates the total time required for execution, and provides methods to get the degrees of various stepper motors at a given timestamp. |
FastLogic.java | The FastLogic class provides the core functionalities for simulating and rendering the drawing points based on a given algorithm. It handles multi-threading, data collection, distance calculation, and drawing on a canvas. |
Logic.java | This code defines an abstract class called Logic, which provides core functionalities for a simulation algorithm. It includes methods for checking if the simulation is finished at a given step and running the simulation. It also includes a helper method for calculating the distance between two points. |
MathLogic.java | The code provides math logic for calculating the degree of rotation and the position of a pencil point based on motor positions. It uses trigonometric calculations and helper classes. |
SimLogic.java | The SimLogic code is responsible for running a simulation of drawing operations. It calculates the next point to draw using mathematical logic, updates the canvas with the new point, and keeps track of the travel distance. The simulation runs at a specified speed and provides information about the completed simulation. |
SimEditor.java | The code defines an interface called "SimEditor" with two methods: "getSimEditorValues()" to get simulation editor values and "getBaseSteps()" to get the base number of steps. |
SimEditorView.form | Exception: |
SimEditorView.java | The "SimEditorView" class is responsible for handling the user interface and data input/output for the simulation editor. It utilizes various components such as spinners, panels, and text areas to display and edit simulation parameters. The class also provides methods to retrieve the current editor values and perform actions like clearing and printing text in the simulation information area. Overall, it serves as the interface between the user and the simulation program. |
SimInfoParameters.java | This code defines an interface called SimInfoParameters, which includes methods for clearing a parameter, printing a string, and printing a string followed by a new line. |
GCode.java | The code defines a class for handling GCode instructions. It has a constructor that takes an array of strings as the source code and a method to get the source code array. |
GCodeConstructError.java | The code defines a custom exception class called GCodeConstructError that can be used to handle errors related to G-code construction in a simulation. |
Motor.java | This code defines an enumeration called Motor, which represents three possible values: A, B, and M. It includes a method toChar() which returns the first character of each enum value as a char type. |
GCodeLine.java | The code is a abstract class that represents a line of G-code in a drawing machine simulation. It has functionalities for parsing the G-code string, extracting motor and degree values, calculating the duration, and providing additional information. It also defines abstract methods for calculating the degree at a given timestamp and constructing extra information. |
GCodeLineDefault.java | The code defines a class called GCodeLineDefault, which extends another class called GCodeLine. It has a constructor to initialize the object, a method to calculate degrees based on a timestamp, and overrides a method to construct additional information. |
GCodeLineExpo.java | The GCodeLineExpo class extends the GCodeLine class and represents a specific type of GCode line. It includes functionality to parse and process specific commands ('W' and'T') from the GCode string. The class also has a method to calculate the degree value based on the acceleration and acceleration distance. |
GCodeLineLinear.java | The code defines a class that represents a linear GCode line. It extends a base GCodeLine class and overrides certain methods. It provides functionality to calculate the degree and construct extra information for the GCode line. |
GCodeSequence.java | The GCodeSequence class represents a sequence of GCodeLine objects. It calculates the duration of the sequence based on the duration of the individual lines. It also provides methods to retrieve the lines and duration of the sequence. |
GCodeSnippet.java | This code defines an interface for a GCodeSnippet, which represents a snippet of G-code used in a simulation. It provides methods to get information about the snippet and its duration. |
SimMainView.java | The main functionality of this code is to create and manage the main view of a simulation. It creates a JPanel with a MapPanel, sets the background color, and applies a custom layout. It provides access to the renderer and map panel for further manipulation. |
SimMainViewLayout.java | The code defines a custom layout manager that arranges components in a specific way. It ensures that a central component is always a square in the middle of the container, with the remaining space filled by rectangles. The layout adapts based on whether the container's width or height is greater. |
SimMonitor.java | This code defines the interface for a simulation monitor. It includes methods to access and update simulation speed, steps, progress, and state. |
SimMonitorView.java | The code defines a GUI component for monitoring and controlling a simulation. It includes sliders, buttons, progress bars, and checkboxes for adjusting simulation speed, accuracy, and other settings. It also provides methods for updating the GUI using the simulation's state. |
SimulationSettingView.form | The given code is an XML file that represents a UI form layout. It consists of various components such as labels, sliders, spinners, progress bars, buttons, and checkboxes. These components are arranged in a grid layout to build a graphical user interface for a monitoring view of a simulation. |
BenchmarkTimer.java | The code implements a benchmark timer that can measure the elapsed time between a start and stop point in milliseconds. It offers synchronized methods for thread-safe usage. |
Helper.java | The code includes helper functions for showing error messages, formatting strings, getting caller method and class names, printing class and method names. It also has a function to get the number of available processors. |
ImageUtils.java | The code defines a utility class that provides a method to resize an image. It takes an original image, target dimensions, creates a new BufferedImage, and returns the resized image. |
NumberUtils.java | The code defines a utility class NumberUtils that checks if an object or a string can be parsed into a double value. It returns true if the input is a valid double and false otherwise. |
Coordinator.java | The code defines an interface for a Coordinator, which is responsible for creating, loading, and saving objects of a given type T to and from files. The interface requires implementations to provide methods for creating an object with a specific name, loading an object from a file, and saving an object to a file. |
FileHub.java | The code defines the FileHub interface, which provides methods to open and create file pages. It takes a File object or a name parameter as inputs. |
FileHubUnderLayPanel.java | The code defines a custom JPanel subclass called FileHubUnderLayPanel. It sets border thickness and overrides the paintComponent method to paint a colored background. |
FileHubView.java | The FileHubView class is a component of a graphical user interface that manages tabs for different file views. It adds and removes tabs, loads and saves files, and creates tab components with labels and exit buttons. It interacts with coordinator objects to handle specific file types. |
FileView.java | This code provides a base class for a file view in a drawing machine application. It includes functionality for managing file properties, accessing the file's absolute path, and obtaining an object to save. It also includes a nested class for an exit button with a click action. |
SimGCodeTab.java | The code defines a SimGCodeTab class that represents a panel for editing and loading GCode. It sets up a syntax-highlighting text editor, loads GCode from a provided SimProgramInfo object, and provides a method to load the GCode, optionally filtering out comment lines. |
SimProgramCoordinator.java | The SimProgramCoordinator class is responsible for coordinating the creation, loading, and saving of simulation program files in the DrawMachine application. It interacts with the SimProgramLoader and FileHubView to handle these functionalities. |
SimProgramFileView.java | The code defines a view for a simulation program file. It includes tabs for simulation and GCode, uses a data collector, and provides access to the tabs and program data. |
SimSimulationTab.java | The code defines the SimSimulationTab class, which is a JPanel containing a SimEditorView and a SimView. It provides a way to create a vertical split layout between the two components of specified sizes. |
ItemDivider.java | The ItemDivider class is a specialized JMenuItem that creates a non-selectable menu item with a dividing line. It can be customized with a specific font size. It is commonly used to visually separate menu items or sections within a menu. |
Logo.java | The Logo class is a custom JMenu component that displays an image as its icon. It overrides the paintComponent method to draw the image and sets the component's text to be blank. It also provides a method to disable the component's clickability. |
Menu.java | The code defines a custom Menu component in a Swing application for creating menus. It extends JMenu to provide additional functionality for adding menu items. |
MenuBar.java | The MenuBar class is responsible for creating and managing the menu bar in a graphical user interface. It provides methods to add menus and menu items, and it registers color changes for menu backgrounds and foregrounds. The menus include options for file management, editing, theme settings, and help. It also allows choosing a design color through a color picker. |
NewProgramAction.java | The code defines the functionality for creating a new file in the DrawMachineSim program. It prompts the user to enter a name for the new file and then creates a new file with that name and open it in a new tab. |
OpenWorkspaceAction.java | The code defines the "OpenWorkspaceAction" class, which is responsible for handling the action of opening a workspace. When triggered, it presents a file chooser dialog where the user can select a directory representing the workspace. Upon selection, the code retrieves the chosen directory and loads it into the DrawMachineSim application's workspace view. |
SaveAllProgramAction.java | This code implements the "Save All" functionality for a menu item. When triggered, it saves all program data using the DrawMachineSim class and its associated file hub. Any exceptions encountered are propagated as runtime exceptions. |
SaveProgramAction.java | The code defines a SaveProgramAction class that represents an action to save a program. It is triggered when an event occurs, and it saves the program using the FileHub of the DrawMachineSim's view. |
Workspace.java | The code defines an interface for a workspace, providing methods to load a workspace from a file and retrieve the directory path where the workspace is located. |
WorkspaceDir.java | The code defines a class called WorkspaceDir that extends WorkspaceElement . It represents a directory in a workspace. It has a constructor to initialize the path of the directory. It also overrides the delete() and rename() methods from the parent class. |
WorkspaceElement.java | This code defines an abstract class called WorkspaceElement for managing elements in a workspace. It controls file functionalities like deletion and renaming while extending a tree node. The class provides a constructor and a method to check if the element is a file. |
WorkspaceFile.java | The code defines a WorkspaceFile class that represents a file in the workspace. It extends the WorkspaceElement class and stores a reference to the actual file. It provides methods to retrieve the file, check if it is a file, and implements abstract methods for deleting and renaming the file. |
WorkspaceTree.java | The code defines a custom class called WorkspaceTree, which extends JTree. It provides methods to reset the tree, reload the tree model, and retrieve the root node. The reset method removes all the children of the root node, sets its user object to "..." and reloads the tree. The reload method reloads the tree model. |
WorkspaceView.java | The code creates a workspace view in a Swing application that displays a file hierarchy. It allows users to load a workspace from a file and detects changes in the workspace. Users can open files by double-clicking on them in the workspace view. The code is designed to be flexible and customizable through various handlers. |
Before you begin, ensure that you have the following prerequisites installed:
โน๏ธ Requirement 1
โน๏ธ Requirement 2
โน๏ธ ...
- Clone the DrawMachineSim repository:
git clone https://github.com/GodGotzi/DrawMachineSim
- Change to the project directory:
cd DrawMachineSim
- Install the dependencies:
mvn clean install
java -jar target/myapp.jar
mvn test
โน๏ธ Task 1: Implement X
โน๏ธ Task 2: Refactor Y
โน๏ธ ...
This project is licensed under the โน๏ธ INSERT-LICENSE-TYPE
License. See the LICENSE file for additional info.
โน๏ธ List any resources, contributors, inspiration, etc.