Updates:
- 2021/09/16: publishing this blog-post finally
- 2021/09/04: 0.8.6: supporting OFF, OBJ, AMF, 3MF and 3MJ in addition to STL
- 2021/04/11: 0.8.5: more tests and Makefiles added
- 2021/04/06: 0.8.4: SVG export working with example, various bug fixes
- 2021/04/04: 0.8.3: first print actually working (extrusion calculation fixed, removed most un/retract for now)
- 2021/04/02: starting write-up
Table of Contents
Introduction
Since I started to develop on the conic slicer slicer4rtn
for the RTN, and starting to work on the more complex PAXSlicer for 5-axis printer like PAX option. So I was searching for a slicer to adapt for future projects to have more control of the slicer stage and learn of the actual details and so I came across Mandoline Py, a slicer coded in Python utilizing at its core pyclipper and at first glance it was well thought out, clean code, yet not many comments but function names and variables were explanatory – I was quite impressed by Revar Desmera, who was able to put this together in such a consistent manner.
There wasn’t much information available otherwise, and the author did not reply to my emails, so I looked at past closed issues at github, which gave me a bit background information, and the challenges Revar faced.
So, after a couple of weeks pondering and waiting for Revar to respond, April 4 2021 I began to adopt it and push it forward to become usable for me. I will document all future changes (or possible a fork of it) on this blog-post.
Features
- purely written in Python, compact source code, easy to read & understand
vector.py
: base vector operationspoint3d.py
: x,y,z to index to x,y,zline_segment3d.py
: two points making a line, with cachingfacet3d.py
: three points making a triangle/facet, with cachingfacet.slice_at_z(z)
geometry2d.py
: uses pyclipper- provides path operations like offset, union, diff, clip, paths_contain (point in paths)
- makes infill patterns like lines, grid, triangles, hexagons
model3d.py
: STL reader & writer, OBJ, OFF, 3MF, AMF, 3MJ reader- indexing points, edges and facets
model.slice_at_z(z, lh)
results in polygons/paths
slicer.py
: slicing the model- generating perimeters
- generating support
- generating adhesion (skirt, brim, raft)
- generating solid & sparse infill
- pathing: coordinates perimeters, support, adhesion, infill paths
- converting paths into Gcode (or SVG)
__init__.py
: main entry point ofmandoline
program:- process arguments
- load model and relevel, apply model operations (scale), check manifoldness
- slice model
- slice model into Gcode to print via FDM 3D printer
- slice model to SVG slices (very experimental) for debugging purposes and possibly to post-process to pixel-based slices for SLA or SLS 3D printer (not yet tested)
- load mutiple configs in sequence with
-l config.ini
, e.g. printer specifics, material settings - simple to query features/settings with
-Q <term>
Usage
% mandoline
== Mandoline Py 0.8.5 == https://github.com/(Spiritdude|revarbat)/mandoline-py
usage: mandoline [-h] [-o OUTFILE] [-n] [-g] [-v] [-d] [--no-raft] [--raft] [--brim] [--no-support] [--support] [--support-all]
[-f MATERIAL,...] [-F FORMAT] [-l OPTNAME] [-M OPTNAME=VALUE] [-S OPTNAME=VALUE] [-Q OPTNAME] [-w]
[--help-configs] [--show-configs]
[infile]
positional arguments:
infile Input model filename (STL).
optional arguments:
-h, --help show this help message and exit
-o OUTFILE, --outfile OUTFILE
Slices model (STL) and write GCode or SVGs to file.
-n, --no-validation Skip performing model validation.
-g, --gui-display Show sliced paths output in GUI.
-v, --verbose Show verbose output.
-d, --debug Show debug output.
--no-raft Force adhesion to not be generated.
--raft Force raft generation.
--brim Force brim generation.
--no-support Force external support structure generation.
--support Force external support structure generation.
--support-all Force external support structure generation.
-f MATERIAL,..., --filament MATERIAL,...
Configures extruder(s) for given materials, in order. Ex: -f PLA,TPU,PVA
-F FORMAT, --format FORMAT
Set output format (gcode, svg)
-l OPTNAME, --load OPTNAME
Load config file, containing <k>=<v> lines
-M OPTNAME=VALUE, --model OPTNAME=VALUE
Set model manipulation operation(s) (scale).
-S OPTNAME=VALUE, --set-option OPTNAME=VALUE
Set a slicing config option.
-Q OPTNAME, --query-option OPTNAME
Display a slicing config option value.
-w, --write-configs Save any changed slicing config options.
--help-configs Display help for all slicing options.
--show-configs Display values of all slicing options.
examples:
mandoline cube.stl
mandoline -l myprinter.ini cube.stl
mandoline -l myprinter.ini -S layer_height=0.3 cube.stl
mandoline -l myprinter.ini -l petg.ini -S infill_type=Triangles cube.stl -o test.gcode
mandoline -Q skirt
Download
https://github.com/Spiritdude/mandoline-py
Formats
Gcode
By default Mandoline slices STL into 3D printable Gcode:
% mandoline -l y3228.ini hollowCube.stl -S layer_height=0.3 -o test.gcode
== Mandoline Py 0.8.4 == https://github.com/revarbat/mandoline-py
Loading model "hollowCube.stl"
Loading configs from "y3228.ini"
Slicing starting
+ Random offset -78,34
- Perimeters
- Support
- Raft[ ], Brim[ ], and Skirt[x]
- Infill (Grid)
- Pathing
- Export GCode to "test.gcode"
Took 0.85s total. Estimated build time: 0h 08m, filament used: 1.394m
SVG
Mandoline (0.8.4+) also supports slicing into SVG, for debugging purpose and possibly can be post-processed into PNG to feed into a SLA or SLS 3D printer (no support-structure included yet).
% mandoline hollowCube.stl -o test.svg
== Mandoline Py 0.8.4 == https://github.com/revarbat/mandoline-py
Loading model "hollowCube.stl"
Slicing starting
- Perimeters
- Export 66x SVGs to "test-*.svg"
Took 0.23s total.
Issues to Resolve
- model slicing problems:
- 3D Benchy incomplete, get more linient or auto-fix regarding non-manifolds:
- 3DBenchy.stl loaded with manifold checking, 10x “non-manifold hole edges”:
- Z = 9.087, 5.87
- when disregarding that check with
-n
, then it results in various warnings “Incomplete Polygon …” which results in missing slices – major degration of 3D print - sliced with many warnings (
Incomplete Polygon at z=...
=> missing layers) @0.2mm layer height: 240 layers, 4.011m with 1.75mm filament - sliced with many warnings (=> missing layers) @0.25mm layer height: 192 layers, 4.461m with 1.75mm filament
-M scale=0.5
with- @0.2mm layer height with warnings (=> missing layers): 120 layers, 0.674m with 1.75mm filament
- @0.25mm layer height with warnings (=> missing layers): 96 layers, 0.634m with 1.75mm filament- fixing
- 3DBenchy.stl loaded with manifold checking, 10x “non-manifold hole edges”:
- Voron Design Cube v7 wrong sliced layers without warnings
- 3D Benchy incomplete, get more linient or auto-fix regarding non-manifolds:
- random crashs of pyclipper: I noticed a basic model with
random_pos=True
enabled slices correct and another time when moved to another position fails to slice - properly do un/retract:
- find out if perimeters/walls are crossed, if not, do not un/retract no matter what
TYPE
of extrusion is done
- find out if perimeters/walls are crossed, if not, do not un/retract no matter what
- allow case-insensitive settings:
infill_type
support_type
adhesion_type
bed_geometry
- brim, raft and skirt properly done (*_width vs *_lines and *_offset)
- bottom_layer_extrusion_width
- bottom_layer_speed
- top_layer_speed
- wall/shell/perimeter_speed
- resolve “shell” vs “wall” vs “perimeter” in source variables, source comments and config
infill_type=Hexagons
doesn’t work reliable, often infill is missing entirelysupport 3MF, 3MJ input format beside STL, since 0.8.6: obj, off, amf, 3mf and 3mj- properly support multi-volume -> multi-material -> multi-tool
- 3MF:
examples, Debian package: python3-savitar, since 0.8.6 using XML parser
- clean up multi-nozzle setup, remove GUI, remove material config but hand it over to a collection of .ini files to be selectable with
-l my.ini
… (not yet finalized how to achieve simple multi-nozzle config easy) - testing, testing and testing more
- future developement
- integrate geometry3d union, intersection for segmenting sub-volumes
- analyze geometry from non-planar slicing perspective
- integrate non-planar slicing: tilted, cyclindrical, conic and spherical at a deeper level
- mature it to become optional for PAXSlicer 5-axis slicer
- process metadata from .3mj either piece, sub-volume or face exact within the slicing (tool changing, fill density, slicing settings etc)
Changes
- 2021/09/04: 0.8.6:
- experimental OFF, OBJ, 3MF, 3MJ support
- experimental OFF, OBJ, 3MF, 3MJ support
- 2021/04/08: 0.8.5:
- cli:
-S shell_speed=s
[mm/s]
- cli:
- 2021/04/06: 0.8.4:
- SVG output: supporting slicing to SVG, using “
-o test.svg
“, very experimental - intern:
model.scale([x,y,z])
implemented - cli: support for
-M scale=s
or-M scale=x,y,z
- intern: fixed vector.py
normalize()
and__truediv__()
supporting STL with bad normals - un/retract enabled again in code
- SVG output: supporting slicing to SVG, using “
- 2021/04/04: 0.8.3:
- cli & extending configs:
cool_fan_speed_{min/max}
cool_fan_full_layer=2
, e.g. starting fan after e.g. layer 2 is reached, first layer is 0start_gcode
andend_gcode
and new config type ‘str
‘ as wellskirt_lines=3
only considered ifskirt_layers
!= 0gcode_comments=True|False
: adding various useful info in Gcoderandom_pos=True|False
: randomize position of model on the build-plate
- all the config included in Gcode given
gcode_comments
enabled - intern: carrying over ‘
typ
‘ (‘type’ in python 😉 ) of the extrusion in_raw_add_paths
, to refine the retract/unretract, this allowed to - have output Gcode more descriptive with
;TYPE:..
likePERIMETER
,INFILL
,PRIME
,BRIM
,SKIRT
,SUPPORT
etc, givengcode_comments
is enabled - cli: support
-l
or--load
to load more configs (e.g. per printer, or material) - cli: support
-Q <term>
partial match - output “filament used …[m]” at the end of slicing
- most un/retract disabled for now to confirm extrusion calculation working
- prints simple models like 10/20mm cube and xyzHollowCalibrationCubeV2
- cli & extending configs:
References
- Mandoline Py, original repository
- Mandoline Py, my repo with my changes
- Gcode 2 PNG