Merge branch 'develop'

This commit is contained in:
casperlamboo 2017-07-19 20:55:55 +02:00
commit 281b037f9e
18 changed files with 64 additions and 47 deletions

View File

@ -17,9 +17,8 @@ const geometry = new THREE.TorusGeometry(20, 10, 30, 30);
const slicer = new SLICER.Slicer(); const slicer = new SLICER.Slicer();
slicer.setGeometry(geometry); slicer.setGeometry(geometry);
const gcode = await slicer.slice(settings) const gcode = await slicer.slice(settings, ({ progress: { done, total, action } }) => {
.progress(({ done, total, action }) => {
const percentage = `${(done / total * 100).toFixed()}%` const percentage = `${(done / total * 100).toFixed()}%`
console.log(action, percentage); console.log(action, percentage);
}); }));
``` ```

View File

@ -17,7 +17,7 @@ jsonLoader.load('models/airplane.json', async geometry => {
const slicer = new Slicer().setGeometry(geometry); const slicer = new Slicer().setGeometry(geometry);
const gcode = await slicer.slice(settings) const gcode = await slicer.slice(settings)
.progress(({ done, total, action }) => { .progress(({ progress: { done, total, action } }) => {
const percentage = `${(done / total * 100).toFixed()}%` const percentage = `${(done / total * 100).toFixed()}%`
document.write(`<p>${action}, ${percentage}</p>`); document.write(`<p>${action}, ${percentage}</p>`);
}); });

View File

@ -151,7 +151,6 @@ SystemJS.config({
], ],
map: { map: {
"three": "npm:three@0.83.0", "three": "npm:three@0.83.0",
"progress-promise": "npm:progress-promise@0.0.6",
"text": "github:systemjs/plugin-text@0.0.11", "text": "github:systemjs/plugin-text@0.0.11",
"js-yaml": "npm:js-yaml@3.9.0", "js-yaml": "npm:js-yaml@3.9.0",
"clipper-js": "github:Doodle3D/clipper-js@1.0.2", "clipper-js": "github:Doodle3D/clipper-js@1.0.2",

View File

@ -10,7 +10,6 @@
"clipper-js": "github:Doodle3D/clipper-js@1.0.2", "clipper-js": "github:Doodle3D/clipper-js@1.0.2",
"js-yaml": "npm:js-yaml@^3.9.0", "js-yaml": "npm:js-yaml@^3.9.0",
"json": "github:systemjs/plugin-json@^0.1.2", "json": "github:systemjs/plugin-json@^0.1.2",
"progress-promise": "npm:progress-promise@^0.0.6",
"text": "github:systemjs/plugin-text@^0.0.11", "text": "github:systemjs/plugin-text@^0.0.11",
"three": "npm:three@0.83.0", "three": "npm:three@0.83.0",
"worker": "github:casperlamboo/plugin-worker@master" "worker": "github:casperlamboo/plugin-worker@master"

View File

@ -1,15 +1,12 @@
import * as THREE from 'three'; import * as THREE from 'three';
import slice from './sliceActions/slice.js'; import slice from './sliceActions/slice.js';
import SlicerWorker from './slicerWorker.js!worker'; import SlicerWorker from './slicerWorker.js!worker';
import ProgressPromise from 'progress-promise';
export default class { export default class {
setMesh(mesh) { setMesh(mesh) {
mesh.updateMatrix(); mesh.updateMatrix();
this.setGeometry(mesh.geometry, mesh.matrix); return this.setGeometry(mesh.geometry, mesh.matrix);
return this;
} }
setGeometry(geometry, matrix) { setGeometry(geometry, matrix) {
if (geometry.isBufferGeometry) { if (geometry.isBufferGeometry) {
@ -20,7 +17,7 @@ export default class {
throw new Error('Geometry is not an instance of BufferGeometry or Geometry'); throw new Error('Geometry is not an instance of BufferGeometry or Geometry');
} }
if (matrix) { if (typeof matrix !== 'undefined') {
geometry.applyMatrix(matrix); geometry.applyMatrix(matrix);
} }
@ -28,17 +25,20 @@ export default class {
return this; return this;
} }
sliceSync(settings, onprogress) { sliceSync(settings, onProgress) {
return slice(this.geometry, settings, onprogress); return slice(this.geometry, settings, onProgress);
} }
slice(settings) { slice(settings, onProgress) {
if (!this.geometry) {
throw new Error('Geometry is not set, use Slicer.setGeometry or Slicer.setMesh first');
}
return new Promise((resolve, reject) => {
// create the slicer worker
const slicerWorker = new SlicerWorker(); const slicerWorker = new SlicerWorker();
const geometry = this.geometry.toJSON();
return new ProgressPromise((resolve, reject, progress) => {
slicerWorker.onerror = reject; slicerWorker.onerror = reject;
// listen to messages send from worker
slicerWorker.addEventListener('message', (event) => { slicerWorker.addEventListener('message', (event) => {
const { message, data } = event.data; const { message, data } = event.data;
switch (message) { switch (message) {
@ -48,12 +48,14 @@ export default class {
break; break;
} }
case 'PROGRESS': { case 'PROGRESS': {
progress(data); onProgress(data);
break; break;
} }
} }
}); });
// send geometry and settings to worker to start the slicing progress
const geometry = this.geometry.toJSON();
slicerWorker.postMessage({ slicerWorker.postMessage({
message: 'SLICE', message: 'SLICE',
data: { geometry, settings } data: { geometry, settings }

View File

@ -8,7 +8,9 @@ const offsetOptions = {
}; };
export default function addBrim(slices, settings) { export default function addBrim(slices, settings) {
let { brim: { offset: brimOffset } } = settings; let {
brim: { offset: brimOffset }
} = settings;
brimOffset /= PRECISION; brimOffset /= PRECISION;
const [firstLayer] = slices; const [firstLayer] = slices;

View File

@ -1,7 +1,10 @@
import * as THREE from 'three'; import * as THREE from 'three';
export default function calculateLayersIntersections(lines, settings) { export default function calculateLayersIntersections(lines, settings) {
const { layerHeight, dimensions: { z: dimensionsZ } } = settings; const {
layerHeight,
dimensions: { z: dimensionsZ }
} = settings;
const numLayers = Math.floor(dimensionsZ / layerHeight); const numLayers = Math.floor(dimensionsZ / layerHeight);
@ -9,9 +12,9 @@ export default function calculateLayersIntersections(lines, settings) {
const layerIntersectionPoints = Array.from(Array(numLayers)).map(() => []); const layerIntersectionPoints = Array.from(Array(numLayers)).map(() => []);
for (let lineIndex = 0; lineIndex < lines.length; lineIndex ++) { 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 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); const max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight);

View File

@ -25,7 +25,7 @@ export default function createLines(geometry, settings) {
const lookupB = lineLookup[`${face.c}_${face.b}`]; const lookupB = lineLookup[`${face.c}_${face.b}`];
const lookupC = lineLookup[`${face.a}_${face.c}`]; 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 // only add unique lines
// returns index of said line // returns index of said line

View File

@ -26,8 +26,8 @@ export default function generateInfills(slices, settings) {
let surroundingLayer; let surroundingLayer;
if (layer - bottomSkinCount >= 0 && layer + topSkinCount < slices.length) { if (layer - bottomSkinCount >= 0 && layer + topSkinCount < slices.length) {
const downSkin = slices[layer - bottomSkinCount].getOutline(); const downSkin = slices[layer - bottomSkinCount].outline;
const upSkin = slices[layer + topSkinCount].getOutline(); const upSkin = slices[layer + topSkinCount].outline;
surroundingLayer = upSkin.intersect(downSkin); surroundingLayer = upSkin.intersect(downSkin);
} }

View File

@ -9,7 +9,11 @@ const offsetOptions = {
export default function generateInnerLines(slices, settings) { export default function generateInnerLines(slices, settings) {
// need to scale up everything because of clipper rounding errors // 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; nozzleDiameter /= PRECISION;
shellThickness /= PRECISION; shellThickness /= PRECISION;
const nozzleRadius = nozzleDiameter / 2; const nozzleRadius = nozzleDiameter / 2;

View File

@ -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));
}
}

View File

@ -9,9 +9,9 @@ export default function generateSupport(slices, settings) {
layerHeight, layerHeight,
support: { support: {
gridSize: supportGridSize, gridSize: supportGridSize,
margin: AcceptanceMargin, margin: supportMargin,
plateSize: plateSize, plateSize: plateSize,
distanceY: DistanceY distanceY: supportDistanceY
}, },
nozzleDiameter nozzleDiameter
} = settings; } = settings;
@ -30,7 +30,7 @@ export default function generateSupport(slices, settings) {
if (supportAreas.length > 0) { if (supportAreas.length > 0) {
if (layer >= supportDistanceLayers) { if (layer >= supportDistanceLayers) {
var sliceSkin = slices[layer - supportDistanceLayers].getOutline(); var sliceSkin = slices[layer - supportDistanceLayers].outline;
sliceSkin = sliceSkin; sliceSkin = sliceSkin;
var supportAreasSlimmed = supportAreas.difference(sliceSkin.offset(supportMargin)); 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]; var slice = slices[layer + supportDistanceLayers];
for (var i = 0; i < slice.parts.length; i ++) { for (var i = 0; i < slice.parts.length; i ++) {
@ -62,10 +62,10 @@ export default function generateSupport(slices, settings) {
var outerLine = slicePart.outerLine; var outerLine = slicePart.outerLine;
} }
else { 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); var overhang = outerLine.difference(overlap);
if (overlap.length === 0 || overhang.length > 0) { if (overlap.length === 0 || overhang.length > 0) {

View File

@ -4,12 +4,6 @@ export default class {
constructor() { constructor() {
this.parts = []; this.parts = [];
} }
getOutline() {
return this.parts.reduce((shape, part) => {
if (part.outerLine) shape.join(part.outerLine);
return shape;
}, new Shape([], true));
}
add(shape) { add(shape) {
const part = { shape }; const part = { shape };

View File

@ -1,5 +1,5 @@
import Shape from 'Doodle3D/clipper-js'; import Shape from 'Doodle3D/clipper-js';
import Slice from '../Slice.js'; import Slice from './helpers/Slice.js';
import { CLEAN_DELTA, PRECISION } from '../constants.js'; import { CLEAN_DELTA, PRECISION } from '../constants.js';

View File

@ -2,6 +2,7 @@ import calculateLayersIntersections from './calculateLayersIntersections.js';
import createLines from './createLines.js'; import createLines from './createLines.js';
import generateInfills from './generateInfills.js'; import generateInfills from './generateInfills.js';
import generateInnerLines from './generateInnerLines.js'; import generateInnerLines from './generateInnerLines.js';
import generateOutlines from './generateOutlines.js';
import generateSupport from './generateSupport.js'; import generateSupport from './generateSupport.js';
import intersectionsToShapes from './intersectionsToShapes.js'; import intersectionsToShapes from './intersectionsToShapes.js';
import addBrim from './addBrim.js'; import addBrim from './addBrim.js';
@ -13,7 +14,7 @@ import applyPrecision from './applyPrecision.js';
import removePrecision from './removePrecision.js'; import removePrecision from './removePrecision.js';
export default function(geometry, settings, onProgress) { export default function(geometry, settings, onProgress) {
const totalStages = 11; const totalStages = 12;
let current = -1; let current = -1;
const updateProgress = (action) => { const updateProgress = (action) => {
current ++; current ++;
@ -27,7 +28,7 @@ export default function(geometry, settings, onProgress) {
const lines = createLines(geometry, settings); const lines = createLines(geometry, settings);
updateProgress('Detecting open vs closed shapes'); updateProgress('Detecting open vs closed shapes');
const openClosed = detectOpenClosed(lines); detectOpenClosed(lines);
updateProgress('Calculating layer intersections'); updateProgress('Calculating layer intersections');
const { const {
@ -45,6 +46,8 @@ export default function(geometry, settings, onProgress) {
updateProgress('Generating inner lines'); updateProgress('Generating inner lines');
generateInnerLines(slices, settings); generateInnerLines(slices, settings);
updateProgress('Generating out lines');
generateOutlines(slices, settings);
updateProgress('Generating infills'); updateProgress('Generating infills');
generateInfills(slices, settings); generateInfills(slices, settings);
updateProgress('Generating support'); updateProgress('Generating support');

View File

@ -1,4 +1,4 @@
import GCode from '../GCode.js'; import GCode from './helpers/GCode.js';
export default function slicesToGCode(slices, settings) { export default function slicesToGCode(slices, settings) {
const gcode = new GCode(settings); const gcode = new GCode(settings);

View File

@ -6,7 +6,7 @@ const loader = new THREE.JSONLoader();
const onProgress = progress => { const onProgress = progress => {
self.postMessage({ self.postMessage({
message: 'PROGRESS', message: 'PROGRESS',
data: progress data: { progress }
}); });
} }
@ -16,7 +16,7 @@ self.addEventListener('message', (event) => {
case 'SLICE': { case 'SLICE': {
const { geometry: JSONGeometry, settings } = data; const { geometry: JSONGeometry, settings } = data;
const { geometry } = new loader.parse(JSONGeometry.data); const { geometry } = loader.parse(JSONGeometry.data);
const gcode = slice(geometry, settings, onProgress); const gcode = slice(geometry, settings, onProgress);