4 releases (breaking)
0.7.0 | Mar 23, 2025 |
---|---|
0.6.0 | Mar 14, 2025 |
0.5.0 | Mar 8, 2025 |
0.4.0 | Mar 7, 2025 |
#8 in #generative
Used in 2 crates
410KB
8K
SLoC
Plottery
Plottery is a genererative art engine for pen-plotters written in Rust.
- plottery_lib (crates.io): Core library – Contains the functionality to generate art. This includes shapes, geometry helpers, structs for composition and other tools.
- plottery_editor: Plottery Editor (releases) – The GUI Application to create, manage and run projects, preview artworks and control the plotter hardware.
- plottery_server: Controller for the pen-plotter hardware – The server offers a http interface to send tasks to execute on the hardware and controls the motors. This is highly customized to my personal DIY pen-plotter.
- plottery_cli (crates.io): Command line interface to create and run projects.
- plottery_project (crates.io): Library containing functionality to handle Plottery projects.
Editor
The Editor lets you manage, preview and run Plottery projects.
Projects
Create
To create a new project either use the editor or the command line interface (CLI) like so:
cargo install plottery_cli
plottery new /path/to/folder awesome_project
Projects in Plottery are a wrapper around a regular cargo project. They support a couple of commands when run directly:
cargo run svg # run project and open the result as .svg
cargo run -- --help # get some info
The editor can also be used to run a project and tweak its input parameters.
Parameters
Projects expose parameters as a struct:
#[derive(PlotteryParams)]
pub struct Params {
num_points: i32,
points_distance: f32,
}
Generate
generate.rs
defines the function used to generate the art. It receives an instance of Params
as an argument and returns a Layer
:
pub fn generate(params: Params) -> Layer {
let mut l = Layer::new();
/* Generate your art here! */
l.with_name("root").optimize_recursive()
}
Example
This project generates a spiral masked inside a rectangle:
use plottery_lib::*;
use plottery_project::*;
// These project parameters are exposed in the Plottery Editor.
#[derive(PlotteryParams)]
pub struct Params {
#[value(2_000)]
num_points: i32,
#[value(10.0)]
rotations: f32,
}
pub fn generate(params: Params) -> Layer {
let mut l = Layer::new();
let size = V2::a6(); // DIN-A6 paper size
let frame = Frame::new(
size,
size.min_axis() * 0.1, // 10% margin of smallest side
);
// add outer border as a paper cutting guide
l.push_rect(frame.outer_rect());
// generate spiral by collecting from iterator of points
let path: Path = (0..params.num_points)
.map(|i| {
let angle =
Angle::from_rotations(i as f32 / params.num_points as f32) * params.rotations;
let radius = i as f32 * 0.005;
V2::polar(angle, radius)
})
.collect::<Path>() // collect points into a Path
.translate(frame.center()); // translate spiral to center of frame
// mask path to the inner rect of the frame (outer frame without the margin)
let masked_path = path.mask_brute_force(&frame.inner_rect().into(), SampleSettings::default());
// push all elements of inside the inner frame to `l` flat
l.push_layer_flat(masked_path.inside);
l.with_name("root").optimize_recursive()
}
Dependencies
~13–25MB
~359K SLoC