mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-22 21:47:59 +01:00
Merge branch 'develop'
This commit is contained in:
commit
48f2cef965
@ -9,6 +9,7 @@ const settings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone();
|
const geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone();
|
||||||
|
geometry.mergeVertices();
|
||||||
|
|
||||||
const onProgress = ({ progress: { done, total, action } }) => {
|
const onProgress = ({ progress: { done, total, action } }) => {
|
||||||
const percentage = `${(done / total * 100).toFixed()}%`
|
const percentage = `${(done / total * 100).toFixed()}%`
|
||||||
@ -17,4 +18,4 @@ const onProgress = ({ progress: { done, total, action } }) => {
|
|||||||
|
|
||||||
sliceGeometry(settings, geometry, null, false, onProgress).then(gcode => {
|
sliceGeometry(settings, geometry, null, false, onProgress).then(gcode => {
|
||||||
document.body.innerHTML = gcode.replace(/(?:\r\n|\r|\n)/g, '<br />');
|
document.body.innerHTML = gcode.replace(/(?:\r\n|\r|\n)/g, '<br />');
|
||||||
});
|
});
|
||||||
|
@ -2,49 +2,49 @@ dimensions:
|
|||||||
x: 200
|
x: 200
|
||||||
y: 200
|
y: 200
|
||||||
z: 200
|
z: 200
|
||||||
temperature: 210
|
|
||||||
bedTemperature: 70
|
|
||||||
# heatBedTemperature: 20
|
|
||||||
# heatTemperature: 20
|
|
||||||
# heatupEnabled: true
|
|
||||||
travelSpeed: 200.0
|
|
||||||
layerHeight: 0.15
|
|
||||||
heatedBed: false
|
heatedBed: false
|
||||||
nozzleDiameter: 0.4
|
nozzleDiameter: 0.4
|
||||||
filamentThickness: 2.85
|
filamentThickness: 2.85
|
||||||
|
temperature: 210
|
||||||
|
bedTemperature: 70
|
||||||
|
layerHeight: 0.15
|
||||||
|
thickness:
|
||||||
|
top: 1.2
|
||||||
|
bottom: 1.2
|
||||||
|
shell: 0.8
|
||||||
retraction:
|
retraction:
|
||||||
amount: 3.0
|
|
||||||
enabled: true
|
enabled: true
|
||||||
|
amount: 3.0
|
||||||
speed: 50.0
|
speed: 50.0
|
||||||
minDistance: 0.0
|
minDistance: 0.0
|
||||||
|
travel:
|
||||||
|
speed: 200.0
|
||||||
support:
|
support:
|
||||||
|
enabled: false
|
||||||
acceptanceMargin: 1.5
|
acceptanceMargin: 1.5
|
||||||
distanceY: 0.4
|
distanceY: 0.4
|
||||||
enabled: false
|
|
||||||
gridSize: 6.0
|
gridSize: 6.0
|
||||||
margin: 2.0
|
margin: 2.0
|
||||||
plateSize: 4.0
|
plateSize: 4.0
|
||||||
flowRate: 0.8
|
flowRate: 0.8
|
||||||
speed: 40.0
|
speed: 40.0
|
||||||
outerLine:
|
innerShell:
|
||||||
|
flowRate: 1.0
|
||||||
|
speed: 50.0
|
||||||
|
outerShell:
|
||||||
flowRate: 1.0
|
flowRate: 1.0
|
||||||
speed: 40.0
|
speed: 40.0
|
||||||
innerLine:
|
innerInfill:
|
||||||
flowRate: 1.0
|
flowRate: 1.0
|
||||||
speed: 50.0
|
speed: 80.0
|
||||||
fill:
|
|
||||||
flowRate: 1.0
|
|
||||||
speed: 50.0
|
|
||||||
gridSize: 5.0
|
gridSize: 5.0
|
||||||
|
outerInfill:
|
||||||
|
flowRate: 1.0
|
||||||
|
speed: 50.0
|
||||||
brim:
|
brim:
|
||||||
|
offset: 4.0
|
||||||
flowRate: 1.0
|
flowRate: 1.0
|
||||||
speed: 40.0
|
speed: 40.0
|
||||||
offset: 4.0
|
firstLayer:
|
||||||
top:
|
|
||||||
thickness: 1.2
|
|
||||||
bottom:
|
|
||||||
flowRate: 1.2
|
flowRate: 1.2
|
||||||
speed: 40.0
|
speed: 40.0
|
||||||
thickness: 0.4
|
|
||||||
shell:
|
|
||||||
thickness: 0.4
|
|
||||||
|
@ -2,10 +2,11 @@ import { PRECISION } from '../constants.js'
|
|||||||
|
|
||||||
export default function applyPrecision(shapes) {
|
export default function applyPrecision(shapes) {
|
||||||
for (let i = 0; i < shapes.length; i ++) {
|
for (let i = 0; i < shapes.length; i ++) {
|
||||||
const { closedShapes, openShapes } = shapes[i];
|
const { fillShapes, lineShapesOpen, lineShapesClosed } = shapes[i];
|
||||||
|
|
||||||
scaleUpShape(closedShapes);
|
scaleUpShape(fillShapes);
|
||||||
scaleUpShape(openShapes);
|
scaleUpShape(lineShapesOpen);
|
||||||
|
scaleUpShape(lineShapesClosed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,19 +5,21 @@ import Shape from 'clipper-js';
|
|||||||
export default function generateInfills(slices, settings) {
|
export default function generateInfills(slices, settings) {
|
||||||
let {
|
let {
|
||||||
layerHeight,
|
layerHeight,
|
||||||
fill: { gridSize: fillGridSize },
|
innerInfill: { gridSize: infillGridSize },
|
||||||
bottom: { thickness: bottomThickness },
|
thickness: {
|
||||||
top: { thickness: topThickness },
|
top: topThickness,
|
||||||
|
bottom: bottomThickness
|
||||||
|
},
|
||||||
nozzleDiameter
|
nozzleDiameter
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
fillGridSize /= PRECISION;
|
infillGridSize /= PRECISION;
|
||||||
nozzleDiameter /= PRECISION;
|
nozzleDiameter /= PRECISION;
|
||||||
|
|
||||||
const bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
|
const bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
|
||||||
const topSkinCount = Math.ceil(topThickness/layerHeight);
|
const topSkinCount = Math.ceil(topThickness/layerHeight);
|
||||||
const nozzleRadius = nozzleDiameter / 2;
|
const nozzleRadius = nozzleDiameter / 2;
|
||||||
const hightemplateSize = Math.sqrt(2 * Math.pow(nozzleDiameter, 2));
|
const outerFillTemplateSize = Math.sqrt(2 * Math.pow(nozzleDiameter, 2));
|
||||||
|
|
||||||
for (let layer = 0; layer < slices.length; layer ++) {
|
for (let layer = 0; layer < slices.length; layer ++) {
|
||||||
const slice = slices[layer];
|
const slice = slices[layer];
|
||||||
@ -32,39 +34,35 @@ export default function generateInfills(slices, settings) {
|
|||||||
for (let i = 0; i < slice.parts.length; i ++) {
|
for (let i = 0; i < slice.parts.length; i ++) {
|
||||||
const part = slice.parts[i];
|
const part = slice.parts[i];
|
||||||
|
|
||||||
if (!part.shape.closed) {
|
if (!part.closed) continue;
|
||||||
continue;
|
|
||||||
|
const innerShell = part.shell[part.shell.length - 1];
|
||||||
|
|
||||||
|
if (innerShell.paths.length === 0) continue;
|
||||||
|
|
||||||
|
const fillArea = innerShell.offset(-nozzleRadius);
|
||||||
|
let innerFillArea;
|
||||||
|
let outerFillArea;
|
||||||
|
if (surroundingLayer) {
|
||||||
|
outerFillArea = fillArea.difference(surroundingLayer).intersect(fillArea);
|
||||||
|
innerFillArea = fillArea.difference(outerFillArea);
|
||||||
|
} else {
|
||||||
|
outerFillArea = fillArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
const outerLine = part.outerLine;
|
if (innerFillArea && innerFillArea.paths.length > 0) {
|
||||||
|
const bounds = innerFillArea.shapeBounds();
|
||||||
|
const innerFillTemplate = getFillTemplate(bounds, infillGridSize, true, true);
|
||||||
|
|
||||||
if (outerLine.paths.length > 0) {
|
part.innerFill.join(innerFillTemplate.intersect(innerFillArea));
|
||||||
const inset = (part.innerLines.length > 0) ? part.innerLines[part.innerLines.length - 1] : outerLine;
|
}
|
||||||
|
|
||||||
const fillArea = inset.offset(-nozzleRadius);
|
if (outerFillArea.paths.length > 0) {
|
||||||
let lowFillArea;
|
const bounds = outerFillArea.shapeBounds();
|
||||||
let highFillArea;
|
const even = (layer % 2 === 0);
|
||||||
if (surroundingLayer) {
|
const outerFillTemplate = getFillTemplate(bounds, outerFillTemplateSize, even, !even);
|
||||||
highFillArea = fillArea.difference(surroundingLayer).intersect(fillArea);
|
|
||||||
lowFillArea = fillArea.difference(highFillArea);
|
|
||||||
} else {
|
|
||||||
highFillArea = fillArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lowFillArea && lowFillArea.paths.length > 0) {
|
part.outerFill.join(outerFillTemplate.intersect(outerFillArea));
|
||||||
const bounds = lowFillArea.shapeBounds();
|
|
||||||
const lowFillTemplate = getFillTemplate(bounds, fillGridSize, true, true);
|
|
||||||
|
|
||||||
part.fill.join(lowFillTemplate.intersect(lowFillArea));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (highFillArea.paths.length > 0) {
|
|
||||||
const bounds = highFillArea.shapeBounds();
|
|
||||||
const even = (layer % 2 === 0);
|
|
||||||
const highFillTemplate = getFillTemplate(bounds, hightemplateSize, even, !even);
|
|
||||||
|
|
||||||
part.fill.join(highFillTemplate.intersect(highFillArea));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,14 @@ export default function generateInnerLines(slices, settings) {
|
|||||||
let {
|
let {
|
||||||
layerHeight,
|
layerHeight,
|
||||||
nozzleDiameter,
|
nozzleDiameter,
|
||||||
shell: { thickness: shellThickness }
|
thickness: { shell: shellThickness }
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
nozzleDiameter /= PRECISION;
|
nozzleDiameter /= PRECISION;
|
||||||
shellThickness /= PRECISION;
|
shellThickness /= PRECISION;
|
||||||
|
|
||||||
const nozzleRadius = nozzleDiameter / 2;
|
const nozzleRadius = nozzleDiameter / 2;
|
||||||
const shells = Math.round(shellThickness / nozzleDiameter);
|
const numShells = Math.round(shellThickness / nozzleDiameter);
|
||||||
|
|
||||||
for (let layer = 0; layer < slices.length; layer ++) {
|
for (let layer = 0; layer < slices.length; layer ++) {
|
||||||
const slice = slices[layer];
|
const slice = slices[layer];
|
||||||
@ -25,21 +27,21 @@ export default function generateInnerLines(slices, settings) {
|
|||||||
for (let i = 0; i < slice.parts.length; i ++) {
|
for (let i = 0; i < slice.parts.length; i ++) {
|
||||||
const part = slice.parts[i];
|
const part = slice.parts[i];
|
||||||
|
|
||||||
if (!part.shape.closed) continue;
|
if (!part.closed) continue;
|
||||||
|
|
||||||
const outerLine = part.shape.offset(-nozzleRadius, offsetOptions);
|
const outerLine = part.shape.offset(-nozzleRadius, offsetOptions);
|
||||||
|
|
||||||
if (outerLine.paths.length > 0) {
|
if (outerLine.paths.length > 0) {
|
||||||
part.outerLine.join(outerLine);
|
part.shell.push(outerLine);
|
||||||
|
|
||||||
// start with 1 because outerLine is the 1st (0) shell
|
// start with 1 because outerLine is the 1st (0) shell
|
||||||
for (let shell = 1; shell < shells; shell += 1) {
|
for (let inset = 1; inset < numShells; inset += 1) {
|
||||||
const offset = shell * nozzleDiameter;
|
const offset = inset * nozzleDiameter;
|
||||||
|
|
||||||
const innerLine = outerLine.offset(-offset, offsetOptions);
|
const shell = outerLine.offset(-offset, offsetOptions);
|
||||||
|
|
||||||
if (innerLine.paths.length > 0) {
|
if (shell.paths.length > 0) {
|
||||||
part.innerLines.push(innerLine);
|
part.shell.push(shell);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,10 @@ export default function calculateOutlines(slices, settings) {
|
|||||||
const slice = slices[layer];
|
const slice = slices[layer];
|
||||||
|
|
||||||
slice.outline = slice.parts.reduce((shape, part) => {
|
slice.outline = slice.parts.reduce((shape, part) => {
|
||||||
if (part.outerLine) shape.join(part.outerLine);
|
if (part.closed) {
|
||||||
|
const [outerLine] = part.shell;
|
||||||
|
shape.join(outerLine);
|
||||||
|
}
|
||||||
return shape;
|
return shape;
|
||||||
}, new Shape([], true));
|
}, new Shape([], true));
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,15 @@ const POSITION_Y = 'Y';
|
|||||||
const POSITION_Z = 'Z';
|
const POSITION_Z = 'Z';
|
||||||
|
|
||||||
export default class {
|
export default class {
|
||||||
constructor(settings) {
|
constructor(nozzleToFilamentRatio) {
|
||||||
|
this._nozzleToFilamentRatio = nozzleToFilamentRatio;
|
||||||
|
|
||||||
this._gcode = '';
|
this._gcode = '';
|
||||||
this._currentValues = {};
|
this._currentValues = {};
|
||||||
this._settings = settings;
|
|
||||||
this._nozzlePosition = new THREE.Vector2(0, 0);
|
this._nozzlePosition = new THREE.Vector2(0, 0);
|
||||||
this._extruder = 0.0;
|
this._extruder = 0.0;
|
||||||
this._isRetracted = false;
|
this._isRetracted = false;
|
||||||
this._isFanOn = false;
|
this._isFanOn = false;
|
||||||
|
|
||||||
this.bottom = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_addGCode(command) {
|
_addGCode(command) {
|
||||||
@ -62,14 +61,8 @@ export default class {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTo(x, y, layer) {
|
moveTo(x, y, z, { speed }) {
|
||||||
const {
|
speed *= 60;
|
||||||
layerHeight,
|
|
||||||
travelSpeed
|
|
||||||
} = this._settings;
|
|
||||||
|
|
||||||
const z = layer * layerHeight + 0.2;
|
|
||||||
const speed = travelSpeed * 60;
|
|
||||||
|
|
||||||
this._addGCode({
|
this._addGCode({
|
||||||
[MOVE]: 0,
|
[MOVE]: 0,
|
||||||
@ -84,30 +77,13 @@ export default class {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
lineTo(x, y, layer, type) {
|
lineTo(x, y, z, { speed, flowRate }) {
|
||||||
const newNozzlePosition = new THREE.Vector2(x, y);
|
const newNozzlePosition = new THREE.Vector2(x, y);
|
||||||
|
|
||||||
const {
|
|
||||||
layerHeight,
|
|
||||||
nozzleDiameter,
|
|
||||||
filamentThickness,
|
|
||||||
travelSpeed
|
|
||||||
} = this._settings;
|
|
||||||
|
|
||||||
const profile = this._settings[(this.bottom ? 'bottom' : type)];
|
|
||||||
|
|
||||||
let {
|
|
||||||
speed,
|
|
||||||
flowRate
|
|
||||||
} = profile;
|
|
||||||
|
|
||||||
speed *= 60;
|
speed *= 60;
|
||||||
const z = layer * layerHeight + 0.2;
|
|
||||||
|
|
||||||
const lineLength = this._nozzlePosition.distanceTo(newNozzlePosition);
|
const lineLength = this._nozzlePosition.distanceTo(newNozzlePosition);
|
||||||
|
this._extruder += this._nozzleToFilamentRatio * lineLength * flowRate;
|
||||||
const filamentSurfaceArea = Math.pow((filamentThickness / 2), 2) * Math.PI;
|
|
||||||
this._extruder += lineLength * ((nozzleDiameter * layerHeight) / filamentSurfaceArea) * flowRate;
|
|
||||||
|
|
||||||
this._addGCode({
|
this._addGCode({
|
||||||
[MOVE]: 1,
|
[MOVE]: 1,
|
||||||
@ -123,21 +99,13 @@ export default class {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
unRetract() {
|
unRetract({ enabled, speed, minDistance }) {
|
||||||
const {
|
if (this._isRetracted && enabled) {
|
||||||
retraction: {
|
|
||||||
enabled: retractionEnabled,
|
|
||||||
minDistance: retractionMinDistance,
|
|
||||||
speed: retractionSpeed
|
|
||||||
}
|
|
||||||
} = this._settings;
|
|
||||||
|
|
||||||
if (this._isRetracted && retractionEnabled) {
|
|
||||||
this._isRetracted = false;
|
this._isRetracted = false;
|
||||||
|
|
||||||
const speed = retractionSpeed * 60;
|
speed *= 60;
|
||||||
|
|
||||||
if (this._extruder > retractionMinDistance) {
|
if (this._extruder > minDistance) {
|
||||||
this._addGCode({
|
this._addGCode({
|
||||||
[MOVE]: 0,
|
[MOVE]: 0,
|
||||||
[EXTRUDER]: this._extruder.toFixed(3),
|
[EXTRUDER]: this._extruder.toFixed(3),
|
||||||
@ -149,25 +117,16 @@ export default class {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
retract() {
|
retract({ enabled, speed, minDistance, amount }) {
|
||||||
const {
|
if (!this._isRetracted && enabled) {
|
||||||
retraction: {
|
|
||||||
amount: retractionAmount,
|
|
||||||
enabled: retractionEnabled,
|
|
||||||
minDistance: retractionMinDistance,
|
|
||||||
speed: retractionSpeed
|
|
||||||
}
|
|
||||||
} = this._settings;
|
|
||||||
|
|
||||||
if (!this._isRetracted && retractionEnabled) {
|
|
||||||
this._isRetracted = true;
|
this._isRetracted = true;
|
||||||
|
|
||||||
const speed = retractionSpeed * 60;
|
speed *= 60;
|
||||||
|
|
||||||
if (this._extruder > retractionMinDistance) {
|
if (this._extruder > minDistance) {
|
||||||
this._addGCode({
|
this._addGCode({
|
||||||
[MOVE]: 0,
|
[MOVE]: 0,
|
||||||
[EXTRUDER]: (this._extruder - retractionAmount).toFixed(3),
|
[EXTRUDER]: (this._extruder - amount).toFixed(3),
|
||||||
[SPEED]: speed.toFixed(3)
|
[SPEED]: speed.toFixed(3)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ export default class {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.parts = [];
|
this.parts = [];
|
||||||
}
|
}
|
||||||
add(shape) {
|
add(shape, closed) {
|
||||||
const part = { shape };
|
const part = { shape, closed };
|
||||||
|
|
||||||
if (shape.closed) {
|
if (closed) {
|
||||||
part.innerLines = [];
|
part.shell = [];
|
||||||
part.outerLine = new Shape([], true);
|
part.innerFill = new Shape([], false);
|
||||||
part.fill = new Shape([], false);
|
part.outerFill = new Shape([], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.parts.push(part);
|
this.parts.push(part);
|
||||||
|
@ -10,8 +10,9 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
|||||||
|
|
||||||
if (intersectionIndexes.length === 0) continue;
|
if (intersectionIndexes.length === 0) continue;
|
||||||
|
|
||||||
const closedShapes = [];
|
const fillShapes = [];
|
||||||
const openShapes = [];
|
const lineShapesOpen = [];
|
||||||
|
const lineShapesClosed = [];
|
||||||
for (let i = 0; i < intersectionIndexes.length; i ++) {
|
for (let i = 0; i < intersectionIndexes.length; i ++) {
|
||||||
let index = intersectionIndexes[i];
|
let index = intersectionIndexes[i];
|
||||||
|
|
||||||
@ -107,14 +108,17 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (openGeometry) {
|
if (openGeometry) {
|
||||||
if (!openShape) shape.push(shape[0].clone());
|
if (openShape) {
|
||||||
openShapes.push(shape);
|
lineShapesOpen.push(shape);
|
||||||
|
} else {
|
||||||
|
lineShapesClosed.push(shape);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
closedShapes.push(shape);
|
fillShapes.push(shape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layers.push({ closedShapes, openShapes });
|
layers.push({ fillShapes, lineShapesOpen, lineShapesClosed });
|
||||||
}
|
}
|
||||||
|
|
||||||
return layers;
|
return layers;
|
||||||
|
@ -17,7 +17,7 @@ export default function optimizePaths(slices, settings) {
|
|||||||
for (let i = 0; i < slice.parts.length; i ++) {
|
for (let i = 0; i < slice.parts.length; i ++) {
|
||||||
const part = slice.parts[i];
|
const part = slice.parts[i];
|
||||||
|
|
||||||
const shape = part.shape.closed ? part.outerLine : part.shape;
|
const shape = part.closed ? part.shell[0] : part.shape;
|
||||||
const bounds = shape.shapeBounds();
|
const bounds = shape.shapeBounds();
|
||||||
|
|
||||||
boundingBoxes.set(part, bounds);
|
boundingBoxes.set(part, bounds);
|
||||||
@ -47,24 +47,24 @@ export default function optimizePaths(slices, settings) {
|
|||||||
const [part] = slice.parts.splice(closestPart, 1);
|
const [part] = slice.parts.splice(closestPart, 1);
|
||||||
parts.push(part);
|
parts.push(part);
|
||||||
|
|
||||||
if (part.shape.closed) {
|
if (part.closed) {
|
||||||
if (part.outerLine.paths.length > 0) {
|
for (let i = 0; i < part.shell.length; i ++) {
|
||||||
part.outerLine = optimizeShape(part.outerLine, start);
|
const shell = part.shell[i];
|
||||||
start.copy(part.outerLine.lastPoint(true));
|
|
||||||
|
if (shell.paths.length === 0) continue;
|
||||||
|
|
||||||
|
part.shell[i] = optimizeShape(shell, start);
|
||||||
|
start.copy(part.shell[i].lastPoint(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < part.innerLines.length; i ++) {
|
if (part.outerFill.paths.length > 0) {
|
||||||
const innerLine = part.innerLines[i];
|
part.outerFill = optimizeShape(part.outerFill, start);
|
||||||
|
start.copy(part.outerFill.lastPoint(true));
|
||||||
if (innerLine.paths.length > 0) {
|
|
||||||
part.innerLines[i] = optimizeShape(innerLine, start);
|
|
||||||
start.copy(part.innerLines[i].lastPoint(true));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (part.fill.paths.length > 0) {
|
if (part.innerFill.paths.length > 0) {
|
||||||
part.fill = optimizeShape(part.fill, start);
|
part.innerFill = optimizeShape(part.innerFill, start);
|
||||||
start.copy(part.fill.lastPoint(true));
|
start.copy(part.innerFill.lastPoint(true));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
part.shape = optimizeShape(part.shape, start);
|
part.shape = optimizeShape(part.shape, start);
|
||||||
|
@ -9,13 +9,13 @@ export default function removePrecision(slices) {
|
|||||||
for (let i = 0; i < slice.parts.length; i ++) {
|
for (let i = 0; i < slice.parts.length; i ++) {
|
||||||
const part = slice.parts[i];
|
const part = slice.parts[i];
|
||||||
|
|
||||||
if (part.shape.closed) {
|
if (part.closed) {
|
||||||
part.outerLine.scaleDown(inversePrecision);
|
for (let i = 0; i < part.shell.length; i ++) {
|
||||||
for (let i = 0; i < part.innerLines.length; i ++) {
|
const innerLine = part.shell[i];
|
||||||
const innerLine = part.innerLines[i];
|
|
||||||
innerLine.scaleDown(inversePrecision);
|
innerLine.scaleDown(inversePrecision);
|
||||||
}
|
}
|
||||||
part.fill.scaleDown(inversePrecision);
|
part.innerFill.scaleDown(inversePrecision);
|
||||||
|
part.outerFill.scaleDown(inversePrecision);
|
||||||
} else {
|
} else {
|
||||||
part.shape.scaleDown(inversePrecision);
|
part.shape.scaleDown(inversePrecision);
|
||||||
}
|
}
|
||||||
|
@ -9,15 +9,18 @@ export default function shapesToSlices(shapes, settings) {
|
|||||||
const sliceLayers = [];
|
const sliceLayers = [];
|
||||||
|
|
||||||
for (let layer = 0; layer < shapes.length; layer ++) {
|
for (let layer = 0; layer < shapes.length; layer ++) {
|
||||||
let { closedShapes, openShapes } = shapes[layer];
|
let { fillShapes, lineShapesOpen, lineShapesClosed } = shapes[layer];
|
||||||
|
|
||||||
closedShapes = new Shape(closedShapes, true, true, true, true)
|
fillShapes = new Shape(fillShapes, true, true, true, true)
|
||||||
.fixOrientation()
|
.fixOrientation()
|
||||||
.simplify('pftNonZero')
|
.simplify('pftNonZero')
|
||||||
.clean(cleanDelta)
|
.clean(cleanDelta)
|
||||||
.seperateShapes();
|
.seperateShapes();
|
||||||
|
|
||||||
openShapes = new Shape(openShapes, false, true, true, true);
|
lineShapesClosed = new Shape(lineShapesClosed, true, true, true, true)
|
||||||
|
.clean(cleanDelta);
|
||||||
|
|
||||||
|
lineShapesOpen = new Shape(lineShapesOpen, false, true, true, true);
|
||||||
// .clean(cleanDelta);
|
// .clean(cleanDelta);
|
||||||
// TODO
|
// TODO
|
||||||
// Cleaning is actually wanted here but there is a bug in the clean function
|
// Cleaning is actually wanted here but there is a bug in the clean function
|
||||||
@ -25,17 +28,24 @@ export default function shapesToSlices(shapes, settings) {
|
|||||||
|
|
||||||
const slice = new Slice();
|
const slice = new Slice();
|
||||||
|
|
||||||
for (let i = 0; i < closedShapes.length; i ++) {
|
for (let i = 0; i < fillShapes.length; i ++) {
|
||||||
const closedShape = closedShapes[i];
|
const fillShape = fillShapes[i];
|
||||||
slice.add(closedShape);
|
slice.add(fillShape, true);
|
||||||
|
|
||||||
// if (openShapes.path.length > 0) {
|
// if (lineShapesClosed.paths.length > 0) {
|
||||||
// openShapes = openShapes.difference(closedShape);
|
// lineShapesClosed = lineShapesClosed.difference(closedShape);
|
||||||
|
// }
|
||||||
|
// if (lineShapesOpen.paths.length > 0) {
|
||||||
|
// lineShapesOpen = lineShapesOpen.difference(closedShape);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openShapes.paths.length > 0) {
|
if (lineShapesClosed.paths.length > 0) {
|
||||||
slice.add(openShapes);
|
slice.add(lineShapesClosed, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineShapesOpen.paths.length > 0) {
|
||||||
|
slice.add(lineShapesOpen, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
sliceLayers.push(slice);
|
sliceLayers.push(slice);
|
||||||
|
@ -1,47 +1,80 @@
|
|||||||
import GCode from './helpers/GCode.js';
|
import GCode from './helpers/GCode.js';
|
||||||
|
|
||||||
export default function slicesToGCode(slices, settings) {
|
const PROFILE_TYPES = ['support', 'innerShell', 'outerShell', 'innerInfill', 'outerInfill', 'brim'];
|
||||||
const gcode = new GCode(settings);
|
|
||||||
|
|
||||||
|
export default function slicesToGCode(slices, settings) {
|
||||||
|
const {
|
||||||
|
layerHeight,
|
||||||
|
filamentThickness,
|
||||||
|
nozzleDiameter,
|
||||||
|
travelSpeed,
|
||||||
|
retraction,
|
||||||
|
travel
|
||||||
|
} = settings;
|
||||||
|
|
||||||
|
const filamentSurfaceArea = Math.pow((filamentThickness / 2), 2) * Math.PI;
|
||||||
|
const lineSurfaceArea = nozzleDiameter * layerHeight;
|
||||||
|
const nozzleToFilamentRatio = lineSurfaceArea / filamentSurfaceArea;
|
||||||
|
|
||||||
|
const gcode = new GCode(nozzleToFilamentRatio);
|
||||||
|
|
||||||
|
const defaultProfile = {
|
||||||
|
travelProfile: travel,
|
||||||
|
retractionProfile: retraction
|
||||||
|
};
|
||||||
|
|
||||||
|
let isFirstLayer = true;
|
||||||
for (let layer = 0; layer < slices.length; layer ++) {
|
for (let layer = 0; layer < slices.length; layer ++) {
|
||||||
const slice = slices[layer];
|
const slice = slices[layer];
|
||||||
|
const z = layer * layerHeight + 0.2;
|
||||||
|
|
||||||
if (layer === 1) {
|
if (layer === 1) {
|
||||||
gcode.turnFanOn();
|
gcode.turnFanOn();
|
||||||
gcode.bottom = false;
|
isFirstLayer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const profiles = PROFILE_TYPES.reduce((profiles, profileType) => {
|
||||||
|
profiles[profileType] = {
|
||||||
|
...defaultProfile,
|
||||||
|
lineProfile: isFirstLayer ? settings.firstLayer : settings[profileType]
|
||||||
|
};
|
||||||
|
return profiles;
|
||||||
|
}, {});
|
||||||
|
|
||||||
if (typeof slice.brim !== 'undefined') {
|
if (typeof slice.brim !== 'undefined') {
|
||||||
pathToGCode(gcode, slice.brim, true, true, layer, 'brim');
|
pathToGCode(gcode, slice.brim, true, true, z, profiles.brim);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < slice.parts.length; i ++) {
|
for (let i = 0; i < slice.parts.length; i ++) {
|
||||||
const part = slice.parts[i];
|
const part = slice.parts[i];
|
||||||
|
|
||||||
if (part.shape.closed) {
|
if (part.closed) {
|
||||||
pathToGCode(gcode, part.outerLine, false, true, layer, 'outerLine');
|
for (let i = 0; i < part.shell.length; i ++) {
|
||||||
|
const shell = part.shell[i];
|
||||||
|
const isOuterShell = i === 0;
|
||||||
|
|
||||||
for (let i = 0; i < part.innerLines.length; i ++) {
|
const unRetract = isOuterShell;
|
||||||
const innerLine = part.innerLines[i];
|
const profile = isOuterShell ? profiles.outerShell : profiles.innerShell;
|
||||||
pathToGCode(gcode, innerLine, false, false, layer, 'innerLine');
|
pathToGCode(gcode, shell, false, unRetract, z, profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
pathToGCode(gcode, part.fill, true, false, layer, 'fill');
|
pathToGCode(gcode, part.outerFill, false, false, z, profiles.outerInfill);
|
||||||
|
pathToGCode(gcode, part.innerFill, true, false, z, profiles.innerInfill);
|
||||||
} else {
|
} else {
|
||||||
const retract = !(slice.parts.length === 1 && typeof slice.support === 'undefined');
|
const retract = !(slice.parts.length === 1 && typeof slice.support === 'undefined');
|
||||||
pathToGCode(gcode, part.shape, retract, retract, layer, 'outerLine');
|
pathToGCode(gcode, part.shape, retract, retract, z, profiles.outerShell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof slice.support !== 'undefined') {
|
if (typeof slice.support !== 'undefined') {
|
||||||
pathToGCode(gcode, slice.support, true, true, layer, 'support');
|
pathToGCode(gcode, slice.support, true, true, z, profiles.support);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gcode.getGCode();
|
return gcode.getGCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
function pathToGCode(gcode, shape, retract, unRetract, layer, type) {
|
function pathToGCode(gcode, shape, retract, unRetract, z, { lineProfile, travelProfile, retractionProfile }) {
|
||||||
const { closed } = shape;
|
const { closed } = shape;
|
||||||
const paths = shape.mapToLower();
|
const paths = shape.mapToLower();
|
||||||
|
|
||||||
@ -55,18 +88,18 @@ function pathToGCode(gcode, shape, retract, unRetract, layer, type) {
|
|||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
// TODO
|
// TODO
|
||||||
// moveTo should impliment combing
|
// moveTo should impliment combing
|
||||||
gcode.moveTo(point.x, point.y, layer);
|
gcode.moveTo(point.x, point.y, z, travelProfile);
|
||||||
|
|
||||||
if (unRetract) {
|
if (unRetract) {
|
||||||
gcode.unRetract();
|
gcode.unRetract(retractionProfile);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gcode.lineTo(point.x, point.y, layer, type);
|
gcode.lineTo(point.x, point.y, z, lineProfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retract) {
|
if (retract) {
|
||||||
gcode.retract();
|
gcode.retract(retractionProfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user