give some love

This commit is contained in:
Max Halford 2021-12-22 18:49:31 +01:00
parent 8fb1ee048d
commit 3f38d34694
5 changed files with 225276 additions and 1 deletions

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Max Halford
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,6 +1,49 @@
# svg2stl
This repository provides a script which takes as input an SVG such as this one:
![example.svg]
It outputs an [STL file](https://www.wikiwand.com/en/STL_(file_format)) like this one:
![example.png]
The resulting solid is a cuboid with holes in it. It essentially adds a third dimension to the SVG file. The purpose of the output STL is to be fed into a 3D printer. The end goal is to make a physical [stencil](https://www.wikiwand.com/en/Stencil) for artistic purposes.
## Installation
```sh ```sh
git clone https://github.com/MaxHalford/svg2stl git clone https://github.com/MaxHalford/svg2stl
cd svg2stl cd svg2stl
pip install -r requirements.txt pip install -r requirements.txt
```
## Usage
You can generate an STL with the same name as the input file like this:
```py
python svg2stl.py example.svg --thickness 4 python svg2stl.py example.svg --thickness 4
``` ```
You can also show what this looks like in a GUI:
```py
python svg2stl.py example.svg --thickness 4 --show
```
## How it works
- The SVG file is parsed into a sequence of steps thanks to [`svg.path`](https://github.com/regebro/svg.path).
- Each step is turned into 2D geometric coordinates by sampling from each step's parametric equation with [`numpy`](https://numpy.org/).
- Each coordinate is duplicated so that there are top and bottom coordinates.
- The coordinates are stitched together to define panes: a floor, a ceiling, and many walls.
- [`pygmsh`](https://github.com/nschloe/pygmsh) does the heavy lifting. It generates a mesh of triangles from the panes through [constrained Delaunay triangulation](https://www.wikiwand.com/en/Constrained_Delaunay_triangulation).
## Motivation
There are some websites out there that already do this. Like [this](https://svg2stl.com/), [this](https://activmap.github.io/svg-to-stl/), and [this](https://github.com/rcalme/svg-to-stl). But they're websites, and sometimes it's nice to be able to do this from the command line. Especially if you want to process many SVGs.
## License
The MIT License (MIT). Please see the [license file](LICENSE) for more information.

BIN
example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

225206
example.stl Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
import argparse import argparse
import pathlib
from xml.dom import minidom from xml.dom import minidom
import gmsh import gmsh
@ -17,6 +18,7 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Convert an SVG into an STL.") parser = argparse.ArgumentParser(description="Convert an SVG into an STL.")
parser.add_argument("svg_path", type=str, help="path towards an SVG file") parser.add_argument("svg_path", type=str, help="path towards an SVG file")
parser.add_argument("--thickness", default=1, type=float) parser.add_argument("--thickness", default=1, type=float)
parser.add_argument("--show", dest="show", action="store_true", default=False)
args = parser.parse_args() args = parser.parse_args()
steps = parse_svg_into_steps(args.svg_path) steps = parse_svg_into_steps(args.svg_path)
@ -147,4 +149,7 @@ if __name__ == "__main__":
gmsh.model.geo.synchronize() gmsh.model.geo.synchronize()
gmsh.model.mesh.generate() gmsh.model.mesh.generate()
gmsh.write(str(pathlib.Path(args.svg_path).with_suffix(".stl")))
if args.show:
gmsh.fltk.run() gmsh.fltk.run()