UNPKG

@jakebeamish/penplotting

Version:

A JavaScript framework for making SVG files for penplotters.

180 lines (129 loc) 5.19 kB
# Penplotting.js ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/jakebeamish/Penplotting.js/node.js.yml?style=flat&label=tests) Penplotting.js is a JavaScript framework for making generative art in SVG format for penplotters. This project is a personal project, and as such, it is a work-in-progress. New features and breaking changes are expected in future updates. Use at your own discretion, feel free to contribute and raise issues. ## Features - Shapes and geometry classes: Vector, Point, Line, Path, Circle, AABB, Matrix - Seedable PRNG implementations with useful methods - Quadtree for optimised nearest-neighbour search - Paper sizes ## Installation ```sh npm i @jakebeamish/penplotting ``` ## Usage To start a new plot, run ```sh npx new-plot ``` This command runs a shell script that will create boilerplate `index.html`, `style.css` and `plot.js` files in the current working directory. Inside `plot.js`, adjust the options for initializing the plot. A full list of options can be found in the [Plot constructor docs](https://jakebeamish.github.io/Penplotting.js/Plot.html#constructor). ```js const plot = new Plot({ units: "mm", title: "My amazing plot", size: Paper.A5, strokeWidth: 0.05, }); ``` The image is defined in a `plot.generate()` function in which Vectors and other shape objects can be created, manipulated, and added to the SVG document with `plot.add(shapes)`, where `shapes` is a shape or an array of shapes. For a complete overview, see the [API Documentation](https://jakebeamish.github.io/Penplotting.js/). ```js import { Plot, Vector, Triangle, Line, AABB, Circle, Path, PAPER, PRNG, } from "@jakebeamish/penplotting"; // Setup a new plot with configuration options let plot = new Plot({ size: PAPER.A6.landscape(), backgroundColor: "white", strokeWidth: 0.3, }); // Create the work inside the plot.generate() function plot.generate = () => { // Initialise PRNG const prng = new PRNG({ seed: plot.seed.decimal }); // Destructure the plot size for easy access to width and height const { width, height } = plot.size; // The Vector constructor takes up to three parameters x, y, and z // If an argument is not given for a coordinate, the default value is 0 const centre = new Vector(width / 2, height / 2); // Lines can be created using the constructor, or the fromArray static method // which requires an array in the format [x1, y1, x2, y2] const line = Line.fromArray([30, centre.y - 10, 30, centre.y + 10]); // Shapes are added to the SVG using plot.add() plot.add(line); // Circles can be created in a similar way. It requires a position (either as // a Vector or as individual coordinates), and a radius const circle = Circle.fromVector(new Vector(50, centre.y), 10); plot.add(circle); const square = new AABB(80, centre.y, 10, 10); const triangle = new Triangle( new Vector(100, centre.y + 10), new Vector(110, centre.y - 10), new Vector(120, centre.y + 10) ); // AABBs and Triangles can't be added to a plot directly - the lines() method // can be used to return an array of lines that compose the shape // plot.add() can be given an (optionally nested) array to add multiple shapes plot.add([square.lines(), triangle.lines()]); let randomPoints = []; for (let i = 0; i < 30; i++) { randomPoints.push( Vector.lerp(new Vector(30, 20), new Vector(width - 20, 20), i / 30).add( new Vector(0, prng.randomBipolarFloat() * 5) ) ); } let randomPath = new Path(randomPoints); let sinPoints = []; for (let i = 0; i < 100; i++) { sinPoints.push( Vector.lerp( new Vector(30, height - 20), new Vector(width - 20, height - 20), i / 100 ).add(new Vector(0, Math.sin((i / 100) * Math.PI * 10) * 3)) ); } let sinPath = new Path(sinPoints); plot.add([randomPath, sinPath]); }; plot.draw(); ``` Calling `plot.draw()` at the end of the file generates an SVG element and UI inside `index.html`, which can be viewed in a browser. The above code results in the following output: ![demo screenshot](https://github.com/jakebeamish/Penplotting.js/blob/main/assets/demo_screenshot.png) ### Keyboard shortcuts | Action | Key | | --------------------------- | --- | | Download an SVG file | `d` | | Regenerate with random seed | `r` | ### Plotting the SVG files The SVG file can be downloaded and optionally processed further. Personally, I use vpype to optimise the file, and then the axidraw Inkscape plugin to control the plotter. ## Contributing Contributions are welcome. Issues, comments and Pull Requests can be made at https://github.com/jakebeamish/penplot-svg-tool/issues. The project is tested using jest. Documentation is generated using JSDoc. ## License This project is licensed under the MIT License. See the [LICENSE.md](https://github.com/jakebeamish/Penplotting.js/blob/main/LICENSE.md) file for details. ## Acknowledgements This project incorporates code from: - [CodingTrain/Quadtree](https://github.com/CodingTrain/Quadtree) - Licensed under the MIT License.