mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-26 15:34:57 +01:00
Merge branch 'develop'
This commit is contained in:
commit
281b037f9e
@ -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);
|
}));
|
||||||
});
|
|
||||||
```
|
```
|
||||||
|
@ -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>`);
|
||||||
});
|
});
|
||||||
|
@ -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",
|
||||||
|
@ -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"
|
||||||
|
@ -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) {
|
||||||
const slicerWorker = new SlicerWorker();
|
if (!this.geometry) {
|
||||||
|
throw new Error('Geometry is not set, use Slicer.setGeometry or Slicer.setMesh first');
|
||||||
|
}
|
||||||
|
|
||||||
const geometry = this.geometry.toJSON();
|
return new Promise((resolve, reject) => {
|
||||||
|
// create the slicer worker
|
||||||
return new ProgressPromise((resolve, reject, progress) => {
|
const slicerWorker = new SlicerWorker();
|
||||||
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 }
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
12
src/sliceActions/generateOutlines.js
Normal file
12
src/sliceActions/generateOutlines.js
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
@ -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) {
|
||||||
|
@ -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 };
|
||||||
|
|
@ -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';
|
||||||
|
|
||||||
|
@ -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');
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user