3D Printing: Mandoline Slicer

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

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

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
    • 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)

Changes

  • 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

References

3D Printing: Kiri:Moto CLI Slicer

Updates:

  • 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

Introduction

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.

Requirements

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

Download

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

Installation

make requirements
sudo make install 

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

Usage

KiriMotoSlicer 0.0.4 USAGE: [<options>] [file] ...
   options:
      --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")

   examples:
      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 .

Internals

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)

Examples

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.

Conclusion

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
mm
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

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

References

3D Modeling: FreeCAD2Any

Just a brief announcement of a small Python script for command-line use (CLI) which allows to convert FCStd (FreeCAD Standard file-format) to

  • STL
  • IGES
  • STEP
  • Brep
  • AMF
  • OFF
  • OBJ
  • 3MJ

which I primarely use to bring FreeCAD into the 3D printing framework with Print3r.

Platforms

  • Linux/Ubuntu 20.04 LTS

Download

https://github.com/Spiritdude/FreeCAD2Any

References

  • Print3r, makes use of freecad2any in order to pre-process FCStd, IGES, STEP and Brep files

3D Printing: Non-Planar “Balcony” Overhang with 3-axis FDM Printer

Updates:

  • 2021/05/02: adding overhang-inout with 5 segments, with conic inside- and outside-cone mode
  • 2021/05/01: adding tilt sliced overhang segment variant as comparison
  • 2021/04/29: video uploaded and blog-post published
  • 2021/04/27: first successful tests with vertical nozzle (3-axis FDM printer)

Introduction

The past few months and weeks I focused on the non-planar slicing, and the first tests with sub-volume segmenting and thereby mixing planar and non-planar sliced G-code worked as simulation, and now in actual prints.

One of the benchmarks are 90° overhangs in different directions, and I printed with vertical nozzle on an ordinary 3-axis FDM printer, therefore I prepared the G-code with a new tool (in-development) which coordinates segmenting and planar/non-planar slicing of sub-volumes, and the conic sliced segment was sliced with 25° conic angle so it remains printable with the vertical nozzle unlike the simulation where a 4- or 5-axis FDM printer is required:

Gallery

Conic Sliced Overhang Segment

The simulation as reference:

and the actual print process with vertical nozzle on a low-cost 3-axis FDM printer:

Excerpt of the actual printing process with brief annotations:

Tilt Sliced Overhang Segment

Just for sake trying out, instead of conic sliced overhang segment, tilt sliced and 45° Z rotated to nicely extend to the maximum overhang position:

and the actual print of a slightly lower model but with the same features:

Comparing Tilted Sliced vs Conic Sliced Overhang Underside

Overhang In/Out: 2 Overhang Conic Segments

5 segments (bottom to top): z-planar, conic (inside-cone), z-planar, conic (outside-cone), z-planar

And revisiting the Overhang In/Out Model, which features ingoing and outgoing overhang, segmented into 5 sub-volumes:

  1. bottom: z-planar
  2. ingoing1) overhang: conic (inside-cone mode)
  3. middle: z-planar
  4. outgoing1) overhang: conic (outside-code mode)
  5. upper: z-planar

1) when dealing with conic slicing, the direction of overhang matters when deciding the mode of conic slicing, e.g. outside-cone or inside-cone.


and the actual print, a half of the model so the printing of inner overhang on the lower part of the model is visible:

Conclusion

It took me a few days to tune the 3-axis FDM printer to print in acceptable quality of this Overhang Model No 5 and also Overhang In/Out Model. A strong part-cooler was mandatory, well adjusted print temperature and slow perimeter as those extrusions align horizontally without vertical support; and it worked: the main idea is to segment and limit the overhang part to ~2mm thickness – a quasi “balcony” – which still allows a classic vertical nozzle with part-cooler to print such, and then switch back to planar printing again.

Vertical nozzle with part-cooler printing conic sliced overhang – a “balcony” – working with narrow margins

Detail settings: the conic overhang was sliced with Slicer4RTN with following settings slicer4rtn --slicer=cura-slicer --speed_wall=10 --speed_wall_0=10 --speed_wall_x=10 ... and since the Z-axis motion is limited to 4mm/s (M6 threaded rod, 1 rotation => 1mm) the overall printing speed is slow enough to provide acceptable print quality.

References

3D Printing: Sub-Volume Segmenting & (Non-)Planar Slicing

Introduction

In order to take advantage of 4- and 5-axis non-planar FDM1) printing (e.g. tilted, conic, cylindrical, spherical) the model may be segmented and then dedicate slicing methods can be assigned to such sub-volumes.

A few basic examples combining planar and non-planar slicing methods on sub-volume segmented models illustrating the possibilities printing without support structures:

  1. Fused Deposition Modeling (FDM) also known as Fused Filament Fabrication (FFF)

T-Model: 2 Segments: Z-planar & Conic

Utilizing novel conic slicing as introduced by ZHAW researchers in 2020/2021:

T-model segmented into 2 sub-volumes, sliced z-planar and conic (outside-cone mode)

Conic slices can be printed with 4-axis Rotating Tilted Nozzle (RTN) although printing the Z-planar sliced part might not give goods surface results but rather using a 5-axis Penta Axis (PAX) printhead to cover both cases easily.

T-Model: 3 Segments: Z-planar & 2x Tilted

Using non-rotating but tilted sliced (like used with belt-printers) but in two distinct directions:

T-model segmented into 2 sub-volumes, sliced z-planar and twice tilted in opposite directions

Tilted slices can be printed with 4-axis Rotating Tilted Nozzle (RTN) but the first Z-planar part, as mentioned above, might not provide sufficient surface quality, whereas a 5-axis Penta Axis (PAX) printhead can print both segments easily.

T-Model: 3 Segments: Z-planar & 2x X-planar

A more classic planar approach but with different planes as reference, first Z-planar then twice X-planar in different directions:

T-model segmented into 3 sub-volumes, sliced z-planar and twice x-planar

X-planar printing requires either 5-axis Penta Axis (PAX) printhead or the ability to tilt the bed.

Overhang In/Out: 2 Segments: 2x Conic

Lower part is sliced with conic slicing with inside-cone mode to print in-going overhang, whereas the upper part is sliced with outside-cone mode to cover the out-going overhang:

Overhang in/out model segmented into 2 sub-volumes: lower part is sliced conic (inside-cone mode) and upper part conic (outside-cone mode)

This model covers the classic case of 4-axis Rotating Tilted Nozzle (RTN) application: rotating 45° tilted nozzle printing in two different modes (outside-cone and inside-cone); a 5-axis Penta Axis (PAX) printhead also can print such.

Overhang Out No 5: 2 Segments: Z-planar & Conic

Another overhang piece, stretching out into one direction; the lower part Z-planar, and the overhang conic (outside-cone mode) with an offset to align better with the lower segment:

Overhang Out No 5 model segmented into 2 sub-volumes: z-planar at the bottom and overhang segment conic (outside-cone mode)

Overhang Out No 5: 3 Segments: 2x Z-planar & Conic

Perhaps a more realistic approach using the conic part as a “balcony” just for the overhang part sufficiently thick to carry next segment and switching back to Z-planar:

Overhang Out No 5 model segmented into 3 sub-volumes: z-planar first, then conic (outside-cone) building a thin “balcony” as support for the z-planar part on top again

Early tests have shown the thickness of the conic overhang “balcony” depends on the actual length of the in-air overhang, where print speed, part-cooling capacity and extrusion consistency determine the geometrical accuracy. More examples with “balcony” printed with 3-axis FDM printer followed.

Conclusion

Unlike with ordinary Z-planar slicing, it may be suitable to dedicate a particular slicing method and orientation for sub-volumes in order to take advantage of the possibilities like avoiding support structure, particular strength properties or surface quality.

This of course opens a wide-range of possibilities and complexity therefore:

  • where to segment
  • which slicing method to use
  • in which orientation the slicing is performed

but I think it’s worth it, in particular when a piece is printed more than once like with small series manufacturing / production.

The examples have been produced with various slicers and combined with a new application coordinating the segmenting and dedicated slicing methods, which currently (2021/04) is in development; it also involves a new file-format describing the segmenting and its slicing settings. The segment positioning was done manually as a start, but I expect with more experience and research some cases can be detected automatically.

Sub-volume segmenting is just one approach to take advantage of 5-axis FDM printing, another is continuous slicing along the form.

References

See Also

PS: All animations I combined in a short 3min video: Mixing Planar & Non-Planar Slicing Methods for 3D Printing Overhangs without Support Structure (YouTube)

3D Printing: YAGV: Yet Another G-code Viewer Fork

One of the oldest standalone G-code viewers yagv (Yet Another G-code Viewer) I forked and added following features:

  • ported to Python3
  • new color scheme (white background)
  • parsing G-code comments, determining wall, infill, support structure and render with different colors
  • support for Slic3r, PrusaSlicer, Cura/cura-slicer, Mandoline and Slicer4RTN (non-planar)
  • panning implemented (properly works with zoom and rotation)
    • same mouse button layout as OpenSCAD
  • more test G-code included in tests/

Example of non-planar G-code:

Download

https://github.com/Spiritdude/yagv

Note: I opened a Pull Request (PR) but not sure if it’s accepted.

See Also

3D Printing: Non-Planar Slicing with Planar Slicer

Updates:

  • 2021/04/09: spherical slicing redone, slightly better than before
  • 2021/04/03: cylindrical & spherical slices added
  • 2021/03/26: refocusing to non-planar slicing with planar slicing
  • 2021/03/14: starting write-up with basic illustrations

Introduction

After discovering the 4-axis Rotating Tilted Nozzle (RTN) and its prototype of RotBot as developed by ZHAW and their conic slicing method, it became clear to me a 5-axis 3D printer with variable tilting nozzle is the way to go as it is a superset of 4-axis and 3-axis 3D printing.

With that in mind, I realized there was time to explore non-planar slicing with planar slicers in more details.

Slicing Methods

Let’s provide an overview of various slicing methods:

Horizontal Slices

Vertical slicing creates horizontal slices, the traditional aka planar slicing method, so issues and limitations are well known:

  • simple to slice
  • only challenge is to create support structure for overhangs to ensure all printed layers have layers beneath
  • no collision detection needed, as all already printed layers are beneath

Tilted Slices

Tilted slices are kind of new(er) and became known with belt printers, usually 45° tilted:

Transformation is [ x, y, z – y ]

  • simple to slice
  • belt-printer: no collision detection is needed
  • can print 90° overhangs in one direction only

There are patches for Cura available to slice for belt printer, additional the experimental Slicer4RTN also provides tilted slicing.

Conical Slices

New slicing method as introduced by ZHAW researchers and announced in 2021/01 utilizing planar slicer:

  • requires a center of the conic layers
  • can print 90° overhangs, two distinct modes: inside out (outside cone), or outside in (inside cone) depending on direction to a central slicing cone center
  • requires rotating and tilted nozzle aka Rotating Tilted Nozzle (RTN)
  • angle of conic slicing can be changed from 45° to 20° and models become printable with vertical nozzle with reduced print quality

Transformation is [ x, y, z + sqrt(x2 + y2) ]

I implemented a conic slicer named Slicer4RTN in 2021/03. There are more complex conic transformations possible, e.g. map the x/y angle via atan(y/x) but just adding sqrt(x2 + y2) to z does achieve a conic slice.

Cylindrical Slices

Early tests using planar slicers to slice also cylindrical, like this:

Transformation is [ atan(y/x), z, sqrt(x2 + y2) ]

It can be printed on a fixed vertical rod, with a rotating and tilting nozzle, or horizontal rotating rod (like a lathe) and vertical nozzle then:

I came up with this way by myself based on the study on conic(al) slicing but I was made aware researchers Coupek, Friedrich, Battran, Riedel back in 2018 published a paper on this method already.

(Hemi-)Spherical Slices

Early tests using planar slicers to slice also spherical, like this:

Transformation is [ sqrt(x2 + y2 + z2), atan(y/x), atan(z/sqrt(x2 + y2)) ]

It can be printed with a 5-axis like PAX printhead, it’s main advantage is to getting close to print continuous overhangs of any angle.

I suspect at least one more suitable and simpler sphere transformation, as soon I came up with such I add it on this blog-post.

Conclusion

It is possible to slice non-planar with planar slicers by mapping to and from the space of the slicing you like to have; yet in the slicing procedure some margins are introduced which need to be compensated – the planar slicer needs to work reliable, Slic3r 1.2.9 and CuraEngine 4.4.1 / cura-slicer perform reliable, whereas PrusaSlicer 2.1.1 makes assumptions of the printability and exits when no printable G-code can be produced, not recommended for this case therefore.

The simpler the transformation forward and backward, the more precise G-code can be obtained, e.g. tilted and conic slices provide precise G-code, whereas cylindrical and spherical slices are harder to tune with the planar slicer.

References

3D Printing: Cura CLI Wrapper (cura-slicer)

Updates:

  • 2021/05/01: 0.0.7: support legacy Cura and --binary=.. to change binary name
  • 2021/03/24: 0.0.5: public release

Introduction

I’m a great admirer of the Ultimaker Cura slicer since years, yet I predominantly have been using CuraEngine on the command-line via Print3r, which hides all the tedious configuration. But it came the point (2021/03) when I needed to have a simpler interface than CuraEngine – hence I wrote Cura CLI Wrapper, the executable cura-slicer looks like prusa-slicer or slic3r and has similar usage.

Speciality is to query all the settings from cura-slicer directly:

% cura-slicer --help
acceleration_enabled = 0 (default)
acceleration_infill = 3000 [mm/s²] (default)
acceleration_ironing = 3000 [mm/s²] (default)
acceleration_layer_0 = 3000 [mm/s²] (default)
acceleration_prime_tower = 3000 [mm/s²] (default)
acceleration_print = 3000 [mm/s²] (default)
acceleration_print_layer_0 = 3000 [mm/s²] (default)
acceleration_roofing = 3000 [mm/s²] (default)
acceleration_skirt_brim = 3000 [mm/s²] (default)
acceleration_support = 3000 [mm/s²] (default)
acceleration_support_bottom = 3000 [mm/s²] (default)
acceleration_support_infill = 3000 [mm/s²] (default)
acceleration_support_interface = 3000 [mm/s²] (default)
acceleration_support_roof = 3000 [mm/s²] (default)
...

which lists ~570 settings as of CuraEngine 4.4.1 and its defaults and from where the defaults come from (definition defaults, config or cli), and you can query also a term e.g. like ‘brim’:

% cura-slicer --help brim
acceleration_skirt_brim = 3000 [mm/s²] (default)
brim_gap = 0 [mm] (default)
brim_line_count = 0 (config)
brim_outside_only = 1 (default)
brim_replaces_support = 1 (default)
brim_width = 8 [mm] (default)
jerk_skirt_brim = 20 [mm/s] (default)
prime_tower_brim_enable = 0 (default)
skirt_brim_line_width = 0.4 [mm] (default)
skirt_brim_material_flow = 100 [%] (default)
skirt_brim_minimal_length = 250 [mm] (default)
skirt_brim_speed = 30 [mm/s] (default)
support_brim_enable = 0 (default)
support_brim_line_count = 20 (default)
support_brim_width = 8 [mm] (default)

and with -v switch you even get a more descriptive output:

% cura-slicer --help brim -v
== acceleration_skirt_brim (Skirt/Brim Acceleration) ==
   The acceleration with which the skirt and brim are printed. Normally this is done with the initial layer acceleration, but sometimes you might want to print the skirt or brim at a different acceleration.
   acceleration_skirt_brim = 3000 [mm/s²] (default)

== brim_gap (Brim Distance) ==
   The horizontal distance between the first brim line and the outline of the first layer of the print. A small gap can make the brim easier to remove while still providing the thermal benefits.
   brim_gap = 0 [mm] (default)

== brim_line_count (Brim Line Count) ==
   The number of lines used for a brim. More brim lines enhance adhesion to the build plate, but also reduces the effective print area.
   brim_line_count = 0 (config)

== brim_outside_only (Brim Only on Outside) ==
   Only print the brim on the outside of the model. This reduces the amount of brim you need to remove afterwards, while it doesn't reduce the bed adhesion that much.
   brim_outside_only = 1 (default)
....

Essentially it makes Cura and CuraEngine easy to use on the command-line and provides a way to learn of the hundreds of settings available.

Usage

USAGE Cura-Slicer 0.0.7 aka Cura-CLI-Wrapper (CuraEngine 4.4.1): [<opts>] <file.stl> ...
   options:
      -v or --verbose         increase verbosity
      -vv or --verbose=2          "       "
      --version               display version of this program and exit
      --load=<config>         load config file
      --load <config>           "         "
      --output=<fn>           set output filename
      --output <fn>             "         "
      -o <fn>                   "         "
      --binary=<exe>          set executable of CuraEngine (default: CuraEngine)
      --version=<v>           set version of CuraEngine (default: 4)
      --<k>=<v>               set CuraEngine settings (keys with '-' will be converted to '_')
      -h or --help            display all settings
      -h or --help <term> ..  display settings matching term

   examples:
      cura-slicer --help
      cura-slicer --help retract
      cura-slicer -hv retract 
      cura-slicer sphere.stl
      cura-slicer overhang.stl --output=sample.gcode
      cura-slicer overhang.stl --layer-height=0.1 --support-enable=true -o sample.gcode

Settings

The user settings reside in ~/.config/cura-slicer/base.ini and will not be overwritten when upgrading Cura-CLI-Wrapper, make your changes there.

The system-wide settings reside in /usr/share/cura-slicer/base.ini and should not be be changed as it will be overwritten when upgrading Cura-CLI-Wrapper.

Download

https://github.com/Spiritdude/Cura-CLI-Wrapper

Examples

% cura-slicer cube.stl
== Cura-Slicer 0.0.3 aka Cura-CLI-Wrapper (CuraEngine 4.4.1) == 
processing cube.stl, slicing to cube.gcode
   took 0.62 secs total, done.

% cura-slicer --support-enable=true overhang-inout.stl
== Cura-Slicer 0.0.3 aka Cura-CLI-Wrapper (CuraEngine 4.4.1) == 
processing overhang-inout.stl, slicing to overhang-inout.gcode
   took 0.99 secs total, done.

References

Whereever I used CuraEngine before in my existing software packages I will switch to Cura-CLI-Wrapper with cura-slicer.

3D Printing: Slicer4RTN Released 2021/03/22

Just for sake of completeness a blog-post: I just released the source-code for Slicer4RTN. All developments will be documented there.

% slicer4rtn --subdivide=5 --recenter cube.stl
== Slicer4RTN 0.4.5 == https://github.com/Spiritdude/Slicer4RTN
processing 'cube.stl':
   1/5 read stl
      1/5 subdivide (44 vertices)
      2/5 subdivide (188 vertices)
      3/5 subdivide (764 vertices)
      4/5 subdivide (3068 vertices)
      5/5 subdivide (12284 vertices)
   2/5 map vertices
   3/5 write temporary stl
   4/5 slice (slic3r) stl
=> Processing triangulated mesh
=> Generating perimeters
=> Preparing infill
=> Infilling layers
=> Exporting G-code to ./tmp-204390.gcode
Done. Process took 0 minutes and 1.313 seconds
Filament required: 758.4mm (5.4cm3)
   5/5 remap gcode to 'cube.gcode' (18932 lines)
== took 4 secs total, done.

That’s it.