Slicing Algorithms¶
This page explains how each slicing algorithm works under the hood.
Overview¶
All slicers share a common pattern:
- Input: A triangulated mesh
- Process: Generate cutting surfaces and find intersections
- Output: Layers containing Paths (contours)
The key difference is what cutting surfaces are used:
| Slicer | Cutting Surface | Result |
|---|---|---|
PlanarSlicer |
Horizontal planes at fixed Z heights | Parallel horizontal contours |
InterpolationSlicer |
Isosurfaces of geodesic distance field | Contours that follow mesh curvature |
ScalarFieldSlicer |
Isosurfaces of user-defined scalar field | Custom contour patterns |
Planar Slicing¶
Algorithm¶
The simplest approach - intersect the mesh with horizontal planes:
flowchart TD
A[Mesh] --> B[Compute Z bounds]
B --> C[Generate planes at layer_height intervals]
C --> D[CGAL mesh-plane intersection]
D --> E[Extract polylines from intersection]
E --> F[Create Layer per plane]
How It Works¶
- Compute bounds: Find min/max Z coordinates of mesh vertices
- Generate planes: Create horizontal planes from
z_mintoz_maxspaced bylayer_height - Intersect: Use CGAL's
slicer()function for robust mesh-plane intersection - Extract contours: CGAL returns polylines for each connected intersection
from compas_slicer.slicers import PlanarSlicer
slicer = PlanarSlicer(mesh, layer_height=0.4)
slicer.generate_paths()
# Result: slicer.layers contains one Layer per plane
# Each Layer contains one or more Paths (contours)
Why CGAL?¶
CGAL (Computational Geometry Algorithms Library) provides:
- Robustness: Handles degenerate cases (edges exactly on plane, etc.)
- Speed: Optimized C++ implementation
- Correctness: Proper handling of mesh topology
The intersection is computed via compas_cgal.slicer.slice_mesh().
Parameters¶
| Parameter | Type | Description |
|---|---|---|
layer_height |
float | Distance between planes in mm |
slice_height_range |
tuple | Optional (z_start, z_end) to slice only part of mesh |
Interpolation Slicing (Curved Slicing)¶
Concept¶
Instead of horizontal planes, generate contours that interpolate between two boundary curves. This creates non-planar toolpaths that follow the mesh surface.
flowchart TD
A[Mesh + Boundaries] --> B[Compute geodesic distances]
B --> C[Create distance field on vertices]
C --> D[Extract isocurves at regular intervals]
D --> E[Non-planar Layers]
How It Works¶
- Define boundaries: Mark two sets of mesh vertices as
target_LOWandtarget_HIGH - Compute distances: Calculate geodesic distance from each vertex to both boundaries
- Interpolate: For each vertex, compute interpolated distance:
d = t * d_low + (1-t) * d_high - Extract isocurves: Find contours where the interpolated field equals zero
The key insight: by varying t from 0 to 1, the zero-isocurve sweeps from one boundary to the other.
from compas_slicer.slicers import InterpolationSlicer
from compas_slicer.pre_processing import InterpolationSlicingPreprocessor
# 1. Define boundaries
preprocessor = InterpolationSlicingPreprocessor(mesh, ...)
preprocessor.create_compound_targets()
# 2. Slice with interpolation
slicer = InterpolationSlicer(mesh, preprocessor)
slicer.generate_paths()
Mathematical Background¶
For a mesh with vertices \(V\), we compute:
- \(d_{low}(v)\) = geodesic distance from vertex \(v\) to lower boundary
- \(d_{high}(v)\) = geodesic distance from vertex \(v\) to upper boundary
The interpolated field at parameter \(t \in [0, 1]\):
The zero-level set \(\{v : f_t(v) = 0\}\) gives one contour. Varying \(t\) generates all contours.
Use Cases¶
- Domes and shells: Toolpaths follow curvature for better adhesion
- Overhangs: Reduce support by printing along surface
- Aesthetic parts: Visible layer lines follow form
Scalar Field Slicing¶
Concept¶
The most general approach - extract isocurves of any scalar field defined on mesh vertices.
flowchart TD
A[Mesh + Scalar Field] --> B[Assign field to vertices]
B --> C[Find edges with sign change]
C --> D[Interpolate crossing points]
D --> E[Connect into contours]
How It Works¶
- Define scalar field: Assign one float value per vertex
- Find zero crossings: For each edge, check if field changes sign
- Interpolate position: Find exact crossing point via linear interpolation
- Build contours: Connect crossing points around faces to form polylines
from compas_slicer.slicers import ScalarFieldSlicer
# scalar_field: one value per vertex
slicer = ScalarFieldSlicer(mesh, scalar_field, no_of_isocurves=50)
slicer.generate_paths()
Zero-Crossing Algorithm¶
For an edge with vertices \((u, v)\) and field values \((f_u, f_v)\):
- Test: Edge is crossed if \(f_u \cdot f_v \leq 0\) (different signs)
- Interpolate: Crossing point at parameter \(t = \frac{|f_u|}{|f_u| + |f_v|}\)
- Position: \(p = (1-t) \cdot p_u + t \cdot p_v\)
Marching Algorithm¶
To build connected contours:
- Start at any crossed edge
- Find the face containing this edge
- Find the other crossed edge in this face
- Move to adjacent face sharing that edge
- Repeat until returning to start (closed) or reaching boundary (open)
Use Cases¶
- Custom layer patterns: Any scalar field you can compute
- Distance-based: Contours equidistant from a feature
- Curvature-based: Highlight geometric features
- Stress fields: From FEA analysis
Contour Assembly¶
All slicers eventually produce contours via the ScalarFieldContours class:
From Crossings to Paths¶
flowchart LR
A[Edge crossings] --> B[Face traversal]
B --> C[Connected polylines]
C --> D[Path objects]
- Build crossing map: Dictionary of edge → crossing point
- Traverse faces: Walk around faces connecting crossings
- Handle branches: Multiple paths per layer for complex geometry
- Create Paths: Wrap polylines in Path objects with metadata
Handling Complex Topology¶
The algorithm handles:
- Multiple contours per layer: Holes, disconnected regions
- Open contours: When path hits mesh boundary
- Branching: When contours merge or split
Performance Considerations¶
Planar Slicing¶
- Fast: Single CGAL call handles all planes
- Scales well: O(n) in number of faces
- Memory efficient: Processes planes in batch
Interpolation/Scalar Field Slicing¶
- Slower: One contour extraction per isocurve
- Preprocessing cost: Geodesic distance computation
- Mesh quality matters: Irregular tessellation → irregular contours
Optimization Tips¶
- Clean mesh: Remove degenerate faces, weld vertices
- Appropriate resolution: More faces ≠ better results
- Layer height: Fewer layers = faster slicing
Comparison Summary¶
| Aspect | Planar | Interpolation | Scalar Field |
|---|---|---|---|
| Speed | Fast | Medium | Medium |
| Setup | Simple | Requires boundaries | Requires field |
| Paths | Horizontal only | Follow surface | Arbitrary |
| Use case | Standard FDM | Shells, domes | Custom patterns |
Next Steps¶
- Architecture - Data structures overview
- Print Organization - Adding fabrication parameters
- Examples - Complete working code