diff --git a/README.md b/README.md index c813056..5f45975 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,8 @@ const geometry = new THREE.TorusGeometry(20, 10, 30, 30); const slicer = new SLICER.Slicer(); slicer.setGeometry(geometry); -const gcode = await slicer.slice(settings) - .progress(({ done, total, action }) => { - const percentage = `${(done / total * 100).toFixed()}%` - console.log(action, percentage); - }); +const gcode = await slicer.slice(settings, ({ progress: { done, total, action } }) => { + const percentage = `${(done / total * 100).toFixed()}%` + console.log(action, percentage); +})); ``` diff --git a/example/save.js b/example/save.js index 353ef0d..9524c6c 100644 --- a/example/save.js +++ b/example/save.js @@ -17,7 +17,7 @@ jsonLoader.load('models/airplane.json', async geometry => { const slicer = new Slicer().setGeometry(geometry); const gcode = await slicer.slice(settings) - .progress(({ done, total, action }) => { + .progress(({ progress: { done, total, action } }) => { const percentage = `${(done / total * 100).toFixed()}%` document.write(`

${action}, ${percentage}

`); }); diff --git a/jspm.config.js b/jspm.config.js index 39be6b7..fccd3c9 100644 --- a/jspm.config.js +++ b/jspm.config.js @@ -151,7 +151,6 @@ SystemJS.config({ ], map: { "three": "npm:three@0.83.0", - "progress-promise": "npm:progress-promise@0.0.6", "text": "github:systemjs/plugin-text@0.0.11", "js-yaml": "npm:js-yaml@3.9.0", "clipper-js": "github:Doodle3D/clipper-js@1.0.2", diff --git a/package.json b/package.json index 45167f8..c46dbe3 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "clipper-js": "github:Doodle3D/clipper-js@1.0.2", "js-yaml": "npm:js-yaml@^3.9.0", "json": "github:systemjs/plugin-json@^0.1.2", - "progress-promise": "npm:progress-promise@^0.0.6", "text": "github:systemjs/plugin-text@^0.0.11", "three": "npm:three@0.83.0", "worker": "github:casperlamboo/plugin-worker@master" diff --git a/src/Slicer.js b/src/Slicer.js index 280a6df..c80959b 100644 --- a/src/Slicer.js +++ b/src/Slicer.js @@ -1,15 +1,12 @@ import * as THREE from 'three'; import slice from './sliceActions/slice.js'; import SlicerWorker from './slicerWorker.js!worker'; -import ProgressPromise from 'progress-promise'; export default class { setMesh(mesh) { mesh.updateMatrix(); - this.setGeometry(mesh.geometry, mesh.matrix); - - return this; + return this.setGeometry(mesh.geometry, mesh.matrix); } setGeometry(geometry, matrix) { if (geometry.isBufferGeometry) { @@ -20,7 +17,7 @@ export default class { throw new Error('Geometry is not an instance of BufferGeometry or Geometry'); } - if (matrix) { + if (typeof matrix !== 'undefined') { geometry.applyMatrix(matrix); } @@ -28,17 +25,20 @@ export default class { return this; } - sliceSync(settings, onprogress) { - return slice(this.geometry, settings, onprogress); + sliceSync(settings, onProgress) { + return slice(this.geometry, settings, onProgress); } - slice(settings) { - const slicerWorker = new SlicerWorker(); + slice(settings, onProgress) { + if (!this.geometry) { + throw new Error('Geometry is not set, use Slicer.setGeometry or Slicer.setMesh first'); + } - const geometry = this.geometry.toJSON(); - - return new ProgressPromise((resolve, reject, progress) => { + return new Promise((resolve, reject) => { + // create the slicer worker + const slicerWorker = new SlicerWorker(); slicerWorker.onerror = reject; + // listen to messages send from worker slicerWorker.addEventListener('message', (event) => { const { message, data } = event.data; switch (message) { @@ -48,12 +48,14 @@ export default class { break; } case 'PROGRESS': { - progress(data); + onProgress(data); break; } } }); + // send geometry and settings to worker to start the slicing progress + const geometry = this.geometry.toJSON(); slicerWorker.postMessage({ message: 'SLICE', data: { geometry, settings } diff --git a/src/sliceActions/addBrim.js b/src/sliceActions/addBrim.js index 33d2475..9812598 100644 --- a/src/sliceActions/addBrim.js +++ b/src/sliceActions/addBrim.js @@ -8,7 +8,9 @@ const offsetOptions = { }; export default function addBrim(slices, settings) { - let { brim: { offset: brimOffset } } = settings; + let { + brim: { offset: brimOffset } + } = settings; brimOffset /= PRECISION; const [firstLayer] = slices; diff --git a/src/sliceActions/calculateLayersIntersections.js b/src/sliceActions/calculateLayersIntersections.js index 76b0e9f..78c2f21 100644 --- a/src/sliceActions/calculateLayersIntersections.js +++ b/src/sliceActions/calculateLayersIntersections.js @@ -1,7 +1,10 @@ import * as THREE from 'three'; export default function calculateLayersIntersections(lines, settings) { - const { layerHeight, dimensions: { z: dimensionsZ } } = settings; + const { + layerHeight, + dimensions: { z: dimensionsZ } + } = settings; const numLayers = Math.floor(dimensionsZ / layerHeight); @@ -9,9 +12,9 @@ export default function calculateLayersIntersections(lines, settings) { const layerIntersectionPoints = Array.from(Array(numLayers)).map(() => []); for (let lineIndex = 0; lineIndex < lines.length; lineIndex ++) { - const line = lines[lineIndex].line; + const { line, isFlat } = lines[lineIndex]; - if (line.isFlat) continue; + if (isFlat) continue; const min = Math.ceil(Math.min(line.start.y, line.end.y) / layerHeight); const max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight); diff --git a/src/sliceActions/createLines.js b/src/sliceActions/createLines.js index 188f1c3..5a6e3fc 100644 --- a/src/sliceActions/createLines.js +++ b/src/sliceActions/createLines.js @@ -25,7 +25,7 @@ export default function createLines(geometry, settings) { const lookupB = lineLookup[`${face.c}_${face.b}`]; const lookupC = lineLookup[`${face.a}_${face.c}`]; - const isFlat = face.normal.y !== 1 && face.normal.y !== -1; + const isFlat = face.normal.y > 0.999 || face.normal.y < -0.999; // only add unique lines // returns index of said line diff --git a/src/sliceActions/generateInfills.js b/src/sliceActions/generateInfills.js index f9ec418..e959475 100644 --- a/src/sliceActions/generateInfills.js +++ b/src/sliceActions/generateInfills.js @@ -26,8 +26,8 @@ export default function generateInfills(slices, settings) { let surroundingLayer; if (layer - bottomSkinCount >= 0 && layer + topSkinCount < slices.length) { - const downSkin = slices[layer - bottomSkinCount].getOutline(); - const upSkin = slices[layer + topSkinCount].getOutline(); + const downSkin = slices[layer - bottomSkinCount].outline; + const upSkin = slices[layer + topSkinCount].outline; surroundingLayer = upSkin.intersect(downSkin); } diff --git a/src/sliceActions/generateInnerLines.js b/src/sliceActions/generateInnerLines.js index a25550d..a829a43 100644 --- a/src/sliceActions/generateInnerLines.js +++ b/src/sliceActions/generateInnerLines.js @@ -9,7 +9,11 @@ const offsetOptions = { export default function generateInnerLines(slices, settings) { // need to scale up everything because of clipper rounding errors - let { layerHeight, nozzleDiameter, shell: { thickness: shellThickness } } = settings; + let { + layerHeight, + nozzleDiameter, + shell: { thickness: shellThickness } + } = settings; nozzleDiameter /= PRECISION; shellThickness /= PRECISION; const nozzleRadius = nozzleDiameter / 2; diff --git a/src/sliceActions/generateOutlines.js b/src/sliceActions/generateOutlines.js new file mode 100644 index 0000000..d98ccdf --- /dev/null +++ b/src/sliceActions/generateOutlines.js @@ -0,0 +1,12 @@ +import Shape from 'Doodle3D/clipper-js'; + +export default function calculateOutlines(slices, settings) { + for (let layer = 0; layer < slices.length; layer ++) { + const slice = slices[layer]; + + slice.outline = slice.parts.reduce((shape, part) => { + if (part.outerLine) shape.join(part.outerLine); + return shape; + }, new Shape([], true)); + } +} diff --git a/src/sliceActions/generateSupport.js b/src/sliceActions/generateSupport.js index 2a1a01e..d8d2e37 100644 --- a/src/sliceActions/generateSupport.js +++ b/src/sliceActions/generateSupport.js @@ -9,9 +9,9 @@ export default function generateSupport(slices, settings) { layerHeight, support: { gridSize: supportGridSize, - margin: AcceptanceMargin, + margin: supportMargin, plateSize: plateSize, - distanceY: DistanceY + distanceY: supportDistanceY }, nozzleDiameter } = settings; @@ -30,7 +30,7 @@ export default function generateSupport(slices, settings) { if (supportAreas.length > 0) { if (layer >= supportDistanceLayers) { - var sliceSkin = slices[layer - supportDistanceLayers].getOutline(); + var sliceSkin = slices[layer - supportDistanceLayers].outline; sliceSkin = sliceSkin; var supportAreasSlimmed = supportAreas.difference(sliceSkin.offset(supportMargin)); @@ -52,7 +52,7 @@ export default function generateSupport(slices, settings) { } } - var supportSkin = slices[layer + supportDistanceLayers - 1].getOutline(); + var supportSkin = slices[layer + supportDistanceLayers - 1].outline; var slice = slices[layer + supportDistanceLayers]; for (var i = 0; i < slice.parts.length; i ++) { @@ -62,10 +62,10 @@ export default function generateSupport(slices, settings) { var outerLine = slicePart.outerLine; } else { - var outerLine = slicePart.intersect.offset(supportAcceptanceMargin); + var outerLine = slicePart.intersect.offset(supportMargin); } - var overlap = supportSkin.offset(supportAcceptanceMargin).intersect(outerLine); + var overlap = supportSkin.offset(supportMargin).intersect(outerLine); var overhang = outerLine.difference(overlap); if (overlap.length === 0 || overhang.length > 0) { diff --git a/src/GCode.js b/src/sliceActions/helpers/GCode.js similarity index 100% rename from src/GCode.js rename to src/sliceActions/helpers/GCode.js diff --git a/src/Slice.js b/src/sliceActions/helpers/Slice.js similarity index 65% rename from src/Slice.js rename to src/sliceActions/helpers/Slice.js index c9a1ea3..4e1002e 100644 --- a/src/Slice.js +++ b/src/sliceActions/helpers/Slice.js @@ -4,12 +4,6 @@ export default class { constructor() { this.parts = []; } - getOutline() { - return this.parts.reduce((shape, part) => { - if (part.outerLine) shape.join(part.outerLine); - return shape; - }, new Shape([], true)); - } add(shape) { const part = { shape }; diff --git a/src/sliceActions/shapesToSlices.js b/src/sliceActions/shapesToSlices.js index 615d242..f77eaee 100644 --- a/src/sliceActions/shapesToSlices.js +++ b/src/sliceActions/shapesToSlices.js @@ -1,5 +1,5 @@ import Shape from 'Doodle3D/clipper-js'; -import Slice from '../Slice.js'; +import Slice from './helpers/Slice.js'; import { CLEAN_DELTA, PRECISION } from '../constants.js'; diff --git a/src/sliceActions/slice.js b/src/sliceActions/slice.js index 2042875..e0d63e1 100644 --- a/src/sliceActions/slice.js +++ b/src/sliceActions/slice.js @@ -2,6 +2,7 @@ import calculateLayersIntersections from './calculateLayersIntersections.js'; import createLines from './createLines.js'; import generateInfills from './generateInfills.js'; import generateInnerLines from './generateInnerLines.js'; +import generateOutlines from './generateOutlines.js'; import generateSupport from './generateSupport.js'; import intersectionsToShapes from './intersectionsToShapes.js'; import addBrim from './addBrim.js'; @@ -13,7 +14,7 @@ import applyPrecision from './applyPrecision.js'; import removePrecision from './removePrecision.js'; export default function(geometry, settings, onProgress) { - const totalStages = 11; + const totalStages = 12; let current = -1; const updateProgress = (action) => { current ++; @@ -27,7 +28,7 @@ export default function(geometry, settings, onProgress) { const lines = createLines(geometry, settings); updateProgress('Detecting open vs closed shapes'); - const openClosed = detectOpenClosed(lines); + detectOpenClosed(lines); updateProgress('Calculating layer intersections'); const { @@ -45,6 +46,8 @@ export default function(geometry, settings, onProgress) { updateProgress('Generating inner lines'); generateInnerLines(slices, settings); + updateProgress('Generating out lines'); + generateOutlines(slices, settings); updateProgress('Generating infills'); generateInfills(slices, settings); updateProgress('Generating support'); diff --git a/src/sliceActions/slicesToGCode.js b/src/sliceActions/slicesToGCode.js index 7268ae3..407619a 100644 --- a/src/sliceActions/slicesToGCode.js +++ b/src/sliceActions/slicesToGCode.js @@ -1,4 +1,4 @@ -import GCode from '../GCode.js'; +import GCode from './helpers/GCode.js'; export default function slicesToGCode(slices, settings) { const gcode = new GCode(settings); diff --git a/src/slicerWorker.js b/src/slicerWorker.js index a761bd4..ff1797e 100644 --- a/src/slicerWorker.js +++ b/src/slicerWorker.js @@ -6,7 +6,7 @@ const loader = new THREE.JSONLoader(); const onProgress = progress => { self.postMessage({ message: 'PROGRESS', - data: progress + data: { progress } }); } @@ -16,7 +16,7 @@ self.addEventListener('message', (event) => { case 'SLICE': { const { geometry: JSONGeometry, settings } = data; - const { geometry } = new loader.parse(JSONGeometry.data); + const { geometry } = loader.parse(JSONGeometry.data); const gcode = slice(geometry, settings, onProgress);