mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-12-23 19:43:48 +01:00
implement constants
This commit is contained in:
parent
9d17df0cf3
commit
ebbe75ef2e
2
src/constants.js
Normal file
2
src/constants.js
Normal file
@ -0,0 +1,2 @@
|
||||
export const CLEAN_DELTA = 0.01;
|
||||
export const PRECISION = 0.01;
|
105
src/gcode.js
105
src/gcode.js
@ -1,5 +1,14 @@
|
||||
import THREE from 'three.js';
|
||||
|
||||
const G_COMMAND = 'G';
|
||||
const M_COMMAND = 'M';
|
||||
const FAN_SPEED = 'S';
|
||||
const SPEED = 'F';
|
||||
const EXTRUDER = 'E';
|
||||
const POSITION_X = 'X';
|
||||
const POSITION_Y = 'Y';
|
||||
const POSITION_Z = 'Z';
|
||||
|
||||
export default class {
|
||||
constructor () {
|
||||
this.gcode = '';
|
||||
@ -23,15 +32,14 @@ export default class {
|
||||
str = action + value;
|
||||
|
||||
first = false;
|
||||
}
|
||||
else if (currentValue !== value) {
|
||||
} else if (currentValue !== value) {
|
||||
str += ` ${action}${value}`;
|
||||
|
||||
this.current[action] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this.gcode += str + '\n';
|
||||
this.gcode += `${str}\n`;
|
||||
}
|
||||
|
||||
setSettings (settings) {
|
||||
@ -43,13 +51,8 @@ export default class {
|
||||
turnFanOn (fanSpeed) {
|
||||
this.isFanOn = true;
|
||||
|
||||
var gcode = {
|
||||
'M': 106
|
||||
}
|
||||
|
||||
if (fanSpeed !== undefined) {
|
||||
gcode['S'] = fanSpeed;
|
||||
}
|
||||
const gcode = { [M_COMMAND]: 106 }
|
||||
if (fanSpeed !== undefined) gcode[FAN_SPEED] = fanSpeed;
|
||||
|
||||
this._addGCode(gcode);
|
||||
|
||||
@ -59,24 +62,24 @@ export default class {
|
||||
turnFanOff () {
|
||||
this.isFanOn = false;
|
||||
|
||||
this._addGCode({
|
||||
'M': 107
|
||||
});
|
||||
this._addGCode({ [M_COMMAND]: 107 });
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
moveTo (x, y, layer) {
|
||||
var layerHeight = this.settings.config['layerHeight'];
|
||||
var travelSpeed = this.settings.config['travelSpeed'];
|
||||
const layerHeight = this.settings.config['layerHeight'];
|
||||
const travelSpeed = this.settings.config['travelSpeed'];
|
||||
|
||||
var z = (layer + 1) * layerHeight;
|
||||
var speed = travelSpeed * 60;
|
||||
const z = (layer + 1) * layerHeight;
|
||||
const speed = travelSpeed * 60;
|
||||
|
||||
this._addGCode({
|
||||
'G': 0,
|
||||
'X': x.toFixed(3), 'Y': y.toFixed(3), 'Z': z.toFixed(3),
|
||||
'F': speed.toFixed(3)
|
||||
[G_COMMAND]: 0,
|
||||
[POSITION_X]: x.toFixed(3),
|
||||
[POSITION_Y]: y.toFixed(3),
|
||||
[POSITION_Z]: z.toFixed(3),
|
||||
[SPEED]: speed.toFixed(3)
|
||||
});
|
||||
|
||||
this._nozzlePosition.set(x, y);
|
||||
@ -85,29 +88,31 @@ export default class {
|
||||
}
|
||||
|
||||
lineTo (x, y, layer, type) {
|
||||
var newNozzlePosition = new THREE.Vector2(x, y);
|
||||
const newNozzlePosition = new THREE.Vector2(x, y);
|
||||
|
||||
var layerHeight = this.settings.config['layerHeight'];
|
||||
var nozzleDiameter = this.settings.config['nozzleDiameter'];
|
||||
var filamentThickness = this.settings.config['filamentThickness'];
|
||||
var travelSpeed = this.settings.config['travelSpeed'];
|
||||
const layerHeight = this.settings.config['layerHeight'];
|
||||
const nozzleDiameter = this.settings.config['nozzleDiameter'];
|
||||
const filamentThickness = this.settings.config['filamentThickness'];
|
||||
const travelSpeed = this.settings.config['travelSpeed'];
|
||||
|
||||
var profile = this.settings.config[(this.bottom ? 'bottom' : type)];
|
||||
const profile = this.settings.config[(this.bottom ? 'bottom' : type)];
|
||||
|
||||
var speed = profile['speed'] * 60;
|
||||
var flowRate = profile['flowRate'];
|
||||
var z = (layer + 1) * layerHeight;
|
||||
const speed = profile['speed'] * 60;
|
||||
const flowRate = profile['flowRate'];
|
||||
const z = (layer + 1) * layerHeight;
|
||||
|
||||
var lineLength = this._nozzlePosition.distanceTo(newNozzlePosition);
|
||||
const lineLength = this._nozzlePosition.distanceTo(newNozzlePosition);
|
||||
|
||||
var filamentSurfaceArea = Math.pow((filamentThickness / 2), 2) * Math.PI;
|
||||
const filamentSurfaceArea = Math.pow((filamentThickness / 2), 2) * Math.PI;
|
||||
this.extruder += lineLength * nozzleDiameter * layerHeight / filamentSurfaceArea * flowRate;
|
||||
|
||||
this._addGCode({
|
||||
'G': 1,
|
||||
'X': x.toFixed(3), 'Y': y.toFixed(3), 'Z': z.toFixed(3),
|
||||
'F': speed.toFixed(3),
|
||||
'E': this.extruder.toFixed(3)
|
||||
[G_COMMAND]: 1,
|
||||
[POSITION_X]: x.toFixed(3),
|
||||
[POSITION_Y]: y.toFixed(3),
|
||||
[POSITION_Z]: z.toFixed(3),
|
||||
[SPEED]: speed.toFixed(3),
|
||||
[EXTRUDER]: this.extruder.toFixed(3)
|
||||
});
|
||||
|
||||
this._nozzlePosition.copy(newNozzlePosition);
|
||||
@ -116,20 +121,20 @@ export default class {
|
||||
}
|
||||
|
||||
unRetract () {
|
||||
var retractionEnabled = this.settings.config['retractionEnabled'];
|
||||
var retractionMinDistance = this.settings.config['retractionMinDistance'];
|
||||
var retractionSpeed = this.settings.config['retractionSpeed'];
|
||||
const retractionEnabled = this.settings.config['retractionEnabled'];
|
||||
const retractionMinDistance = this.settings.config['retractionMinDistance'];
|
||||
const retractionSpeed = this.settings.config['retractionSpeed'];
|
||||
|
||||
if (this.isRetracted && retractionEnabled) {
|
||||
this.isRetracted = false;
|
||||
|
||||
var speed = retractionSpeed * 60;
|
||||
const speed = retractionSpeed * 60;
|
||||
|
||||
if (this.extruder > retractionMinDistance) {
|
||||
this._addGCode({
|
||||
'G': 0,
|
||||
'E': this.extruder.toFixed(3),
|
||||
'F': speed.toFixed(3)
|
||||
[G_COMMAND]: 0,
|
||||
[EXTRUDER]: this.extruder.toFixed(3),
|
||||
[SPEED]: speed.toFixed(3)
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -138,21 +143,21 @@ export default class {
|
||||
}
|
||||
|
||||
retract () {
|
||||
var retractionAmount = this.settings.config['retractionAmount'];
|
||||
var retractionEnabled = this.settings.config['retractionEnabled'];
|
||||
var retractionMinDistance = this.settings.config['retractionMinDistance'];
|
||||
var retractionSpeed = this.settings.config['retractionSpeed'];
|
||||
const retractionAmount = this.settings.config['retractionAmount'];
|
||||
const retractionEnabled = this.settings.config['retractionEnabled'];
|
||||
const retractionMinDistance = this.settings.config['retractionMinDistance'];
|
||||
const retractionSpeed = this.settings.config['retractionSpeed'];
|
||||
|
||||
if (!this.isRetracted && retractionEnabled) {
|
||||
this.isRetracted = true;
|
||||
|
||||
var speed = retractionSpeed * 60;
|
||||
const speed = retractionSpeed * 60;
|
||||
|
||||
if (this.extruder > retractionMinDistance && retractionEnabled) {
|
||||
this._addGCode({
|
||||
'G': 0,
|
||||
'E': (this.extruder - retractionAmount).toFixed(3),
|
||||
'F': speed.toFixed(3)
|
||||
[G_COMMAND]: 0,
|
||||
[EXTRUDER]: (this.extruder - retractionAmount).toFixed(3),
|
||||
[SPEED]: speed.toFixed(3)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { PRECISION } from '../constants.js'
|
||||
import getFillTemplate from './getFillTemplate.js';
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
|
||||
const scale = 100;
|
||||
|
||||
export default function generateInfills(slices, settings) {
|
||||
console.log('generating infills');
|
||||
|
||||
@ -15,9 +14,9 @@ export default function generateInfills(slices, settings) {
|
||||
infillOverlap
|
||||
} = settings.config;
|
||||
|
||||
fillGridSize *= scale;
|
||||
nozzleDiameter *= scale;
|
||||
infillOverlap *= scale;
|
||||
fillGridSize /= PRECISION;
|
||||
nozzleDiameter /= PRECISION;
|
||||
infillOverlap /= PRECISION;
|
||||
|
||||
const bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
|
||||
const topSkinCount = Math.ceil(topThickness/layerHeight);
|
||||
|
@ -1,4 +1,5 @@
|
||||
const scale = 100;
|
||||
import { PRECISION } from '../constants.js'
|
||||
|
||||
const offsetOptions = {
|
||||
jointType: 'jtSquare',
|
||||
endType: 'etClosedPolygon',
|
||||
@ -7,33 +8,32 @@ const offsetOptions = {
|
||||
};
|
||||
|
||||
export default function generateInnerLines(slices, settings) {
|
||||
console.log("generating outer lines and inner lines");
|
||||
console.log('generating outer lines and inner lines');
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
let { layerHeight, nozzleDiameter, shellThickness } = settings.config;
|
||||
nozzleDiameter *= scale;
|
||||
shellThickness *= scale;
|
||||
var nozzleRadius = nozzleDiameter / 2;
|
||||
var shells = Math.round(shellThickness / nozzleDiameter);
|
||||
nozzleDiameter /= PRECISION;
|
||||
shellThickness /= PRECISION;
|
||||
const nozzleRadius = nozzleDiameter / 2;
|
||||
const shells = Math.round(shellThickness / nozzleDiameter);
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
for (let layer = 0; layer < slices.length; layer ++) {
|
||||
const slice = slices[layer];
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
for (let i = 0; i < slice.parts.length; i ++) {
|
||||
const part = slice.parts[i];
|
||||
|
||||
if (!part.shape.closed) continue;
|
||||
|
||||
// var outerLine = part.shape.clone().scaleUp(scale).offset(-nozzleRadius);
|
||||
const outerLine = part.shape.scaleUp(scale).offset(-nozzleRadius, offsetOptions);
|
||||
const outerLine = part.shape.scaleDown(PRECISION).offset(-nozzleRadius, offsetOptions);
|
||||
|
||||
if (outerLine.paths.length > 0) {
|
||||
part.outerLine.join(outerLine);
|
||||
|
||||
for (var shell = 1; shell < shells; shell += 1) {
|
||||
var offset = shell * nozzleDiameter;
|
||||
for (let shell = 1; shell < shells; shell += 1) {
|
||||
const offset = shell * nozzleDiameter;
|
||||
|
||||
var innerLine = outerLine.offset(-offset, offsetOptions);
|
||||
const innerLine = outerLine.offset(-offset, offsetOptions);
|
||||
|
||||
if (innerLine.paths.length > 0) {
|
||||
part.innerLines.push(innerLine);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import getFillTemplate from './getFillTemplate.js';
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
|
||||
const scale = 100;
|
||||
import { PRECISION } from '../constants.js';
|
||||
|
||||
export default function generateSupport(slices, settings) {
|
||||
console.log("generating support");
|
||||
@ -16,10 +15,10 @@ export default function generateSupport(slices, settings) {
|
||||
nozzleDiameter
|
||||
} = settings.config;
|
||||
|
||||
supportGridSize *= scale;
|
||||
supportMargin *= scale;
|
||||
plateSize *= scale;
|
||||
nozzleDiameter *= scale;
|
||||
supportGridSize /= PRECISION;
|
||||
supportMargin /= PRECISION;
|
||||
plateSize /= PRECISION;
|
||||
nozzleDiameter /= PRECISION;
|
||||
var supportDistanceLayers = Math.max(Math.ceil(supportDistanceY / layerHeight), 1);
|
||||
|
||||
var supportAreas = new Shape([], true);
|
||||
|
@ -4,43 +4,39 @@ import Shape from 'Doodle3D/clipper-js';
|
||||
export default function intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings) {
|
||||
console.log("generating slices");
|
||||
|
||||
var layers = [];
|
||||
const layers = [];
|
||||
|
||||
for (var layer = 1; layer < layerIntersectionIndexes.length; layer ++) {
|
||||
var intersectionIndexes = layerIntersectionIndexes[layer];
|
||||
var intersectionPoints = layerIntersectionPoints[layer];
|
||||
for (let layer = 1; layer < layerIntersectionIndexes.length; layer ++) {
|
||||
const intersectionIndexes = layerIntersectionIndexes[layer];
|
||||
const intersectionPoints = layerIntersectionPoints[layer];
|
||||
|
||||
if (intersectionIndexes.length === 0) {
|
||||
continue;
|
||||
}
|
||||
if (intersectionIndexes.length === 0) continue;
|
||||
|
||||
var closedShapes = [];
|
||||
var openShapes = [];
|
||||
for (var i = 0; i < intersectionIndexes.length; i ++) {
|
||||
var index = intersectionIndexes[i];
|
||||
const closedShapes = [];
|
||||
const openShapes = [];
|
||||
for (let i = 0; i < intersectionIndexes.length; i ++) {
|
||||
let index = intersectionIndexes[i];
|
||||
|
||||
if (intersectionPoints[index] === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (intersectionPoints[index] === undefined) continue;
|
||||
|
||||
var firstPoints = [index];
|
||||
var isFirstPoint = true;
|
||||
var closed = false;
|
||||
const shape = [];
|
||||
|
||||
var shape = [];
|
||||
const firstPoints = [index];
|
||||
let isFirstPoint = true;
|
||||
let closed = false;
|
||||
|
||||
while (index !== -1) {
|
||||
var intersection = intersectionPoints[index];
|
||||
const intersection = intersectionPoints[index];
|
||||
// uppercase X and Y because clipper vector
|
||||
shape.push(intersection);
|
||||
|
||||
delete intersectionPoints[index];
|
||||
|
||||
var connects = lines[index].connects;
|
||||
var faceNormals = lines[index].normals;
|
||||
const connects = lines[index].connects;
|
||||
const faceNormals = lines[index].normals;
|
||||
|
||||
for (var j = 0; j < connects.length; j ++) {
|
||||
var index = connects[j];
|
||||
for (let i = 0; i < connects.length; i ++) {
|
||||
index = connects[i];
|
||||
|
||||
if (firstPoints.indexOf(index) !== -1 && shape.length > 2) {
|
||||
closed = true;
|
||||
@ -50,10 +46,10 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
||||
|
||||
// Check if index has an intersection or is already used
|
||||
if (intersectionPoints[index] !== undefined) {
|
||||
var faceNormal = faceNormals[Math.floor(j / 2)];
|
||||
const faceNormal = faceNormals[Math.floor(i / 2)];
|
||||
|
||||
var a = new THREE.Vector2(intersection.x, intersection.y);
|
||||
var b = new THREE.Vector2(intersectionPoints[index].x, intersectionPoints[index].y);
|
||||
const a = new THREE.Vector2(intersection.x, intersection.y);
|
||||
const b = new THREE.Vector2(intersectionPoints[index].x, intersectionPoints[index].y);
|
||||
|
||||
// can't calculate normal between points if distance is smaller as 0.0001
|
||||
if ((faceNormal.x === 0 && faceNormal.y === 0) || a.distanceTo(b) < 0.0001) {
|
||||
@ -63,26 +59,23 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
||||
|
||||
delete intersectionPoints[index];
|
||||
|
||||
connects = connects.concat(lines[index].connects);
|
||||
faceNormals = faceNormals.concat(lines[index].normals);
|
||||
connects.push(...lines[index].connects);
|
||||
faceNormals.push(...lines[index].normals);
|
||||
index = -1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// make sure the path goes the right direction
|
||||
// THREE.Vector2.normal is not yet implimented
|
||||
// var normal = a.sub(b).normal().normalize();
|
||||
var normal = a.sub(b);
|
||||
// const normal = a.sub(b).normal().normalize();
|
||||
const normal = a.sub(b);
|
||||
normal.set(-normal.y, normal.x).normalize();
|
||||
|
||||
if (normal.dot(faceNormal) > 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
@ -90,25 +83,24 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
||||
}
|
||||
|
||||
if (!closed) {
|
||||
var index = firstPoints[0];
|
||||
index = firstPoints[0];
|
||||
|
||||
while (index !== -1) {
|
||||
if (firstPoints.indexOf(index) === -1) {
|
||||
var intersection = intersectionPoints[index];
|
||||
const intersection = intersectionPoints[index];
|
||||
shape.unshift(intersection);
|
||||
|
||||
delete intersectionPoints[index];
|
||||
}
|
||||
|
||||
var connects = lines[index].connects;
|
||||
const connects = lines[index].connects;
|
||||
|
||||
for (var i = 0; i < connects.length; i ++) {
|
||||
var index = connects[i];
|
||||
for (let i = 0; i < connects.length; i ++) {
|
||||
index = connects[i];
|
||||
|
||||
if (intersectionPoints[index] !== undefined) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
@ -117,8 +109,7 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
||||
|
||||
if (closed) {
|
||||
closedShapes.push(shape);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
openShapes.push(shape);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import THREE from 'three.js';
|
||||
import { PRECISION } from '../constants.js';
|
||||
|
||||
const offsetOptions = {
|
||||
jointType: 'jtSquare',
|
||||
endType: 'etClosedPolygon',
|
||||
@ -9,15 +11,12 @@ const offsetOptions = {
|
||||
export default function optimizePaths(slices, settings) {
|
||||
console.log("opimize paths");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
const brimOffset = settings.config["brimOffset"] / PRECISION;
|
||||
|
||||
var brimOffset = settings.config["brimOffset"] * scale;
|
||||
const start = new THREE.Vector2(0, 0);
|
||||
|
||||
var start = new THREE.Vector2(0, 0);
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
for (let layer = 0; layer < slices.length; layer ++) {
|
||||
const slice = slices[layer];
|
||||
|
||||
if (layer === 0) {
|
||||
slice.brim = slice.getOutline().offset(brimOffset, offsetOptions);
|
||||
@ -25,24 +24,24 @@ export default function optimizePaths(slices, settings) {
|
||||
|
||||
// start = slice.optimizePaths(start);
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
for (let i = 0; i < slice.parts.length; i ++) {
|
||||
const part = slice.parts[i];
|
||||
|
||||
if (part.shape.closed) {
|
||||
part.outerLine.scaleDown(scale);
|
||||
for (var j = 0; j < part.innerLines.length; j ++) {
|
||||
var innerLine = part.innerLines[j];
|
||||
innerLine.scaleDown(scale);
|
||||
part.outerLine.scaleDown(1 / PRECISION);
|
||||
for (let i = 0; i < part.innerLines.length; i ++) {
|
||||
const innerLine = part.innerLines[i];
|
||||
innerLine.scaleDown(1 / PRECISION);
|
||||
}
|
||||
part.fill.scaleDown(scale);
|
||||
part.fill.scaleDown(1 / PRECISION);
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.support !== undefined) {
|
||||
slice.support.scaleDown(scale);
|
||||
slice.support.scaleDown(1 / PRECISION);
|
||||
}
|
||||
if (slice.brim !== undefined) {
|
||||
slice.brim.scaleDown(scale);
|
||||
slice.brim.scaleDown(1 / PRECISION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,34 @@
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
import Slice from '../slice.js';
|
||||
|
||||
import { CLEAN_DELTA } from '../constants.js';
|
||||
|
||||
export default function shapesToSlices(shapes, settings) {
|
||||
const sliceLayers = [];
|
||||
|
||||
for (var layer = 0; layer < shapes.length; layer ++) {
|
||||
var { closedShapes, openShapes } = shapes[layer];
|
||||
for (let layer = 0; layer < shapes.length; layer ++) {
|
||||
let { closedShapes, openShapes } = shapes[layer];
|
||||
|
||||
closedShapes = new Shape(closedShapes, true, true)
|
||||
.clean(0.01)
|
||||
.clean(CLEAN_DELTA)
|
||||
.fixOrientation()
|
||||
.removeOverlap()
|
||||
.seperateShapes();
|
||||
|
||||
openShapes = new Shape(openShapes, false, true)
|
||||
.clean(0.01);
|
||||
.clean(CLEAN_DELTA);
|
||||
|
||||
var slice = new Slice();
|
||||
const slice = new Slice();
|
||||
|
||||
for (var i = 0; i < closedShapes.length; i ++) {
|
||||
var closedShape = closedShapes[i];
|
||||
for (let i = 0; i < closedShapes.length; i ++) {
|
||||
const closedShape = closedShapes[i];
|
||||
slice.add(closedShape);
|
||||
|
||||
// if (openShapes.path.length > 0) {
|
||||
// openShapes = openShapes.difference(closedShape);
|
||||
// }
|
||||
}
|
||||
|
||||
if (openShapes.paths.length > 0) {
|
||||
slice.add(openShapes);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user