Tag Archives: Slicer

3D Printing: Mandoline Slicer


  • 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
20mm xyzHollowCalibrationCubeV2 sliced with Mandoline 0.8.5


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.


  • purely written in Python, compact source code, easy to read & understand
    • vector.py: base vector operations
    • point3d.py: x,y,z to index to x,y,z
    • line_segment3d.py: two points making a line, with caching
    • facet3d.py: three points making a triangle/facet, with caching
      • facet.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 of mandoline 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>


% 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]

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
                        Set model manipulation operation(s) (scale).
                        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.

   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





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         


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
    • Voron Design Cube v7 wrong sliced layers without warnings
  • 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
  • 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 entirely
  • support 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)


  • 2021/09/04: 0.8.6:
    • experimental OFF, OBJ, 3MF, 3MJ support
  • 2021/04/08: 0.8.5:
    • cli: -S shell_speed=s [mm/s]
  • 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
  • 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 0
      • start_gcode and end_gcode and new config type ‘str‘ as well
      • skirt_lines=3 only considered if skirt_layers != 0
      • gcode_comments=True|False: adding various useful info in Gcode
      • random_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:.. like PERIMETER, INFILL, PRIME, BRIM, SKIRT, SUPPORT etc, given gcode_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


3D Printing: Kiri:Moto CLI Slicer


  • 2021/09/27: -l <conf> to load configurations (experimental)
  • 2021/08/27: software released on github
  • 2021/08/09: KiriMotoSlicer 0.0.4: -h <term> to query settings, setting extruder.0.*
  • 2021/08/08: KiriMotoSlicer 0.0.2: usage output (help), preliminary integration into Print3r framework
  • 2021/08/02: starting write-up


Kiri:Moto is a browser-based slicer, which can be also installed locally using NodeJS. Stewart Allen developed it and even provides a command-line interface (CLI) example as well src/kiri/cli.js. I extended it further into kirimoto-slicer so I could use it in conjunction of Print3r.


  • Node 13 or later (use nvm to switch quickly between different versions)
  • UNIX platform (Linux, etc)


git clone https://github.com/Spiritdude/KiriMotoSlicer


make requirements
sudo make install 

requirements clones original grid-apps (Kiri:Moto) whereas install installs KiriMotoSlicer (kirimoto-slicer) executable system-wide.


KiriMotoSlicer 0.0.4 USAGE: [<options>] [file] ...
      --help                        this usage help
      --help=<term>                 show settings matching <term>
      -h <term>                        "       "
      --version                     display version and exit
      --verbose                     increase verbosity
      -v or -vvv                       "       "
      --output=<fn>                 force output filename
      -o <fn>                          "       "
      --load=<conf>                 load configuration (lines of <k>=<v>, or experimental JSON as grid-apps/src/dev/*)
      -l <conf>                              "                "                      "
      --setTemperature=<s>          include set temperature extruder & bed in gcodePre (default: true)
      --bedOrigin=<x>,<y>           set origin of bed (use with --outputOriginCenter=true) (default: [0,0])

   slice configuration:
      --processName=<v>             set process name (default: "generic")
      --sliceHeight=<v>             set slice height (default: 0.25)
      --sliceShells=<v>             set slice shells (default: 3)
      --sliceShellOrder=<v>         set slice shell order ["in-out","out-in"] (default: "in-out")
      --sliceLayerStart=<v>         set slice layer start ["last","center","origin"] (default: "last")
      --sliceFillAngle=<v>          set slice fill angle (default: 45)
      --sliceFillOverlap=<v>        set slice fill overlap (default: 0.3)
      --sliceFillSparse=<v>         set slice fill sparse (default: 0.2)
      --sliceFillType=<v>           set slice fill type ["vase","hex","grid","gyroid","triangle","linear","bubbles"] (default: "gyroid")  
      --sliceAdaptive=<v>           set slice adaptive (default: false)
      --sliceMinHeight=<v>          set slice min height (default: 0)
      --sliceSupportDensity=<v>     set slice support density (default: 0.25)
      --sliceSupportOffset=<v>      set slice support offset (default: 0.4)
      --sliceSupportGap=<v>         set slice support gap (default: 1)
      --sliceSupportSize=<v>        set slice support size (default: 6)
      --sliceSupportArea=<v>        set slice support area (default: 1)
      --sliceSupportExtra=<v>       set slice support extra (default: 0)
      --sliceSupportAngle=<v>       set slice support angle (default: 50)
      --sliceSupportNozzle=<v>      set slice support nozzle (default: 0)
      --sliceSolidMinArea=<v>       set slice solid min area (default: 10)
      --sliceSolidLayers=<v>        set slice solid layers (default: 3)
      --sliceBottomLayers=<v>       set slice bottom layers (default: 3)
      --sliceTopLayers=<v>          set slice top layers (default: 3)
      --firstLayerRate=<v>          set first layer rate (default: 10)
      --firstLayerPrintMult=<v>     set first layer print mult (default: 1.15)
      --firstLayerYOffset=<v>       set first layer YOffset (default: 0)
      --firstLayerBrim=<v>          set first layer brim (default: 0)
      --firstLayerBeltLead=<v>      set first layer belt lead (default: 3)
      --sliceSkirtCount=<v>         set slice skirt count (default: 0)
      --sliceSkirtOffset=<v>        set slice skirt offset (default: 2)
      --sliceLineWidth=<v>          set slice line width (default: 0)
      --outputTemp=<v>              set output temp (default: 210)
      --outputBedTemp=<v>           set output bed temp (default: 60)
      --outputFeedrate=<v>          set output feedrate (default: 50)
      --outputFinishrate=<v>        set output finishrate (default: 50)

      --outputSeekrate=<v>          set output seekrate (default: 80)
      --outputShellMult=<v>         set output shell mult (default: 1.25)
      --outputFillMult=<v>          set output fill mult (default: 1.25)
      --outputSparseMult=<v>        set output sparse mult (default: 1.25)
      --outputRetractDist=<v>       set output retract dist (default: 4)
      --outputRetractSpeed=<v>      set output retract speed (default: 30)
      --outputRetractDwell=<v>      set output retract dwell (default: 30)
      --outputShortPoly=<v>         set output short poly (default: 100)
      --outputMinSpeed=<v>          set output min speed (default: 10)
      --outputCoastDist=<v>         set output coast dist (default: 0.1)
      --outputLayerRetract=<v>      set output layer retract (default: true)
      --detectThinWalls=<v>         set detect thin walls (default: true)
      --zHopDistance=<v>            set z hop distance (default: 0)
      --antiBacklash=<v>            set anti backlash (default: 0)
      --outputOriginCenter=<v>      set output origin center (default: false)
      --sliceFillRate=<v>           set slice fill rate (default: 0)
      --sliceSupportEnable=<v>      set slice support enable (default: false)
      --firstSliceHeight=<v>        set first slice height (default: 0.25)
      --firstLayerFillRate=<v>      set first layer fill rate (default: 35)
      --firstLayerLineMult=<v>      set first layer line mult (default: 1)
      --firstLayerNozzleTemp=<v>    set first layer nozzle temp (default: 0)
      --firstLayerBedTemp=<v>       set first layer bed temp (default: 0)
      --firstLayerBrimTrig=<v>      set first layer brim trig (default: 0)
      --outputRaft=<v>              set output raft (default: false)
      --outputRaftSpacing=<v>       set output raft spacing (default: 0.2)
      --outputRetractWipe=<v>       set output retract wipe (default: 0)
      --outputBrimCount=<v>         set output brim count (default: 2)
      --outputBrimOffset=<v>        set output brim offset (default: 2)
      --outputLoopLayers=<v>        set output loop layers (default: null)
      --outputInvertX=<v>           set output invert x (default: false)
      --outputInvertY=<v>           set output invert y (default: false)
      --arcTolerance=<v>            set arc tolerance (default: 0)
      --gcodePause=<v>              set gcode pause (default: "")
      --ranges=<v>                  set ranges (default: [])
      --firstLayerFanSpeed=<v>      set first layer fan speed (default: 0)
      --outputFanSpeed=<v>          set output fan speed (default: 255)

   device configuration:
      --noclone=<v>                 set noclone (default: false)
      --mode=<v>                    set mode ["FDM","SLA","CNC","Laser"] (default: "FDM")
      --internal=<v>                set internal (default: 0)
      --imageURL=<v>                set image URL (default: "")
      --imageScale=<v>              set image scale (default: 0.75)
      --imageAnchor=<v>             set image anchor (default: 0)
      --bedHeight=<v>               set bed height (default: 2.5)
      --bedWidth=<v>                set bed width (default: 220)
      --bedDepth=<v>                set bed depth (default: 220)
      --bedRound=<v>                set bed round (default: false)
      --bedBelt=<v>                 set bed belt (default: false)
      --maxHeight=<v>               set max height (default: 300)
      --originCenter=<v>            set origin center (default: false)
      --extrudeAbs=<v>              set extrude abs (default: true)
      --spindleMax=<v>              set spindle max (default: 0)
      --gcodeFan=<v>                set gcode fan (default: "M106 S{fan_speed}")
      --gcodeTrack=<v>              set gcode track (default: "")
      --gcodeLayer=<v>              set gcode layer (default: ";LAYER:{layer}")
      --gcodePre=<v>                set gcode pre (default: "M107                     ; turn off filament cooling fan\nG90          
            ; set absolute positioning mode\nM82                      ; set absolute positioning for extruder\nM104 S{temp} T{tool} 
    ; set extruder temperature\nM140 S{bed_temp} T{tool} ; set bed temperature\nG28                      ; home axes\nG92 X0 Y0 Z0 E
0          ; reset all axes positions\nG1 X0 Y0 Z0.25 F180      ; move XY to 0,0 and Z 0.25mm over bed\nG92 E0                   ; z
ero the extruded\nM190 S{bed_temp} T{tool} ; wait for bed to reach target temp\nM109 S{temp} T{tool}     ; wait for extruder to reac
h target temp\nG92 E0                   ; zero the extruded\nG1 F225                  ; set feed speed")
      --gcodePost=<v>               set gcode post (default: "M107                     ; turn off filament cooling fan\nM104 S0 T{to
ol}          ; turn off right extruder\nM140 S0 T{tool}          ; turn off bed\nG1 X0 Y300 F1200         ; end move\nM84           
           ; disable stepper motors")
      --gcodeProc=<v>               set gcode proc (default: "")
      --gcodePause=<v>              set gcode pause (default: "")
      --gcodeDwell=<v>              set gcode dwell (default: "")
      --gcodeSpindle=<v>            set gcode spindle (default: "")
      --gcodeChange=<v>             set gcode change (default: "")
      --gcodeFExt=<v>               set gcode FExt (default: "gcode")
      --gcodeSpace=<v>              set gcode space (default: true)
      --gcodeStrip=<v>              set gcode strip (default: false)
      --gcodeLaserOn=<v>            set gcode laser on (default: "")
      --gcodeLaserOff=<v>           set gcode laser off (default: "")
      --extruders.[0..<n-1>].{extFilament,extNozzle,extSelect,extDeselect,extOffsetX,extOffsetY}=<v> set extruders (default: [{"extFilament":1.75,"extNozzle":0.5,"extSelect":["T0"],"extDeselect":[],"extOffsetX":0,"extOffsetY":0}])
      --new=<v>                     set new (default: false)
      --deviceName=<v>              set device name (default: "3D Printer")

      kirimoto-slicer cube.stl
      kirimoto-slicer cube.stl -o test.gcode
      kirimoto-slicer -v cube.stl --sliceHeight=0.1
      kirimoto-slicer cube.stl --extruders.0.extNozzle=0.5 --sliceHeight=0.42
      kirimoto-slicer -h slice
      kirimoto-slicer -h .


Kiri:Moto distincts:

  • shells (aka perimeters, walls)
  • solid fill (like bottom and top layers)
  • sparse fill (aka fill)

As of 2021/08 Kiri:Moto doesn’t distinct support structures on bed or everywhere, so it can only be enabled or disabled with --sliceSupportEnable=true or false.

Smart Help

KiriMotoSlicer supports ~100 settings (as compared to Cura with over 500 settings) which can be queried with --help=<term> or -h <term>:

% kirimoto-slicer -h slice
query settings for 'slice':
      --sliceHeight=<v>             set slice height (default: 0.25)
      --sliceShells=<v>             set slice shells (default: 3)
      --sliceShellOrder=<v>         set slice shell order ["in-out","out-in"] (default: "in-out")
      --sliceLayerStart=<v>         set slice layer start ["last","center","origin"] (default: "last")
      --sliceFillAngle=<v>          set slice fill angle (default: 45)

% kirimoto-slicer -h shell
query settings for 'shell':
      --sliceShells=<v>             set slice shells (default: 3)
      --sliceShellOrder=<v>         set slice shell order ["in-out","out-in"] (default: "in-out")
      --outputShellMult=<v>         set output shell mult (default: 1.25)


xyzHollowCalibrationCubeV2 (allows 0% infill without support) using --sliceFillSparse=0

Visualized with gcode2png.

Fill Types

20mm cube:

Fill type 'vase' and 'bubbles' are listed as available but don’t work yet.


As of 2021/08 I’m quite impressed with Kiri:Moto. It goes different ways than the most other slicers, for example:

  • first layer outline is printed extremely slow
  • first layer filling is printed fast
    • other slicer print first layer outline & filling slow
  • shells/walls are printed inside out with increased speed, other slicers slow down shells/walls
    • the result in my case are very clean walls, as the emphasis is on fast contineous extruding than slow extruding

I also noticed there is little retraction done by default, fast motion to continue filling where other slicers retract & unretract more often.

So, the print with basic forms sliced looks good so far, and with just 100 settings it’s easy to learn and memorize, compared to Cura with over 500 settings.

While I like a new and usable slicer be available, the downside is that JavaScript use was once promising, but as of 2020/2021 it has become a mess as Browser JS and Node JS have diverted immensely, and the entire “Async Hell” has just driven forward with async / await / promise / then non-sense – it is really software development gone wrong for a decade. On the upside, JavaScript makes the slicing engine accessible and easier to extend than with verbose C++ or rudimentary C.

Print3r Support

As of version Print3r 0.3.8 the KiriMotoSlicer is supported, using slicer independent settings (write the profile once, use multiple slicers).

% print3r --printer=ashtar-k-2-pax --random-placement print --slicer=kirimoto xyzHollowCalibrationCubeV2.stl --fill-density=0
== Print3r 0.3.8 == https://github.com/Spiritdude/Print3r
print3r: conf: device /dev/ttyACM0, Ashtar K 38x30x33 PAX #2, build/v 300x300x330mm, nozzle/d 0.4mm, layer/h 0.25mm, filament/d 1.75
print3r: slice (kirimoto) part <xyzHollowCalibrationCubeV2.stl> to gcode: prepare, reposition [145,116], translate 145.0,116.0,0.0, reposition [128,211], slice, done.
print3r: print: 0h 14m elapsed, eta 0h 00m, 100.0% complete, z=20.00mm, layer #80, filament 0.93m


Configurations can be stored line-wise like:

# is a comment
sliceHeight = 0.25
sliceLineWidth = 0.45

and optionally you can load JSON formatted configuration as in grid-apps/src/dev/*

kirimoto-slicer -l my.conf test.stl
kirimoto-slicer -l grid-apps/src/dev/Creality.Ender.3 test.stl




  • 2021/09/28: added reference to newly published paper by ZHAW
  • 2021/03/22: 0.4.5: source released on github, page published
  • 2021/03/20: 0.4.2: adding more core slicer examples
  • 2021/03/17: 0.3.1: start writing page, provide overview of settings


Slicer4RTN aka “Slicer for Rotating Tilted Nozzle (RTN)” is a highly experimental conic slicer utilizing existing planar slicer like Slic3r with pre- and post-processing to create G-code which can be printed with a 4-axis RTN, allowing to print particular overhangs without support:

Some of the conceptual thoughts on Conic Slicing for Rotating Tilted Nozzle (RTN).


  • conic slicing (rotating tilted nozzle)
    • variable angle of cone
    • single rotation or unlimited rotation
    • printing 90° – 110° overhangs without support, given some conditions
  • unidirectional tilted slicing (tilted nozzle)
    • variable tilt angle
    • printing 90° – 110° overhangs in one direction, like possible with a belt printer

And yes you can print non-planar conic sliced G-code with an ordinary 3-axis 3D printer if you dare, something like this:

Just keep your expectation on the print quality low, as you try to print with a vertical nozzle which is meant to be printed with a tilted nozzle, but you will be able to print 90° overhangs without support structure.




% slicer4rtn
USAGE Slicer4RTN 0.4.4: [<opts>] <file.stl> ...
      -v or --verbose      increase verbosity
      --version            display version and exit
      -k or --keep         keep all temporary files (temp.stl, temp.gcode)
      --recenter           recenter model X- & Y-wise
      --subdivide=<n>      set midpoint subdivisions (default: 2)
      --mode=<mode>        set cone mode, either 'outside' or 'inside' (default: 'outside')
      --output=<fname>     override default naming convention file.stl -> file.gcode
      --axis=<axis>        set axis count of printer: 3, 4 or 5 (default: 4)
      --angle=<angle>      set angle of cone (default: 45)
      --center=<cx,cy>     set conic slicing center (default: 0,0)
      --bed-center=<cx,cy> set bed-enter, only affects output G-code (default: 100,100)
      --layer-height=<z>   set conic layer height (default: 0.2)
      --rot-gcode=<v>      set G-code symbol for rotation (default: A)
      --rot-revolv=<mode>  set rotation revolution, 0 = unlimited, 1 = once (default: 1)
      --rot-offset=<a>     set rotation offset (default: -90)
      --rot-fixed=<angle>  set fixed rotation angle, usable if --axis=3 but 4-axis or 5-axis printer is target
      --tilt-gcode=<v>     set G-code symbol for tilt for 5-axis operation (default: B)
      --zoff=<v>           set z-offset, will be added to G1 ... Z<v>
      --erate=<f>          set extrusion rate (multiplier, default: 1)
      --efmin=<v>          set extrusion factor minimum, (default: 0.01)
      --efmax=<v>          set extrusion factor maximum, (default: 3)
      --inter-steps=<n>    set interpolation steps per mm (default: 2)
      --motion-minz=<v>    set minimum Z level for motion (without extrusion) (default: 0.2)
      --max-speed=<s>      set maximum speed (default: 0)
      --slicer=<slicer>    set slicer (default: 'slic3r')
      --slicer.<k>=<v>     add additional slicer arguments, e.g. --slicer.infill-density=0
      --<k>=<v>            all other arguments not for slicer4rtn will be passed to the core slicer (slic3r)

      slicer4rtn sphere.stl
      slicer4rtn overhang.stl --output=sample.gcode
      slicer4rtn overhang.stl --axis=5 --output=sample.gcode
      slicer4rtn overhang.stl --axis=3 --output=sample-belt-printer.gcode --fill-density=5
      slicer4rtn model-6.stl --angle=25 --subdivide=5



By default the faces of model is 2x subdivided, you can turn it off by --subdivide=0 or increase like --subdivide=5 for a cube. The current algorithm depends on sufficient detailed faces.

So for simple STLs choose subdivide=5 or higher, for already complex STLs with thousands of faces, you may go with the default.


If you slice a model you did not create yourself, very likely the model might not be properly aligned or centered, with --recenter you can enforce recentering the model X- and Y-wise.


By default outside mode is used, you may change it with --mode=inside which slices for inside-cone printing. Currently slicer4rtn does not segment parts according their required mode, you have to do this manually right now. This may change with a later version.

Needless to say, this mode switch is very basic and only makes sense for very simple models.


By default G-code for 4-axis Rotating Tilted Nozzle (RTN) is generated (--axis=4), which includes rotational information.

  • --axis=3 generates tilted slices at angle 45° (which can be changed with --angle=..) which means overhangs can only be printed in one direction; the G-code can be printed with a 3-axis 3D printer now like a belt-printer; also --rot-fixed=.. one controls the direction of the tilt slicing
  • --axis=4 is the default, a 45° tilted nozzle is implied
  • --axis=5 adds an additional fixed tilt into the G-code like B45 and is printable on a 5-axis Penta Axis (PAX) printer


By default the conic angle is set to 45° and can be changed with --angle=.., e.g. for a 3-axis 3D printer the angle can be set to 15..25° to print conic slices with a vertical nozzle.

If you plan to print conic sliced overhang pieces on your traditional 3-axis 3D printer, then consult the article on 90° Overhangs without Support Structure with Non-Planar Slicing on 3-axis Printer.


By default the conic slicing center is set to 0,0 and can be change with --center=x,y

You control the conic slicing center twofold:

  • with the model itself
  • with --center=cx,cy

You may use --recenter switch to force the model be recentered X- & Y-wise; this is recommended if you did not create the model yourself and the STL is not centered properly.


The slicer final output will be offsetted by these coordinates, by default it is 100,100 which should work for most 3D printers.


By default 0.2mm conic layer height is set, and can be changed with --layer-height=h [mm]

Note: the layer height for the core slicer is calculated and might exceed the hard limits of the core slicer, so reduce the layer height so that slicer4rtn doesn’t stumble.


By default the rotational angle is passed to G-code with A and can be changed, e.g. the RotBot uses U in the firmware to process the rotation angle, hence using --rot-gcode=U


By default the printhead can only revolve once (-180°..180°), hence --rot-revolv=1; a more mechanical complex RTN is the RotBot by ZHAW which permits unlimited rotations with a slip ring, then use --rot-revolv=0

Note: rot-revolv=0 resets at layer change the rotation angle to mod(360) again.


The rotation angle of the tilted nozzle is calculated by the traditional X/Y coordinate system; as I designed my Rotating Tilted Nozzle (RTN) I defined the 0° to be in front, and traditional counter-clockwise with increasing angle; so by default rot-offset is equal -90°.

20mm cube conic sliced, printed with 4/5-axis nozzle, rot-offset=-90 rotation angle A, and tilt angle B shown


In case you like to have non-rotating printing and single direction slicing therefore, then fix the angle with --rot-fixed=angle.


In case when targeting 5-axis Penta Axis (PAX) --axis=5 the tilt G-code is added as default as Bangle, you may change the code with --tilt-gcode=V for example.


In case you have trouble with under- or over-extrusion you can change the multiplier with --erate=f for example to reduce extrusion by 10% use --erate=0.9


By default 2 steps per mm are interpolated per planar G1 extrusion, you may refine it by increasing it, e.g. --inter-steps=4; be aware it creates larger G-code outputs.


By default Slic3r (slic3r) is used as core slicer, an overview of current supported core slicers, selectable with --slicer=...

  • Slic3r 1.2.9 (slic3r): gives good results so far with minimal configuration ★★★★★
  • Prusa Slicer 2.1.1 (prusa-slicer): struggles to slice inverted conic models and fails to create G-code with a message like Empty layers detected, the output would not be printable. It may help to increase --subdivide=n, be aware of immense amount of faces ★★★★★
  • Mandoline (mandoline): fails mostly to slice inverted conic models, but could become relevant in later development ★★★★
  • CuraEngineLegacy 15.10 (CuraEngineLegacy): outdated but surprisingly gives good results, easy to use on command-line ★★★★★
  • CuraEngine 4.4.1 (CuraEngine): gives good results, but is tedious to configure on command-line as requires base configuration in .json, which changes with each new version; it gives warnings & errors for small polygons but makes an effort regardless giving G-code (good behavior, better than Prusa Slicer) ★★★★
    • Cura CLI Wrapper (cura-slicer): same as CuraEngine but easier to configure (allows to query hundreds of possible settings directly with cura-slicer (recommended)

Example of 20mm cube & overhang nr 3 4mm shown at 50% complete:

Slic3r 1.2.9 performs reliable on 20mm cube and overhang nr 3 4mm model, and CuraEngine 4.4.1 gives excellent results as long layer-height is low (below 0.2), whereas older Cura 3.8.x struggles – so definitely use Cura 4.x series.

G-code Size

As conic slices range over X, Y and Z, the G-code becomes quite verbose compared to horizontal slices, for example 20mm cube sliced both times with Slic3r 1.2.1:

  • horizontal slices: 152 KiB (4.7K G1 lines)
  • conic slices: 7,565 KiB (93.6K G1 lines)

which is a significant increase of 50x size of G-code and 20x more G1 statements.

Common Settings

By default

  • /usr/share/slicer4rtn/slicer4rtn.ini (system-wide) and
  • ~/.config/slicer4rtn/slicer4rtn.ini (user)

are considered where all settings can be listed to provide new defaults for slicer4rtn, for example:

# my own settings:
layer-height = 0.15
bed-center = 120,100
rot-offset = 0
rot-resolv = 0

You can use ‘#‘ as a leading indication that the rest of the line is a comment and disregarded.

Note: It is recommended to only list slicer4rtn specific settings there, not slicer specific settings (see below).

Slicer Specific Settings

Each core slicer may have their own base settings, so you don’t need to add it everytime when calling slicer4rtn, so include them in your user settings:

User Slicer Settings

  • ~/.config/slicer4rtn/slic3r.ini
  • ~/.config/slicer4rtn/prusa-slicer.ini
  • ~/.config/slicer4rtn/mandoline.ini
  • ~/.config/slicer4rtn/CuraEngine.ini
  • ~/.config/slicer4rtn/CuraEngineLegacy.ini
  • ~/.config/slicer4rtn/cura-slicer.ini

Make your changes in those files, as they will not be overwritten when you upgrade slicer4rtn in the future, for example slic3r.ini:

external-perimeter-speed = 10%

Note: slic3r and prusa-slicer directly load their slicer specific settings from the file, whereas the other slicers the settings will be parsed by slicer4rtn and passed on via internal command-line execution.

System-Wide Slicer Settings

By default make install installs some base system-wide configs in /usr/share/slicer4rtn with the same filenames as mentioned above, those will be overwritten in future releases of Slicer4RTN, but your user settings will not be overwritten.

When running slicer4rtn is executed first are the system-wide configs loaded, then the user specifics.

Print3r & Slicer4RTN

As of print3r 0.3.2 or later slicer4rtn is supported as well:

  • .config/print3r/printer/<yourprinter>.ini and make a copy like .config/print3r/printer/<yourprinter>-rtn.ini add following lines:
slicer = slicer4rtn
# slicer4rtn specific seeting prepend 'slicer4rtn.' for settings, like:
# slicer4rtn.slicer = prusa-slicer
angle = 25

and alter the start-gcode line with increasing Z motion as well, e.g for my Prusa-i3 clone it has a M6 threaded rod, which means one revolution (200 full steps) 1mm Z motion, hence

start-gcode = ".....\nM203 Z6\n...."

increased Z motion speed to come close to X- and Y- speed, it creates more even extrusions, nicer prints.

Actual use with print3r goes then like this, my Prusa-i3 clone named y3228-rtn now:

% print3r --printer=y3228-rtn --random-placement print overhang4l4mm.stl
% print3r --printer=y3228-rtn --layer-height=0.3 --fill-density=5 print overhang4l4mm.stl
% print3r --printer=y3228-rtn --scad print 'sphere(10)' --fill-density=5

it slices and forwards the G-code according your setup without the requirement to invoke slicer4rtn manually anymore.


See Also