The skin module generates solid fill patterns for top and bottom surfaces of a print.
Skin layers are the fully-filled surfaces at the top and bottom of a print. Unlike infill (which uses patterns like grid or hexagons), skin is printed as solid diagonal lines to create a smooth, continuous surface.
- Solid diagonal fill - 45° alternating lines for strength
- Skin wall perimeter - Single perimeter around skin area
- Hole avoidance - Proper handling of holes in skin regions
- Combing integration - Optimized travel paths between lines
- Adaptive skin detection - See EXPOSURE_DETECTION.md
Skin generation is automatic during slicing:
const { Polyslice } = require("@jgphilpott/polyslice");
const slicer = new Polyslice({
shellSkinThickness: 0.8, // Skin thickness in mm (converted to layer count internally)
infillSpeed: 60, // Speed for skin infill lines
perimeterSpeed: 45, // Speed for skin perimeter
nozzleDiameter: 0.4, // Line spacing equals nozzle diameter
nozzleTemperature: 200,
bedTemperature: 60
});
const gcode = slicer.slice(mesh);Type: Number | Default: 0.8 | Unit: mm
Thickness of solid layers at top and bottom surfaces. The actual number of skin layers is calculated internally based on layer height.
- 0.4mm (1-2 layers) - Thin skin, may show infill pattern through
- 0.6-0.8mm (3 layers at 0.2mm height) - Good balance (default)
- 1.0mm+ (5+ layers) - Very solid, better for functional parts
slicer.setShellSkinThickness(1.0); // ~5 layers at 0.2mm layer height
const thickness = slicer.getShellSkinThickness(); // 1.0A single perimeter is drawn around the skin boundary first:
// Create inset path for skin wall
skinWallPath = createInsetPath(boundaryPath, nozzleDiameter);
// Generate perimeter around skin area
for (point in skinWallPath) {
// Calculate extrusion and generate G-code
}Solid diagonal lines fill the skin area:
// Generate 45° lines with nozzle-diameter spacing
// Alternates between +45° and -45° per layer
useNegativeSlope = (layerIndex % 2) === 1;
// Generate lines across the skin area
// Clip to boundary and avoid holes- Even layers - +45° diagonal lines (y = x + offset)
- Odd layers - -45° diagonal lines (y = -x + offset)
- Spacing - Equal to nozzle diameter (solid fill)
generateSkinGCode(slicer, boundaryPath, z, centerOffsetX, centerOffsetY, layerIndex, lastWallPoint, isHole, generateInfill, holeSkinWalls, holeOuterWalls, coveredAreaSkinWalls, isCoveredArea)
Main skin generation function.
Parameters:
| Parameter | Type | Description |
|---|---|---|
slicer |
Object | Polyslice slicer instance |
boundaryPath |
Array | Skin boundary points |
z |
Number | Z-coordinate for layer |
centerOffsetX |
Number | X offset for centering |
centerOffsetY |
Number | Y offset for centering |
layerIndex |
Number | Current layer index |
lastWallPoint |
Object | Last position for combing |
isHole |
Boolean | Is this a hole boundary? |
generateInfill |
Boolean | Generate diagonal infill? |
holeSkinWalls |
Array | Hole boundaries to exclude |
holeOuterWalls |
Array | Holes for travel avoidance |
coveredAreaSkinWalls |
Array | Covered areas to exclude |
isCoveredArea |
Boolean | Is this a covered area? |
Returns: Object - Last endpoint for combing tracking
Skin sections are marked in the G-code:
; TYPE: SKIN
G0 X15.00 Y10.00 Z0.60 F9000 ; Move to skin wall
G1 X45.00 Y10.00 E1.20 F2700 ; Skin wall segment
G1 X45.00 Y40.00 E2.40 F2700 ; Skin wall segment
G1 X15.00 Y40.00 E3.60 F2700 ; Skin wall segment
G1 X15.00 Y10.00 E4.80 F2700 ; Close skin wall
; Moving to skin infill line
G0 X16.00 Y11.00 Z0.60 F9000
G1 X44.00 Y39.00 E5.90 F3600 ; Diagonal infill line
; Moving to skin infill line
G0 X16.40 Y11.40 Z0.60 F9000
G1 X43.60 Y38.60 E6.98 F3600 ; Next diagonal line
...The skin module properly handles holes in skin regions:
When a hole is detected in a skin layer, a skin wall is generated around it:
// Hole detected in skin region
// Generate skin wall around hole perimeter
generateSkinGCode(slicer, holePath, z, ..., isHole=true, generateInfill=false);Skin infill lines are clipped to exclude hole areas:
// Create gap-adjusted hole boundaries
holeSkinWallsWithGap = [];
for (holeWall in holeSkinWalls) {
holeWithGap = createInsetPath(holeWall, infillGap, true);
holeSkinWallsWithGap.push(holeWithGap);
}
// Clip infill lines against boundaries
clippedSegments = clipLineWithHoles(lineStart, lineEnd, boundary, holeSkinWallsWithGap);Skin can detect and handle fully covered regions (cavities):
Areas that have solid geometry both above and below, like:
- Interior of a closed box
- Between layers of a thick section
- Areas that shouldn't get skin treatment
Covered areas are excluded from skin infill to avoid over-extrusion:
// Covered areas used directly as exclusion zones
coveredAreaSkinWallsWithGap = coveredAreaSkinWalls; // No additional offset
// Combine with hole walls for clipping
allExclusionWalls = holeSkinWallsWithGap.concat(coveredAreaSkinWallsWithGap);
clippedSegments = clipLineWithHoles(start, end, boundary, allExclusionWalls);Travel moves use combing to avoid crossing holes:
combingPath = findCombingPath(lastWallPoint, targetPoint, holeOuterWalls, boundaryPath, nozzleDiameter);Skin lines are printed in optimal order:
- Start from current position
- Find nearest unprinted line endpoint
- Print that line (possibly reversed)
- Repeat until all lines printed
The diagonal pattern alternates per layer for strength:
| Layer | Pattern | Equation |
|---|---|---|
| Even (0, 2, 4...) | +45° | y = x + offset |
| Odd (1, 3, 5...) | -45° | y = -x + offset |
This creates a crosshatch pattern over multiple layers.
src/slicer/skin/
├── skin.coffee # Main skin generation
├── skin.test.coffee # Skin tests
└── exposure/ # Exposure detection
├── exposure.coffee # Exposure detection module
├── exposure.test.coffee
├── cavity.coffee # Cavity detection
└── cavity.test.coffee
- EXPOSURE_DETECTION.md - Adaptive skin for exposed surfaces
- INFILL.md - Interior fill patterns
- WALLS.md - Wall generation
- COMBING.md - Travel path optimization
| Use Case | Recommended Thickness | ~Layers (0.2mm height) |
|---|---|---|
| Fast prototypes | 0.4mm | 2 layers |
| General prints | 0.6mm | 3 layers |
| High quality | 0.8-1.0mm | 4-5 layers |
| Waterproof | 1.0mm+ | 5+ layers |
- Proper overlap - Skin should overlap slightly with walls
- Consistent flow - Calibrate extrusion for solid fill
- Temperature - Ensure proper layer adhesion
- Speed - Slower speeds for better surface finish