mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-16 11:07:57 +01:00
separate into actions into different files
This commit is contained in:
parent
ed5d5e4c42
commit
0900eda91d
50
src/sliceActions/calculateLayersIntersections.js
Normal file
50
src/sliceActions/calculateLayersIntersections.js
Normal file
@ -0,0 +1,50 @@
|
||||
import THREE from 'three.js';
|
||||
|
||||
export default function calculateLayersIntersections(lines, settings) {
|
||||
console.log('calculating layer intersections');
|
||||
|
||||
var layerHeight = settings.config["layerHeight"];
|
||||
var height = settings.config["dimensionsZ"];
|
||||
|
||||
var numLayers = Math.floor(height / layerHeight);
|
||||
|
||||
var layerIntersectionIndexes = [];
|
||||
var layerIntersectionPoints = [];
|
||||
for (var layer = 0; layer < numLayers; layer ++) {
|
||||
layerIntersectionIndexes[layer] = [];
|
||||
layerIntersectionPoints[layer] = [];
|
||||
}
|
||||
|
||||
for (var lineIndex = 0; lineIndex < lines.length; lineIndex ++) {
|
||||
var line = lines[lineIndex].line;
|
||||
|
||||
var min = Math.ceil(Math.min(line.start.y, line.end.y) / layerHeight);
|
||||
var max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight);
|
||||
|
||||
for (var layerIndex = min; layerIndex <= max; layerIndex ++) {
|
||||
if (layerIndex >= 0 && layerIndex < numLayers) {
|
||||
|
||||
layerIntersectionIndexes[layerIndex].push(lineIndex);
|
||||
|
||||
var y = layerIndex * layerHeight;
|
||||
|
||||
if (line.start.y === line.end.y) {
|
||||
var x = line.start.x;
|
||||
var z = line.start.z;
|
||||
}
|
||||
else {
|
||||
var alpha = (y - line.start.y) / (line.end.y - line.start.y);
|
||||
var x = line.end.x * alpha + line.start.x * (1 - alpha);
|
||||
var z = line.end.z * alpha + line.start.z * (1 - alpha);
|
||||
}
|
||||
|
||||
layerIntersectionPoints[layerIndex][lineIndex] = new THREE.Vector2(z, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
layerIntersectionIndexes,
|
||||
layerIntersectionPoints
|
||||
};
|
||||
}
|
49
src/sliceActions/createLines.js
Normal file
49
src/sliceActions/createLines.js
Normal file
@ -0,0 +1,49 @@
|
||||
import THREE from 'three.js';
|
||||
|
||||
export default function createLines(geometry, settings) {
|
||||
console.log('constructing unique lines from geometry');
|
||||
|
||||
var lines = [];
|
||||
var lineLookup = {};
|
||||
|
||||
var addLine = (a, b) => {
|
||||
var index = lineLookup[b + '_' + a];
|
||||
|
||||
if (index === undefined) {
|
||||
index = lines.length;
|
||||
lineLookup[a + '_' + b] = index;
|
||||
|
||||
lines.push({
|
||||
line: new THREE.Line3(geometry.vertices[a], geometry.vertices[b]),
|
||||
connects: [],
|
||||
normals: []
|
||||
});
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
for (var i = 0; i < geometry.faces.length; i ++) {
|
||||
var face = geometry.faces[i];
|
||||
if (face.normal.y !== 1 && face.normal.y !== -1) {
|
||||
var normal = new THREE.Vector2(face.normal.z, face.normal.x).normalize();
|
||||
|
||||
// check for only adding unique lines
|
||||
// returns index of said line
|
||||
var a = addLine(face.a, face.b);
|
||||
var b = addLine(face.b, face.c);
|
||||
var c = addLine(face.c, face.a);
|
||||
|
||||
// set connecting lines (based on face)
|
||||
lines[a].connects.push(b, c);
|
||||
lines[b].connects.push(c, a);
|
||||
lines[c].connects.push(a, b);
|
||||
|
||||
lines[a].normals.push(normal);
|
||||
lines[b].normals.push(normal);
|
||||
lines[c].normals.push(normal);
|
||||
}
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
82
src/sliceActions/generateInfills.js
Normal file
82
src/sliceActions/generateInfills.js
Normal file
@ -0,0 +1,82 @@
|
||||
import getFillTemplate from './getFillTemplate.js';
|
||||
import Paths from '../paths.js';
|
||||
|
||||
export default function generateInfills(slices, settings) {
|
||||
console.log("generating infills");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
|
||||
var layerHeight = settings.config["layerHeight"];
|
||||
var fillGridSize = settings.config["fillGridSize"] * scale;
|
||||
var bottomThickness = settings.config["bottomThickness"];
|
||||
var topThickness = settings.config["topThickness"];
|
||||
var nozzleDiameter = settings.config["nozzleDiameter"] * scale;
|
||||
var infillOverlap = settings.config["infillOverlap"] * scale;
|
||||
|
||||
var bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
|
||||
var topSkinCount = Math.ceil(topThickness/layerHeight);
|
||||
var nozzleRadius = nozzleDiameter / 2;
|
||||
var hightemplateSize = Math.sqrt(2 * Math.pow(nozzleDiameter, 2));
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
if (layer - bottomSkinCount >= 0 && layer + topSkinCount < slices.length) {
|
||||
var downSkin = slices[layer - bottomSkinCount].getOutline();
|
||||
var upSkin = slices[layer + topSkinCount].getOutline();
|
||||
var surroundingLayer = upSkin.intersect(downSkin);
|
||||
}
|
||||
else {
|
||||
var surroundingLayer = false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
|
||||
if (!part.intersect.closed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var outerLine = part.outerLine;
|
||||
|
||||
if (outerLine.length > 0) {
|
||||
var inset = (part.innerLines.length > 0) ? part.innerLines[part.innerLines.length - 1] : outerLine;
|
||||
|
||||
var fillArea = inset.offset(-nozzleRadius);
|
||||
var lowFillArea = false;
|
||||
if (surroundingLayer) {
|
||||
var highFillArea = fillArea.difference(surroundingLayer);
|
||||
|
||||
if (infillOverlap > 0) {
|
||||
highFillArea = highFillArea.offset(infillOverlap);
|
||||
}
|
||||
|
||||
highFillArea = highFillArea.intersect(fillArea);
|
||||
|
||||
var lowFillArea = fillArea.difference(highFillArea);
|
||||
}
|
||||
else {
|
||||
var highFillArea = fillArea;
|
||||
}
|
||||
|
||||
var fill = new Paths([], false);
|
||||
|
||||
if (lowFillArea && lowFillArea.length > 0) {
|
||||
var bounds = lowFillArea.bounds();
|
||||
var lowFillTemplate = getFillTemplate(bounds, fillGridSize, true, true);
|
||||
|
||||
part.fill.join(lowFillTemplate.intersect(lowFillArea));
|
||||
}
|
||||
|
||||
if (highFillArea.length > 0) {
|
||||
var bounds = highFillArea.bounds();
|
||||
var even = (layer % 2 === 0);
|
||||
var highFillTemplate = getFillTemplate(bounds, hightemplateSize, even, !even);
|
||||
|
||||
part.fill.join(highFillTemplate.intersect(highFillArea));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
44
src/sliceActions/generateInnerLines.js
Normal file
44
src/sliceActions/generateInnerLines.js
Normal file
@ -0,0 +1,44 @@
|
||||
export default function generateInnerLines(slices, settings) {
|
||||
console.log("generating outer lines and inner lines");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
|
||||
var layerHeight = settings.config["layerHeight"];
|
||||
var nozzleDiameter = settings.config["nozzleDiameter"] * scale;
|
||||
var shellThickness = settings.config["shellThickness"] * scale;
|
||||
var nozzleRadius = nozzleDiameter / 2;
|
||||
var shells = Math.round(shellThickness / nozzleDiameter);
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
|
||||
if (!part.intersect.closed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// var outerLine = part.intersect.clone().scaleUp(scale).offset(-nozzleRadius);
|
||||
var outerLine = part.intersect.scaleUp(scale).offset(-nozzleRadius);
|
||||
|
||||
if (outerLine.length > 0) {
|
||||
part.outerLine = outerLine;
|
||||
|
||||
for (var shell = 1; shell < shells; shell += 1) {
|
||||
var offset = shell * nozzleDiameter;
|
||||
|
||||
var innerLine = outerLine.offset(-offset);
|
||||
|
||||
if (innerLine.length > 0) {
|
||||
part.innerLines.push(innerLine);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
src/sliceActions/generateSupport.js
Normal file
71
src/sliceActions/generateSupport.js
Normal file
@ -0,0 +1,71 @@
|
||||
import getFillTemplate from './getFillTemplate.js';
|
||||
import Paths from '../paths.js';
|
||||
|
||||
export default function generateSupport(slices, settings) {
|
||||
console.log("generating support");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
|
||||
var layerHeight = settings.config["layerHeight"];
|
||||
var supportGridSize = settings.config["supportGridSize"] * scale;
|
||||
var supportAcceptanceMargin = settings.config["supportAcceptanceMargin"] * scale;
|
||||
var supportMargin = settings.config["supportMargin"] * scale;
|
||||
var plateSize = settings.config["supportPlateSize"] * scale;
|
||||
var supportDistanceY = settings.config["supportDistanceY"];
|
||||
var supportDistanceLayers = Math.max(Math.ceil(supportDistanceY / layerHeight), 1);
|
||||
var nozzleDiameter = settings.config["nozzleDiameter"] * scale;
|
||||
|
||||
var supportAreas = new Paths([], true);
|
||||
|
||||
for (var layer = slices.length - 1 - supportDistanceLayers; layer >= 0; layer --) {
|
||||
var currentSlice = slices[layer];
|
||||
|
||||
if (supportAreas.length > 0) {
|
||||
|
||||
if (layer >= supportDistanceLayers) {
|
||||
var sliceSkin = slices[layer - supportDistanceLayers].getOutline();
|
||||
sliceSkin = sliceSkin;
|
||||
|
||||
var supportAreasSlimmed = supportAreas.difference(sliceSkin.offset(supportMargin));
|
||||
if (supportAreasSlimmed.area() < 100.0) {
|
||||
supportAreas = supportAreas.difference(sliceSkin);
|
||||
}
|
||||
else {
|
||||
supportAreas = supportAreasSlimmed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var supportTemplate = getFillTemplate(supportAreas.bounds(), supportGridSize, true, true);
|
||||
var supportFill = supportTemplate.intersect(supportAreas);
|
||||
if (supportFill.length === 0) {
|
||||
currentSlice.support = supportAreas.clone();
|
||||
}
|
||||
else {
|
||||
currentSlice.support = supportFill;
|
||||
}
|
||||
}
|
||||
|
||||
var supportSkin = slices[layer + supportDistanceLayers - 1].getOutline();
|
||||
|
||||
var slice = slices[layer + supportDistanceLayers];
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var slicePart = slice.parts[i];
|
||||
|
||||
if (slicePart.intersect.closed) {
|
||||
var outerLine = slicePart.outerLine;
|
||||
}
|
||||
else {
|
||||
var outerLine = slicePart.intersect.offset(supportAcceptanceMargin);
|
||||
}
|
||||
|
||||
var overlap = supportSkin.offset(supportAcceptanceMargin).intersect(outerLine);
|
||||
var overhang = outerLine.difference(overlap);
|
||||
|
||||
if (overlap.length === 0 || overhang.length > 0) {
|
||||
supportAreas = supportAreas.join(overhang);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
src/sliceActions/getFillTemplate.js
Normal file
31
src/sliceActions/getFillTemplate.js
Normal file
@ -0,0 +1,31 @@
|
||||
import Paths from '../paths.js';
|
||||
|
||||
export default function getFillTemplate(bounds, size, even, uneven) {
|
||||
var paths = new Paths([], false);
|
||||
|
||||
var left = Math.floor(bounds.left / size) * size;
|
||||
var right = Math.ceil(bounds.right / size) * size;
|
||||
var top = Math.floor(bounds.top / size) * size;
|
||||
var bottom = Math.ceil(bounds.bottom / size) * size;
|
||||
|
||||
var width = right - left;
|
||||
|
||||
if (even) {
|
||||
for (var y = top; y <= bottom + width; y += size) {
|
||||
paths.push([
|
||||
{X: left, Y: y},
|
||||
{X: right, Y: y - width}
|
||||
]);
|
||||
}
|
||||
}
|
||||
if (uneven) {
|
||||
for (var y = top - width; y <= bottom; y += size) {
|
||||
paths.push([
|
||||
{X: left, Y: y},
|
||||
{X: right, Y: y + width}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
127
src/sliceActions/intersectionsToShapes.js
Normal file
127
src/sliceActions/intersectionsToShapes.js
Normal file
@ -0,0 +1,127 @@
|
||||
import THREE from 'three.js';
|
||||
import Paths from '../paths.js';
|
||||
|
||||
export default function intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings) {
|
||||
console.log("generating slices");
|
||||
|
||||
var shapes = [];
|
||||
|
||||
for (var layer = 1; layer < layerIntersectionIndexes.length; layer ++) {
|
||||
var intersectionIndexes = layerIntersectionIndexes[layer];
|
||||
var intersectionPoints = layerIntersectionPoints[layer];
|
||||
|
||||
if (intersectionIndexes.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var shapeParts = [];
|
||||
for (var i = 0; i < intersectionIndexes.length; i ++) {
|
||||
var index = intersectionIndexes[i];
|
||||
|
||||
if (intersectionPoints[index] === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var firstPoints = [index];
|
||||
var isFirstPoint = true;
|
||||
var closed = false;
|
||||
|
||||
var shape = [];
|
||||
|
||||
while (index !== -1) {
|
||||
var intersection = intersectionPoints[index];
|
||||
// uppercase X and Y because clipper vector
|
||||
shape.push({X: intersection.x, Y: intersection.y});
|
||||
|
||||
delete intersectionPoints[index];
|
||||
|
||||
var connects = lines[index].connects;
|
||||
var faceNormals = lines[index].normals;
|
||||
|
||||
for (var j = 0; j < connects.length; j ++) {
|
||||
var index = connects[j];
|
||||
|
||||
if (firstPoints.indexOf(index) !== -1 && shape.length > 2) {
|
||||
closed = true;
|
||||
index = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if index has an intersection or is already used
|
||||
if (intersectionPoints[index] !== undefined) {
|
||||
var faceNormal = faceNormals[Math.floor(j / 2)];
|
||||
|
||||
var a = new THREE.Vector2(intersection.x, intersection.y);
|
||||
var 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) {
|
||||
if (isFirstPoint) {
|
||||
firstPoints.push(index);
|
||||
}
|
||||
|
||||
delete intersectionPoints[index];
|
||||
|
||||
connects = connects.concat(lines[index].connects);
|
||||
faceNormals = faceNormals.concat(lines[index].normals);
|
||||
index = -1;
|
||||
}
|
||||
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);
|
||||
normal.set(-normal.y, normal.x).normalize();
|
||||
|
||||
if (normal.dot(faceNormal) > 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
isFirstPoint = false;
|
||||
}
|
||||
|
||||
if (!closed) {
|
||||
var index = firstPoints[0];
|
||||
|
||||
while (index !== -1) {
|
||||
if (firstPoints.indexOf(index) === -1) {
|
||||
var intersection = intersectionPoints[index];
|
||||
shape.unshift({X: intersection.x, Y: intersection.y});
|
||||
|
||||
delete intersectionPoints[index];
|
||||
}
|
||||
|
||||
var connects = lines[index].connects;
|
||||
|
||||
for (var i = 0; i < connects.length; i ++) {
|
||||
var index = connects[i];
|
||||
|
||||
if (intersectionPoints[index] !== undefined) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var part = new Paths([shape], closed).clean(0.01);
|
||||
if (part.length > 0) {
|
||||
shapeParts.push(part);
|
||||
}
|
||||
}
|
||||
|
||||
shapes.push(shapeParts);
|
||||
}
|
||||
|
||||
return shapes;
|
||||
}
|
42
src/sliceActions/optimizePaths.js
Normal file
42
src/sliceActions/optimizePaths.js
Normal file
@ -0,0 +1,42 @@
|
||||
import THREE from 'three.js';
|
||||
|
||||
export default function optimizePaths(slices, settings) {
|
||||
console.log("opimize paths");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
|
||||
var brimOffset = settings.config["brimOffset"] * scale;
|
||||
|
||||
var start = new THREE.Vector2(0, 0);
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
if (layer === 0) {
|
||||
slice.brim = slice.getOutline().offset(brimOffset);
|
||||
}
|
||||
|
||||
start = slice.optimizePaths(start);
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
|
||||
if (part.intersect.closed) {
|
||||
part.outerLine.scaleDown(scale);
|
||||
for (var j = 0; j < part.innerLines.length; j ++) {
|
||||
var innerLine = part.innerLines[j];
|
||||
innerLine.scaleDown(scale);
|
||||
}
|
||||
part.fill.scaleDown(scale);
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.support !== undefined) {
|
||||
slice.support.scaleDown(scale);
|
||||
}
|
||||
if (slice.brim !== undefined) {
|
||||
slice.brim.scaleDown(scale);
|
||||
}
|
||||
}
|
||||
}
|
65
src/sliceActions/shapesToSlices.js
Normal file
65
src/sliceActions/shapesToSlices.js
Normal file
@ -0,0 +1,65 @@
|
||||
import Slice from '../slice.js';
|
||||
|
||||
export default function shapesToSlices(shapes, settings) {
|
||||
var slices = [];
|
||||
|
||||
for (var layer = 0; layer < shapes.length; layer ++) {
|
||||
var shapeParts = shapes[layer];
|
||||
|
||||
var slice = new Slice();
|
||||
|
||||
var holes = [];
|
||||
var outlines = [];
|
||||
|
||||
for (var i = 0; i < shapeParts.length; i ++) {
|
||||
var shape = shapeParts[i];
|
||||
|
||||
if (!shape.closed) {
|
||||
slice.add(shape);
|
||||
}
|
||||
else if (shape.isHole()) {
|
||||
holes.push(shape);
|
||||
}
|
||||
else {
|
||||
slice.add(shape);
|
||||
outlines.push(shape);
|
||||
}
|
||||
}
|
||||
|
||||
outlines.sort((a, b) => {
|
||||
return a.boundSize() - b.boundSize();
|
||||
});
|
||||
|
||||
if (holes.length > outlines.length) {
|
||||
[holes, outlines] = [outlines, holes];
|
||||
}
|
||||
else if (holes.length === outlines.length) {
|
||||
holes.sort((a, b) => {
|
||||
return a.boundSize() - b.boundSize();
|
||||
});
|
||||
|
||||
if (holes[0].boundSize > outlines[0].boundSize()) {
|
||||
[holes, outlines] = [outlines, holes];
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < holes.length; i ++) {
|
||||
var hole = holes[i];
|
||||
|
||||
for (var j = 0; j < outlines.length; j ++) {
|
||||
var outline = outlines[j];
|
||||
|
||||
if (outline.pointCollision(hole[0][0])) {
|
||||
outline.join(hole);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slice.removeSelfIntersect();
|
||||
|
||||
slices.push(slice);
|
||||
}
|
||||
|
||||
return slices;
|
||||
}
|
73
src/sliceActions/slicesToGCode.js
Normal file
73
src/sliceActions/slicesToGCode.js
Normal file
@ -0,0 +1,73 @@
|
||||
import GCode from '../gcode.js';
|
||||
|
||||
export default function slicesToGCode(slices, settings) {
|
||||
var gcode = new GCode().setSettings(settings);
|
||||
|
||||
function pathToGCode (path, retract, unRetract, type) {
|
||||
|
||||
for (var i = 0; i < path.length; i ++) {
|
||||
var shape = path[i];
|
||||
|
||||
var length = path.closed ? (shape.length + 1) : shape.length;
|
||||
|
||||
for (var j = 0; j < length; j ++) {
|
||||
var point = shape[j % shape.length];
|
||||
|
||||
if (j === 0) {
|
||||
// TODO
|
||||
// moveTo should impliment combing
|
||||
gcode.moveTo(point.X, point.Y, layer);
|
||||
|
||||
if (unRetract) {
|
||||
gcode.unRetract();
|
||||
}
|
||||
}
|
||||
else {
|
||||
gcode.lineTo(point.X, point.Y, layer, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retract) {
|
||||
gcode.retract();
|
||||
}
|
||||
}
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
if (layer === 1) {
|
||||
gcode.turnFanOn();
|
||||
gcode.bottom = false;
|
||||
}
|
||||
|
||||
if (slice.brim !== undefined) {
|
||||
pathToGCode(slice.brim, true, true, "brim");
|
||||
}
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
|
||||
if (part.intersect.closed) {
|
||||
pathToGCode(part.outerLine, false, true, "outerLine");
|
||||
|
||||
for (var j = 0; j < part.innerLines.length; j ++) {
|
||||
var innerLine = part.innerLines[j];
|
||||
pathToGCode(innerLine, false, false, "innerLine");
|
||||
}
|
||||
|
||||
pathToGCode(part.fill, true, false, "fill");
|
||||
}
|
||||
else {
|
||||
var retract = !(slice.parts.length === 1 && slice.support === undefined);
|
||||
pathToGCode(part.intersect, retract, retract, "outerLine");
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.support !== undefined) {
|
||||
pathToGCode(slice.support, true, true, "support");
|
||||
}
|
||||
}
|
||||
|
||||
return gcode.getGCode();
|
||||
}
|
706
src/slicer.js
706
src/slicer.js
@ -1,7 +1,13 @@
|
||||
import THREE from 'three.js';
|
||||
import Paths from './paths.js';
|
||||
import Slice from './slice.js';
|
||||
import GCode from './gcode.js';
|
||||
import calculateLayersIntersections from './sliceActions/calculateLayersIntersections.js';
|
||||
import createLines from './sliceActions/createLines.js';
|
||||
import generateInfills from './sliceActions/generateInfills.js';
|
||||
import generateInnerLines from './sliceActions/generateInnerLines.js';
|
||||
import generateSupport from './sliceActions/generateSupport.js';
|
||||
import intersectionsToShapes from './sliceActions/intersectionsToShapes.js';
|
||||
import optimizePaths from './sliceActions/optimizePaths.js';
|
||||
import shapesToSlices from './sliceActions/shapesToSlices.js';
|
||||
import slicesToGCode from './sliceActions/slicesToGCode.js';
|
||||
|
||||
export default class {
|
||||
constructor () {
|
||||
@ -54,25 +60,43 @@ export default class {
|
||||
var supportEnabled = settings.config['supportEnabled'];
|
||||
|
||||
// get unique lines from geometry;
|
||||
var lines = this._createLines(settings);
|
||||
var lines = createLines(this.geometry, settings);
|
||||
this.progress.createdLines = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
var {layerIntersectionIndexes, layerIntersectionPoints} = this._calculateLayersIntersections(lines, settings);
|
||||
var {layerIntersectionIndexes, layerIntersectionPoints} = calculateLayersIntersections(lines, settings);
|
||||
this.progress.calculatedLayerIntersections = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
var shapes = this._intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings);
|
||||
var shapes = intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings);
|
||||
this.progress.sliced = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
var slices = this._shapesToSlices(shapes, settings);
|
||||
var slices = shapesToSlices(shapes, settings);
|
||||
this.progress.generatedSlices = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
generateInnerLines(slices, settings);
|
||||
this.progress.generatedInnerLines = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
generateInfills(slices, settings);
|
||||
this.progress.generatedInfills = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
this._generateInnerLines(slices, settings);
|
||||
|
||||
this._generateInfills(slices, settings);
|
||||
|
||||
if (supportEnabled) {
|
||||
this._generateSupport(slices, settings);
|
||||
generateSupport(slices, settings);
|
||||
this.progress.generatedSupport = true;
|
||||
this._updateProgress(settings);
|
||||
}
|
||||
|
||||
this._optimizePaths(slices, settings);
|
||||
|
||||
var gcode = this._slicesToGCode(slices, settings);
|
||||
optimizePaths(slices, settings);
|
||||
this.progress.optimizedPaths = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
var gcode = slicesToGCode(slices, settings);
|
||||
this.progress.generatedGCode = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
if (this.onfinish !== undefined) {
|
||||
this.onfinish(gcode);
|
||||
@ -81,658 +105,6 @@ export default class {
|
||||
return gcode;
|
||||
}
|
||||
|
||||
_createLines (settings) {
|
||||
console.log('constructing unique lines from geometry');
|
||||
|
||||
var lines = [];
|
||||
var lineLookup = {};
|
||||
|
||||
var addLine = (a, b) => {
|
||||
var index = lineLookup[b + '_' + a];
|
||||
|
||||
if (index === undefined) {
|
||||
index = lines.length;
|
||||
lineLookup[a + '_' + b] = index;
|
||||
|
||||
lines.push({
|
||||
line: new THREE.Line3(this.geometry.vertices[a], this.geometry.vertices[b]),
|
||||
connects: [],
|
||||
normals: []
|
||||
});
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.geometry.faces.length; i ++) {
|
||||
var face = this.geometry.faces[i];
|
||||
if (face.normal.y !== 1 && face.normal.y !== -1) {
|
||||
var normal = new THREE.Vector2(face.normal.z, face.normal.x).normalize();
|
||||
|
||||
// check for only adding unique lines
|
||||
// returns index of said line
|
||||
var a = addLine(face.a, face.b);
|
||||
var b = addLine(face.b, face.c);
|
||||
var c = addLine(face.c, face.a);
|
||||
|
||||
// set connecting lines (based on face)
|
||||
lines[a].connects.push(b, c);
|
||||
lines[b].connects.push(c, a);
|
||||
lines[c].connects.push(a, b);
|
||||
|
||||
lines[a].normals.push(normal);
|
||||
lines[b].normals.push(normal);
|
||||
lines[c].normals.push(normal);
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.createdLines = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
_calculateLayersIntersections (lines, settings) {
|
||||
console.log('calculating layer intersections');
|
||||
|
||||
var layerHeight = settings.config["layerHeight"];
|
||||
var height = settings.config["dimensionsZ"];
|
||||
|
||||
var numLayers = Math.floor(height / layerHeight);
|
||||
|
||||
var layerIntersectionIndexes = [];
|
||||
var layerIntersectionPoints = [];
|
||||
for (var layer = 0; layer < numLayers; layer ++) {
|
||||
layerIntersectionIndexes[layer] = [];
|
||||
layerIntersectionPoints[layer] = [];
|
||||
}
|
||||
|
||||
for (var lineIndex = 0; lineIndex < lines.length; lineIndex ++) {
|
||||
var line = lines[lineIndex].line;
|
||||
|
||||
var min = Math.ceil(Math.min(line.start.y, line.end.y) / layerHeight);
|
||||
var max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight);
|
||||
|
||||
for (var layerIndex = min; layerIndex <= max; layerIndex ++) {
|
||||
if (layerIndex >= 0 && layerIndex < numLayers) {
|
||||
|
||||
layerIntersectionIndexes[layerIndex].push(lineIndex);
|
||||
|
||||
var y = layerIndex * layerHeight;
|
||||
|
||||
if (line.start.y === line.end.y) {
|
||||
var x = line.start.x;
|
||||
var z = line.start.z;
|
||||
}
|
||||
else {
|
||||
var alpha = (y - line.start.y) / (line.end.y - line.start.y);
|
||||
var x = line.end.x * alpha + line.start.x * (1 - alpha);
|
||||
var z = line.end.z * alpha + line.start.z * (1 - alpha);
|
||||
}
|
||||
|
||||
layerIntersectionPoints[layerIndex][lineIndex] = new THREE.Vector2(z, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.calculatedLayerIntersections = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
return {
|
||||
layerIntersectionIndexes,
|
||||
layerIntersectionPoints
|
||||
};
|
||||
}
|
||||
|
||||
_intersectionsToShapes (layerIntersectionIndexes, layerIntersectionPoints, lines, settings) {
|
||||
console.log("generating slices");
|
||||
|
||||
var shapes = [];
|
||||
|
||||
for (var layer = 1; layer < layerIntersectionIndexes.length; layer ++) {
|
||||
var intersectionIndexes = layerIntersectionIndexes[layer];
|
||||
var intersectionPoints = layerIntersectionPoints[layer];
|
||||
|
||||
if (intersectionIndexes.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var shapeParts = [];
|
||||
for (var i = 0; i < intersectionIndexes.length; i ++) {
|
||||
var index = intersectionIndexes[i];
|
||||
|
||||
if (intersectionPoints[index] === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var firstPoints = [index];
|
||||
var isFirstPoint = true;
|
||||
var closed = false;
|
||||
|
||||
var shape = [];
|
||||
|
||||
while (index !== -1) {
|
||||
var intersection = intersectionPoints[index];
|
||||
// uppercase X and Y because clipper vector
|
||||
shape.push({X: intersection.x, Y: intersection.y});
|
||||
|
||||
delete intersectionPoints[index];
|
||||
|
||||
var connects = lines[index].connects;
|
||||
var faceNormals = lines[index].normals;
|
||||
|
||||
for (var j = 0; j < connects.length; j ++) {
|
||||
var index = connects[j];
|
||||
|
||||
if (firstPoints.indexOf(index) !== -1 && shape.length > 2) {
|
||||
closed = true;
|
||||
index = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if index has an intersection or is already used
|
||||
if (intersectionPoints[index] !== undefined) {
|
||||
var faceNormal = faceNormals[Math.floor(j / 2)];
|
||||
|
||||
var a = new THREE.Vector2(intersection.x, intersection.y);
|
||||
var 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) {
|
||||
if (isFirstPoint) {
|
||||
firstPoints.push(index);
|
||||
}
|
||||
|
||||
delete intersectionPoints[index];
|
||||
|
||||
connects = connects.concat(lines[index].connects);
|
||||
faceNormals = faceNormals.concat(lines[index].normals);
|
||||
index = -1;
|
||||
}
|
||||
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);
|
||||
normal.set(-normal.y, normal.x).normalize();
|
||||
|
||||
if (normal.dot(faceNormal) > 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
isFirstPoint = false;
|
||||
}
|
||||
|
||||
if (!closed) {
|
||||
var index = firstPoints[0];
|
||||
|
||||
while (index !== -1) {
|
||||
if (firstPoints.indexOf(index) === -1) {
|
||||
var intersection = intersectionPoints[index];
|
||||
shape.unshift({X: intersection.x, Y: intersection.y});
|
||||
|
||||
delete intersectionPoints[index];
|
||||
}
|
||||
|
||||
var connects = lines[index].connects;
|
||||
|
||||
for (var i = 0; i < connects.length; i ++) {
|
||||
var index = connects[i];
|
||||
|
||||
if (intersectionPoints[index] !== undefined) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var part = new Paths([shape], closed).clean(0.01);
|
||||
if (part.length > 0) {
|
||||
shapeParts.push(part);
|
||||
}
|
||||
}
|
||||
|
||||
shapes.push(shapeParts);
|
||||
}
|
||||
|
||||
this.progress.sliced = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
return shapes;
|
||||
}
|
||||
|
||||
_shapesToSlices (shapes, settings) {
|
||||
var slices = [];
|
||||
|
||||
for (var layer = 0; layer < shapes.length; layer ++) {
|
||||
var shapeParts = shapes[layer];
|
||||
|
||||
var slice = new Slice();
|
||||
|
||||
var holes = [];
|
||||
var outlines = [];
|
||||
|
||||
for (var i = 0; i < shapeParts.length; i ++) {
|
||||
var shape = shapeParts[i];
|
||||
|
||||
if (!shape.closed) {
|
||||
slice.add(shape);
|
||||
}
|
||||
else if (shape.isHole()) {
|
||||
holes.push(shape);
|
||||
}
|
||||
else {
|
||||
slice.add(shape);
|
||||
outlines.push(shape);
|
||||
}
|
||||
}
|
||||
|
||||
outlines.sort((a, b) => {
|
||||
return a.boundSize() - b.boundSize();
|
||||
});
|
||||
|
||||
console.log('test');
|
||||
|
||||
if (holes.length > outlines.length) {
|
||||
[holes, outlines] = [outlines, holes];
|
||||
}
|
||||
else if (holes.length === outlines.length) {
|
||||
holes.sort((a, b) => {
|
||||
return a.boundSize() - b.boundSize();
|
||||
});
|
||||
|
||||
if (holes[0].boundSize > outlines[0].boundSize()) {
|
||||
[holes, outlines] = [outlines, holes];
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < holes.length; i ++) {
|
||||
var hole = holes[i];
|
||||
|
||||
for (var j = 0; j < outlines.length; j ++) {
|
||||
var outline = outlines[j];
|
||||
|
||||
if (outline.pointCollision(hole[0][0])) {
|
||||
outline.join(hole);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slice.removeSelfIntersect();
|
||||
|
||||
slices.push(slice);
|
||||
}
|
||||
|
||||
this.progress.generatedSlices = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
return slices;
|
||||
}
|
||||
|
||||
_generateInnerLines (slices, settings) {
|
||||
console.log("generating outer lines and inner lines");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
|
||||
var layerHeight = settings.config["layerHeight"];
|
||||
var nozzleDiameter = settings.config["nozzleDiameter"] * scale;
|
||||
var shellThickness = settings.config["shellThickness"] * scale;
|
||||
var nozzleRadius = nozzleDiameter / 2;
|
||||
var shells = Math.round(shellThickness / nozzleDiameter);
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
|
||||
if (!part.intersect.closed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// var outerLine = part.intersect.clone().scaleUp(scale).offset(-nozzleRadius);
|
||||
var outerLine = part.intersect.scaleUp(scale).offset(-nozzleRadius);
|
||||
|
||||
if (outerLine.length > 0) {
|
||||
part.outerLine = outerLine;
|
||||
|
||||
for (var shell = 1; shell < shells; shell += 1) {
|
||||
var offset = shell * nozzleDiameter;
|
||||
|
||||
var innerLine = outerLine.offset(-offset);
|
||||
|
||||
if (innerLine.length > 0) {
|
||||
part.innerLines.push(innerLine);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.generatedInnerLines = true;
|
||||
this._updateProgress(settings);
|
||||
}
|
||||
|
||||
_generateInfills (slices, settings) {
|
||||
console.log("generating infills");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
|
||||
var layerHeight = settings.config["layerHeight"];
|
||||
var fillGridSize = settings.config["fillGridSize"] * scale;
|
||||
var bottomThickness = settings.config["bottomThickness"];
|
||||
var topThickness = settings.config["topThickness"];
|
||||
var nozzleDiameter = settings.config["nozzleDiameter"] * scale;
|
||||
var infillOverlap = settings.config["infillOverlap"] * scale;
|
||||
|
||||
var bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
|
||||
var topSkinCount = Math.ceil(topThickness/layerHeight);
|
||||
var nozzleRadius = nozzleDiameter / 2;
|
||||
var hightemplateSize = Math.sqrt(2 * Math.pow(nozzleDiameter, 2));
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
if (layer - bottomSkinCount >= 0 && layer + topSkinCount < slices.length) {
|
||||
var downSkin = slices[layer - bottomSkinCount].getOutline();
|
||||
var upSkin = slices[layer + topSkinCount].getOutline();
|
||||
var surroundingLayer = upSkin.intersect(downSkin);
|
||||
}
|
||||
else {
|
||||
var surroundingLayer = false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
|
||||
if (!part.intersect.closed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var outerLine = part.outerLine;
|
||||
|
||||
if (outerLine.length > 0) {
|
||||
var inset = (part.innerLines.length > 0) ? part.innerLines[part.innerLines.length - 1] : outerLine;
|
||||
|
||||
var fillArea = inset.offset(-nozzleRadius);
|
||||
var lowFillArea = false;
|
||||
if (surroundingLayer) {
|
||||
var highFillArea = fillArea.difference(surroundingLayer);
|
||||
|
||||
if (infillOverlap > 0) {
|
||||
highFillArea = highFillArea.offset(infillOverlap);
|
||||
}
|
||||
|
||||
highFillArea = highFillArea.intersect(fillArea);
|
||||
|
||||
var lowFillArea = fillArea.difference(highFillArea);
|
||||
}
|
||||
else {
|
||||
var highFillArea = fillArea;
|
||||
}
|
||||
|
||||
var fill = new Paths([], false);
|
||||
|
||||
if (lowFillArea && lowFillArea.length > 0) {
|
||||
var bounds = lowFillArea.bounds();
|
||||
var lowFillTemplate = this._getFillTemplate(bounds, fillGridSize, true, true);
|
||||
|
||||
part.fill.join(lowFillTemplate.intersect(lowFillArea));
|
||||
}
|
||||
|
||||
if (highFillArea.length > 0) {
|
||||
var bounds = highFillArea.bounds();
|
||||
var even = (layer % 2 === 0);
|
||||
var highFillTemplate = this._getFillTemplate(bounds, hightemplateSize, even, !even);
|
||||
|
||||
part.fill.join(highFillTemplate.intersect(highFillArea));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.generatedInfills = true;
|
||||
this._updateProgress(settings);
|
||||
}
|
||||
|
||||
_generateSupport (slices, settings) {
|
||||
console.log("generating support");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
|
||||
var layerHeight = settings.config["layerHeight"];
|
||||
var supportGridSize = settings.config["supportGridSize"] * scale;
|
||||
var supportAcceptanceMargin = settings.config["supportAcceptanceMargin"] * scale;
|
||||
var supportMargin = settings.config["supportMargin"] * scale;
|
||||
var plateSize = settings.config["supportPlateSize"] * scale;
|
||||
var supportDistanceY = settings.config["supportDistanceY"];
|
||||
var supportDistanceLayers = Math.max(Math.ceil(supportDistanceY / layerHeight), 1);
|
||||
var nozzleDiameter = settings.config["nozzleDiameter"] * scale;
|
||||
|
||||
var supportAreas = new Paths([], true);
|
||||
|
||||
for (var layer = slices.length - 1 - supportDistanceLayers; layer >= 0; layer --) {
|
||||
var currentSlice = slices[layer];
|
||||
|
||||
if (supportAreas.length > 0) {
|
||||
|
||||
if (layer >= supportDistanceLayers) {
|
||||
var sliceSkin = slices[layer - supportDistanceLayers].getOutline();
|
||||
sliceSkin = sliceSkin;
|
||||
|
||||
var supportAreasSlimmed = supportAreas.difference(sliceSkin.offset(supportMargin));
|
||||
if (supportAreasSlimmed.area() < 100.0) {
|
||||
supportAreas = supportAreas.difference(sliceSkin);
|
||||
}
|
||||
else {
|
||||
supportAreas = supportAreasSlimmed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var supportTemplate = this._getFillTemplate(supportAreas.bounds(), supportGridSize, true, true);
|
||||
var supportFill = supportTemplate.intersect(supportAreas);
|
||||
if (supportFill.length === 0) {
|
||||
currentSlice.support = supportAreas.clone();
|
||||
}
|
||||
else {
|
||||
currentSlice.support = supportFill;
|
||||
}
|
||||
}
|
||||
|
||||
var supportSkin = slices[layer + supportDistanceLayers - 1].getOutline();
|
||||
|
||||
var slice = slices[layer + supportDistanceLayers];
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var slicePart = slice.parts[i];
|
||||
|
||||
if (slicePart.intersect.closed) {
|
||||
var outerLine = slicePart.outerLine;
|
||||
}
|
||||
else {
|
||||
var outerLine = slicePart.intersect.offset(supportAcceptanceMargin);
|
||||
}
|
||||
|
||||
var overlap = supportSkin.offset(supportAcceptanceMargin).intersect(outerLine);
|
||||
var overhang = outerLine.difference(overlap);
|
||||
|
||||
if (overlap.length === 0 || overhang.length > 0) {
|
||||
supportAreas = supportAreas.join(overhang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.generatedSupport = true;
|
||||
this._updateProgress(settings);
|
||||
}
|
||||
|
||||
_optimizePaths (slices, settings) {
|
||||
console.log("opimize paths");
|
||||
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
var scale = 100;
|
||||
|
||||
var brimOffset = settings.config["brimOffset"] * scale;
|
||||
|
||||
var start = new THREE.Vector2(0, 0);
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
if (layer === 0) {
|
||||
slice.brim = slice.getOutline().offset(brimOffset);
|
||||
}
|
||||
|
||||
start = slice.optimizePaths(start);
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
|
||||
if (part.intersect.closed) {
|
||||
part.outerLine.scaleDown(scale);
|
||||
for (var j = 0; j < part.innerLines.length; j ++) {
|
||||
var innerLine = part.innerLines[j];
|
||||
innerLine.scaleDown(scale);
|
||||
}
|
||||
part.fill.scaleDown(scale);
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.support !== undefined) {
|
||||
slice.support.scaleDown(scale);
|
||||
}
|
||||
if (slice.brim !== undefined) {
|
||||
slice.brim.scaleDown(scale);
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.optimizedPaths = true;
|
||||
this._updateProgress(settings);
|
||||
}
|
||||
|
||||
_getFillTemplate (bounds, size, even, uneven) {
|
||||
var paths = new Paths([], false);
|
||||
|
||||
var left = Math.floor(bounds.left / size) * size;
|
||||
var right = Math.ceil(bounds.right / size) * size;
|
||||
var top = Math.floor(bounds.top / size) * size;
|
||||
var bottom = Math.ceil(bounds.bottom / size) * size;
|
||||
|
||||
var width = right - left;
|
||||
|
||||
if (even) {
|
||||
for (var y = top; y <= bottom + width; y += size) {
|
||||
paths.push([
|
||||
{X: left, Y: y},
|
||||
{X: right, Y: y - width}
|
||||
]);
|
||||
}
|
||||
}
|
||||
if (uneven) {
|
||||
for (var y = top - width; y <= bottom; y += size) {
|
||||
paths.push([
|
||||
{X: left, Y: y},
|
||||
{X: right, Y: y + width}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
_slicesToGCode (slices, settings) {
|
||||
var gcode = new GCode().setSettings(settings);
|
||||
|
||||
function pathToGCode (path, retract, unRetract, type) {
|
||||
|
||||
for (var i = 0; i < path.length; i ++) {
|
||||
var shape = path[i];
|
||||
|
||||
var length = path.closed ? (shape.length + 1) : shape.length;
|
||||
|
||||
for (var j = 0; j < length; j ++) {
|
||||
var point = shape[j % shape.length];
|
||||
|
||||
if (j === 0) {
|
||||
// TODO
|
||||
// moveTo should impliment combing
|
||||
gcode.moveTo(point.X, point.Y, layer);
|
||||
|
||||
if (unRetract) {
|
||||
gcode.unRetract();
|
||||
}
|
||||
}
|
||||
else {
|
||||
gcode.lineTo(point.X, point.Y, layer, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retract) {
|
||||
gcode.retract();
|
||||
}
|
||||
}
|
||||
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
if (layer === 1) {
|
||||
gcode.turnFanOn();
|
||||
gcode.bottom = false;
|
||||
}
|
||||
|
||||
if (slice.brim !== undefined) {
|
||||
pathToGCode(slice.brim, true, true, "brim");
|
||||
}
|
||||
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var part = slice.parts[i];
|
||||
|
||||
if (part.intersect.closed) {
|
||||
pathToGCode(part.outerLine, false, true, "outerLine");
|
||||
|
||||
for (var j = 0; j < part.innerLines.length; j ++) {
|
||||
var innerLine = part.innerLines[j];
|
||||
pathToGCode(innerLine, false, false, "innerLine");
|
||||
}
|
||||
|
||||
pathToGCode(part.fill, true, false, "fill");
|
||||
}
|
||||
else {
|
||||
var retract = !(slice.parts.length === 1 && slice.support === undefined);
|
||||
pathToGCode(part.intersect, retract, retract, "outerLine");
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.support !== undefined) {
|
||||
pathToGCode(slice.support, true, true, "support");
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.generatedGCode = true;
|
||||
this._updateProgress(settings);
|
||||
|
||||
return gcode.getGCode();
|
||||
}
|
||||
|
||||
_updateProgress (settings) {
|
||||
if (this.onprogress !== undefined) {
|
||||
var supportEnabled = settings.config["supportEnabled"];
|
||||
|
Loading…
Reference in New Issue
Block a user