RasmahRasmah

Additive manufacturing

Overview

Additive manufacturing builds a part up instead of cutting it down. The 3D-printing side of Rasmah turns a watertight mesh into a sequence of flat layers, traces perimeters (walls) and infill inside each layer, and emits the G-code that drives an extruder — the same design → tool path → controller code pipeline as milling, but with an extrusion axis.

The guiding principle is volume balance: the filament pushed into the hot end must exactly become the bead it deposits. A bead of length $L$, width $w$, and height $h$ has volume $Lwh$; the filament of diameter $d$ fed in has volume $E \cdot \pi (d/2)^{2}$. Setting them equal gives the extrusion length

\[E = \frac{L\,w\,h}{\pi (d/2)^{2}} .\]

Slicing

Slicing cuts the mesh into horizontal layers at the given layer height:

Rasmah.SliceLayerType

A single slice: its height and its closed contours, oriented so outer loops are counter-clockwise (positive area) and holes are clockwise (negative).

source
Rasmah.sliceFunction

Slice a watertight mesh into ceil((zmax-zmin)/layer_height) layers from zmin upward. By default the whole vertical extent of the mesh is used.

source
Rasmah.slice_layerFunction

Slice a watertight mesh at one height, with contours oriented (outer CCW, holes CW) and sorted by |area| descending.

source
Rasmah.slice_contoursFunction

Cross-section a watertight TriangleMesh by the plane z = z0, returning closed 3D loops (each a Vector{Vector{Float64}} of coplanar points).

source

Perimeters and infill

Each layer is filled in two stages: the perimeters (the walls, traced inward), then the infill (the interior pattern):

Rasmah.perimetersFunction

Perimeters (walls) of a layer: the contours offset inward walls times by the nozzle line_width (the first wall rides half a width inside the boundary).

source
Rasmah.infill_segmentsFunction

Infill scan segments of a layer for a given density/pattern. Density scales the line spacing so density=1 gives fully solid lines at line_width.

source
Rasmah.inset_contourFunction

Offset a single planar (CCW) contour inward by distance (positive shrinks). Each vertex is the intersection of its two incident edges offset inward by distance. Exact for convex polygons; concave self-intersections are left to the caller (use negative distance to grow, i.e. outward).

source
Rasmah.grid_infillFunction

Scanline (rectilinear) fill of a region with parallel lines at spacing, rotated by angle (radians, in the XY plane). Returns a vector of (a, b) 3D segments (z copied from the region).

source
Rasmah.concentric_infillFunction

Concentric (offset) infill: repeated inward offsets of the outer contour at stepover, returning the contour rings.

source
m = surface_mesh(sphere(1.0))
plan = print_plan(m; layer_height=0.2, perimeters=2, infill_density=0.2)
length(plan.layers)
11

A unit sphere (1 m diameter) sliced at 0.2 m layers gives 11 layers.

Extrusion and G-code

The extrusion balance above becomes a number via extrusion_length, and the whole plan becomes a Marlin-flavoured program via print_gcode:

Rasmah.extrusion_lengthFunction

Extrusion length (mm of filament) needed to lay a bead of length, width, and height, from a filament_diameter feed. Volume balance: length·width·height = E·π·(d/2)².

source
Rasmah.PrintPlanType
PrintPlan

A complete FDM print plan: the sliced layers plus the extrusion settings used to turn them into G-code.

Fields

  • layers: the sliced SliceLayers.
  • perimeters: number of wall perimeters.
  • infill_density: infill density (1 = solid).
  • line_width: nozzle line width (m).
  • layer_height: layer height (m).
  • filament_diameter: filament diameter (m).
source
Rasmah.print_planFunction

Build a print plan from a watertight mesh: slice it, then record the extrusion settings.

source
Rasmah.print_gcodeFunction

Marlin-flavoured G-code for a print plan: home, heat, then per-layer perimeter and infill moves with extrusion (M83 relative E). Returns the full program text.

source
extrusion_length(10e-3, 0.4e-3, 0.2e-3, 1.75e-3)
0.00033260135046143024

Laying a 10 mm bead that is 0.4 mm wide and 0.2 mm tall from 1.75 mm filament needs about 0.33 mm of filament — the volume balance in one number.

gc = print_gcode(plan)
split(gc, '\n')[1:4]
4-element Vector{SubString{String}}:
 "; Rasmah print plan"
 "M104 S210 ; set extruder temp"
 "M140 S60 ; set bed temp"
 "M190 S60 ; wait bed"

Overhangs and supports

Faces that slope outward past a threshold need support, and the flat top face benefits from ironing:

Rasmah.overhang_angleFunction

Angle from the vertical (build direction) of each face normal, in radians: 0 for an up-facing face, π/2 for a vertical wall, π for a down-facing face.

source
Rasmah.unsupported_facesFunction

Count of down-facing faces steeper than max_angle from horizontal (i.e. the surface tilts down by more than max_angle), excluding faces resting on the build plate. These are the regions needing support.

source
Rasmah.support_meshFunction

Generate a support volume for the overhanging faces of a mesh: a filled prism (from the overhang down to the build plate) returned as a triangle mesh (union of the support prisms). max_angle is the maximum printable overhang (from horizontal).

source
Rasmah.ironing_regionFunction

Ironing: a dense top-surface pass that remelts the topmost solid layer for a smooth finish. Returns the top surface region (XY contours at the top height).

source
Rasmah.vase_modeFunction

Spiralize the outer contour of a mesh into a continuous single-wall vase: resample the outer contour at each layer and advance layer_height per lap, emitting a helical ToolPath (the Z rises continuously rather than in steps).

source

Next steps

Additive manufacturing closes the machining loop. Return to Milling, turning, and cutting for the subtractive side, or back to Manufacturing for the shared tool-path model that both sides produce.