Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions examples/scripts/slice-adhesion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Slice script for adhesion examples
*
* This script slices cube and cylinder geometries with adhesion (skirt) enabled
* and saves the G-code to resources/gcode/adhesion for version control.
*/

const { Polyslice, Loader } = require('../../src/index');
const path = require('path');
const fs = require('fs');

console.log('Slicing Adhesion Examples');
console.log('=========================\n');

// Configuration for all slicing operations
const slicerConfig = {
// Adhesion settings
adhesionEnabled: true,
adhesionType: 'skirt',
adhesionDistance: 5,
adhesionLineCount: 3,

// Basic slicing settings
layerHeight: 0.2,
nozzleDiameter: 0.4,
shellWallThickness: 0.8,
shellSkinThickness: 0.8,
infillDensity: 20,
infillPattern: 'grid',

// Print settings
nozzleTemperature: 200,
bedTemperature: 60,
fanSpeed: 100,

// G-code settings
verbose: true,
metadata: false
};

// Define the geometries to slice (only cube and cylinder)
const geometries = [
{ name: 'Cube', file: 'cube/cube-1cm.stl', output: 'cube.gcode' },
{ name: 'Cylinder', file: 'cylinder/cylinder-1cm.stl', output: 'cylinder.gcode' }
];

// Create output directory
const outputDir = path.join(__dirname, '../../resources/gcode/adhesion');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}

console.log(`Output directory: ${outputDir}\n`);

// Process geometries with async/await
async function processGeometries() {
for (let index = 0; index < geometries.length; index++) {
const geometry = geometries[index];
console.log(`[${index + 1}/${geometries.length}] Slicing ${geometry.name}...`);

try {
// Build the full path to the STL file
const stlPath = path.join(__dirname, '../../resources/stl', geometry.file);

if (!fs.existsSync(stlPath)) {
console.error(` ✗ Error: File not found: ${stlPath}\n`);
continue;
}

// Load the STL file (async)
const mesh = await Loader.loadSTL(stlPath);

if (!mesh) {
console.error(` ✗ Error: Failed to load mesh\n`);
continue;
}

// Create slicer instance
const slicer = new Polyslice(slicerConfig);

// Generate G-code
const startTime = Date.now();
const gcode = slicer.slice(mesh);
const endTime = Date.now();
const slicingTime = ((endTime - startTime) / 1000).toFixed(2);

// Write output file
const outputPath = path.join(outputDir, geometry.output);
fs.writeFileSync(outputPath, gcode);

const fileSizeKB = (gcode.length / 1024).toFixed(2);
console.log(` ✓ ${geometry.output} (${fileSizeKB} KB) - ${slicingTime}s\n`);

} catch (error) {
console.error(` ✗ Error processing ${geometry.name}:`, error.message);
console.log('');
}
}

console.log('Adhesion examples sliced successfully!');
}

// Run the async process
processGeometries().catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
"test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch",
"test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage",
"slice": "npm run compile && node examples/scripts/slice-shapes.js && node examples/scripts/slice-holes.js && node examples/scripts/slice-pillars.js && node examples/scripts/slice-arch.js && node examples/scripts/slice-dome.js && node examples/scripts/slice-pyramid.js && node examples/scripts/slice-matryoshka.js && node examples/scripts/slice-lego.js && node examples/scripts/slice-benchy.js low-poly",
"slice": "npm run compile && node examples/scripts/slice-adhesion.js && node examples/scripts/slice-shapes.js && node examples/scripts/slice-holes.js && node examples/scripts/slice-pillars.js && node examples/scripts/slice-arch.js && node examples/scripts/slice-dome.js && node examples/scripts/slice-pyramid.js && node examples/scripts/slice-matryoshka.js && node examples/scripts/slice-lego.js && node examples/scripts/slice-benchy.js low-poly",
"lint": "eslint src/**/*.js",
"lint:fix": "eslint src/**/*.js --fix",
"format": "prettier --write src/**/*.js",
Expand Down
3 changes: 3 additions & 0 deletions resources/gcode/adhesion/cube.gcode
Git LFS file not shown
3 changes: 3 additions & 0 deletions resources/gcode/adhesion/cylinder.gcode
Git LFS file not shown
30 changes: 22 additions & 8 deletions src/polyslice.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,12 @@ class Polyslice
# Build plate adhesion settings for first layer stability.
@adhesionEnabled = options.adhesionEnabled ?= false # Boolean.
@adhesionType = options.adhesionType ?= "skirt" # String ['skirt', 'brim', 'raft'].
@adhesionSkirtType = options.adhesionSkirtType ?= "circular" # String ['circular', 'shape'].
@adhesionDistance = conversions.lengthToInternal(options.adhesionDistance ?= 5, this.lengthUnit) # Number (millimeters internal).
@adhesionLineCount = options.adhesionLineCount ?= 3 # Number.

# Test strip and outline settings for print preparation.
# Test strip settings for print preparation.
@testStrip = options.testStrip ?= false # Boolean - lay down test strip before main print.
@outline = options.outline ?= true # Boolean - make thin outline of layer 1 exterior.

# G-code generation settings.
@metadata = options.metadata ?= true # Boolean - include metadata header in G-code.
Expand Down Expand Up @@ -217,12 +219,18 @@ class Polyslice
getAdhesionType: ->
accessors.getAdhesionType(this)

getAdhesionSkirtType: ->
accessors.getAdhesionSkirtType(this)

getAdhesionDistance: ->
accessors.getAdhesionDistance(this)

getAdhesionLineCount: ->
accessors.getAdhesionLineCount(this)

getTestStrip: ->
accessors.getTestStrip(this)

getOutline: ->
accessors.getOutline(this)

getMetadata: ->
accessors.getMetadata(this)

Expand Down Expand Up @@ -360,12 +368,18 @@ class Polyslice
setAdhesionType: (type = "skirt") ->
accessors.setAdhesionType(this, type)

setAdhesionSkirtType: (type = "circular") ->
accessors.setAdhesionSkirtType(this, type)

setAdhesionDistance: (distance = 5) ->
accessors.setAdhesionDistance(this, distance)

setAdhesionLineCount: (count = 3) ->
accessors.setAdhesionLineCount(this, count)

setTestStrip: (testStrip = false) ->
accessors.setTestStrip(this, testStrip)

setOutline: (outline = true) ->
accessors.setOutline(this, outline)

setMetadata: (metadata = true) ->
accessors.setMetadata(this, metadata)

Expand Down
3 changes: 1 addition & 2 deletions src/polyslice.test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,8 @@ describe 'Polyslice', ->
expect(slicer.getAdhesionEnabled()).toBe(false)
expect(slicer.getAdhesionType()).toBe('skirt')

# Test new test strip and outline settings
# Test test strip setting
expect(slicer.getTestStrip()).toBe(false)
expect(slicer.getOutline()).toBe(true)

test 'should create instance with custom options', ->

Expand Down
38 changes: 38 additions & 0 deletions src/slicer/adhesion/adhesion.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Adhesion generation module for Polyslice.

skirtModule = require('./skirt/skirt')
brimModule = require('./brim/brim')
raftModule = require('./raft/raft')

module.exports =

# Generate G-code for build plate adhesion (skirt, brim, or raft).
generateAdhesionGCode: (slicer, mesh, centerOffsetX, centerOffsetY, boundingBox) ->

return unless slicer.getAdhesionEnabled()

adhesionType = slicer.getAdhesionType()
verbose = slicer.getVerbose()

# Dispatch to appropriate adhesion sub-module.
switch adhesionType

when 'skirt'

if verbose then slicer.gcode += "; TYPE: SKIRT" + slicer.newline

skirtModule.generateSkirt(slicer, mesh, centerOffsetX, centerOffsetY, boundingBox)

when 'brim'

if verbose then slicer.gcode += "; TYPE: BRIM" + slicer.newline

brimModule.generateBrim(slicer, mesh, centerOffsetX, centerOffsetY, boundingBox)

when 'raft'

if verbose then slicer.gcode += "; TYPE: RAFT" + slicer.newline

raftModule.generateRaft(slicer, mesh, centerOffsetX, centerOffsetY, boundingBox)

return
Loading