Merge branch 'develop'

This commit is contained in:
casperlamboo 2017-08-25 15:36:52 +02:00
commit 24a100fbb1
14 changed files with 331 additions and 51 deletions

View File

@ -0,0 +1,80 @@
import Shape from 'clipper-js';
import comb from '../src/sliceActions/helpers/comb.js';
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width = 720;
canvas.height = 480;
const context = canvas.getContext('2d');
const outline = new Shape([[
{ x: 100, y: 100 },
{ x: 400, y: 100 },
{ x: 400, y: 150 },
{ x: 200, y: 150 },
{ x: 200, y: 200 },
{ x: 400, y: 200 },
{ x: 400, y: 250 },
{ x: 200, y: 250 },
{ x: 200, y: 300 },
{ x: 400, y: 300 },
{ x: 400, y: 400 },
{ x: 100, y: 400 }
], [
{ x: 130, y: 310 },
{ x: 130, y: 370 },
{ x: 360, y: 370 },
{ x: 360, y: 360 },
{ x: 150, y: 360 },
{ x: 150, y: 350 },
{ x: 360, y: 350 },
{ x: 360, y: 340 },
{ x: 150, y: 340 },
{ x: 150, y: 330 },
{ x: 360, y: 330 },
{ x: 360, y: 310 }
]], true, true, false);
const start = { x: 380, y: 120 };
const end = { x: 200, y: 380 };
let combPath = comb(outline, start, end);
canvas.onmousemove = (event) => {
start.x = event.x;
start.y = event.y;
combPath = comb(outline, start, end);
draw();
};
draw();
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.strokeStyle = 'black';
for (const path of outline.mapToLower()) {
context.beginPath();
for (const point of path) {
context.lineTo(point.x, point.y);
}
context.closePath();
context.stroke();
}
context.strokeStyle = 'red';
context.beginPath();
for (const point of combPath) {
context.lineTo(point.x, point.y);
}
context.stroke();
context.beginPath();
context.arc(start.x, start.y, 3, 0, Math.PI * 2.0, false);
context.stroke();
context.beginPath();
context.arc(end.x, end.y, 3, 0, Math.PI * 2.0, false);
context.stroke();
}

View File

@ -1,5 +1,7 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { defaultSettings, sliceGeometry } from 'doodle3d-slicer'; import { defaultSettings, sliceGeometry } from 'doodle3d-slicer';
import fileURL from '!url-loader!./models/combingtest.json';
import fileSaver from 'file-saver';
const settings = { const settings = {
...defaultSettings.base, ...defaultSettings.base,
@ -8,14 +10,20 @@ const settings = {
...defaultSettings.quality.high ...defaultSettings.quality.high
}; };
const geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone(); const jsonLoader = new THREE.JSONLoader();
geometry.mergeVertices(); jsonLoader.load(fileURL, geometry => {
geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI / -2));
geometry.applyMatrix(new THREE.Matrix4().setPosition(new THREE.Vector3(50, -0.0, 50)));
const onProgress = ({ progress: { done, total, action } }) => { const onProgress = ({ 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>`);
}; };
sliceGeometry(settings, geometry, null, false, onProgress).then(gcode => { const { filament, duration, gcode } = sliceGeometry(settings, geometry, null, true, onProgress);
document.body.innerHTML = gcode.replace(/(?:\r\n|\r|\n)/g, '<br />'); // console.log('filament: ', filament);
// console.log('duration: ', duration);
// document.body.innerHTML = gcode.replace(/(?:\r\n|\r|\n)/g, '<br />');
const file = new File([gcode], 'gcode.gcode', { type: 'text/plain' });
fileSaver.saveAs(file);
}); });

View File

@ -0,0 +1 @@
{"vertices":[47.12482452392578,42.35624313354492,-2.593571992041396e-15,-7.293127536773682,29.7335205078125,-1.820653115308456e-15,-4.207573413848877,-19.915847778320312,1.219494014914264e-15,54.97896194458008,-14.586255073547363,8.931505683412107e-16,53.85694122314453,-42.07573699951172,2.576395944332666e-15,-35.624122619628906,-25.245441436767578,1.5458375198830296e-15,-38.99018096923828,51.6129035949707,-3.1603789970181283e-15,47.12482452392578,61.71107864379883,-3.7787139115382e-15,47.12482452392578,42.35624313354492,19.999999999999996,-7.293127536773682,29.7335205078125,19.999999999999996,-4.207573413848877,-19.915847778320312,20,54.97896194458008,-14.586255073547362,20,53.85694122314453,-42.07573699951172,20.000000000000004,-35.624122619628906,-25.245441436767578,20,-38.99018096923828,51.6129035949707,19.999999999999996,47.12482452392578,61.71107864379883,19.999999999999996],"normals":[0,-6.123234262925839e-17,-1,0,6.123234262925839e-17,1,0.22595957126202507,-0.9741366804278966,5.964867098368936e-17,0.22595959003447755,-0.9741366760734609,5.964867071705706e-17,0.9980744575480833,0.062027229424660574,-3.798072564474434e-18,0.9980744575147102,0.06202722996166134,-3.798072597356249e-18,-0.08968451372047671,0.995970224453885,-6.098559003229967e-17,-0.0896845139633491,0.9959702244320148,-6.098559003096051e-17,0.9991680515439634,-0.04078240765133586,2.4972023585526864e-18,0.9991680513997995,-0.040782411183346925,2.4972025748259983e-18,-0.18484654771165182,-0.9827673955718536,6.017714989051966e-17,-0.1848465343760269,-0.9827673980801217,6.017715004410679e-17,-0.9990423495327988,-0.04375367230285246,2.679139853736555e-18,-0.9990423494957035,-0.04375367314986121,2.6791399056008846e-18,-0.11646581097902166,0.993194701391927,-6.081563825319445e-17,-0.11646581460851489,0.9931947009663187,-6.081563822713346e-17,1,0,0],"faces":[50,7,0,1,0,0,0,0,0,50,2,3,4,0,0,0,0,0,50,6,7,1,0,0,0,0,0,50,2,4,5,0,0,0,0,0,50,5,6,1,0,0,0,0,0,50,1,2,5,0,0,0,0,0,50,13,10,9,0,1,1,1,1,50,9,14,13,0,1,1,1,1,50,13,12,10,0,1,1,1,1,50,9,15,14,0,1,1,1,1,50,12,11,10,0,1,1,1,1,50,9,8,15,0,1,1,1,1,50,0,8,1,0,2,3,3,3,50,8,9,1,0,2,3,3,3,50,1,9,2,0,4,5,5,5,50,9,10,2,0,4,5,5,5,50,2,10,3,0,6,7,7,7,50,10,11,3,0,6,7,7,7,50,3,11,4,0,8,9,9,9,50,11,12,4,0,8,9,9,9,50,4,12,5,0,10,11,11,11,50,12,13,5,0,10,11,11,11,50,5,13,6,0,12,13,13,13,50,13,14,6,0,12,13,13,13,50,6,14,7,0,14,15,15,15,50,14,15,7,0,14,15,15,15,50,7,15,0,0,16,16,16,16,50,15,8,0,0,16,16,16,16]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -886,8 +886,7 @@
"big.js": { "big.js": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz",
"integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=", "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg="
"dev": true
}, },
"binary-extensions": { "binary-extensions": {
"version": "1.8.0", "version": "1.8.0",
@ -1589,8 +1588,7 @@
"emojis-list": { "emojis-list": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
"dev": true
}, },
"encodeurl": { "encodeurl": {
"version": "1.0.1", "version": "1.0.1",
@ -1897,6 +1895,11 @@
"websocket-driver": "0.6.5" "websocket-driver": "0.6.5"
} }
}, },
"file-saver": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.3.tgz",
"integrity": "sha1-zdTETTqiZOrC9o7BZbx5HDSvEjI="
},
"filename-regex": { "filename-regex": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
@ -3508,8 +3511,7 @@
"json5": { "json5": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
"dev": true
}, },
"jsonify": { "jsonify": {
"version": "0.0.0", "version": "0.0.0",
@ -3564,7 +3566,6 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
"dev": true,
"requires": { "requires": {
"big.js": "3.1.3", "big.js": "3.1.3",
"emojis-list": "2.1.0", "emojis-list": "2.1.0",
@ -3721,8 +3722,7 @@
"mime": { "mime": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
"integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM="
"dev": true
}, },
"mime-db": { "mime-db": {
"version": "1.27.0", "version": "1.27.0",
@ -5065,6 +5065,15 @@
} }
} }
}, },
"url-loader": {
"version": "0.5.9",
"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.5.9.tgz",
"integrity": "sha512-B7QYFyvv+fOBqBVeefsxv6koWWtjmHaMFT6KZWti4KRw8YUD/hOU+3AECvXuzyVawIBx3z7zQRejXCDSO5kk1Q==",
"requires": {
"loader-utils": "1.1.0",
"mime": "1.3.4"
}
},
"url-parse": { "url-parse": {
"version": "1.1.9", "version": "1.1.9",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz",

View File

@ -11,7 +11,9 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"babel-polyfill": "^6.23.0", "babel-polyfill": "^6.23.0",
"three": "^0.83.0" "file-saver": "^1.3.3",
"three": "^0.83.0",
"url-loader": "^0.5.9"
}, },
"devDependencies": { "devDependencies": {
"babel-core": "^6.25.0", "babel-core": "^6.25.0",

View File

@ -8,6 +8,7 @@ filamentThickness: 2.85
temperature: 210 temperature: 210
bedTemperature: 70 bedTemperature: 70
layerHeight: 0.15 layerHeight: 0.15
combing: true
thickness: thickness:
top: 1.2 top: 1.2
bottom: 1.2 bottom: 1.2

View File

@ -1,4 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { PRECISION } from '../../constants.js';
const MOVE = 'G'; const MOVE = 'G';
const M_COMMAND = 'M'; const M_COMMAND = 'M';
@ -17,6 +18,7 @@ export default class {
this._currentValues = {}; this._currentValues = {};
this._nozzlePosition = new THREE.Vector2(0, 0); this._nozzlePosition = new THREE.Vector2(0, 0);
this._extruder = 0.0; this._extruder = 0.0;
this._duration = 0.0;
this._isRetracted = false; this._isRetracted = false;
this._isFanOn = false; this._isFanOn = false;
} }
@ -62,35 +64,37 @@ export default class {
} }
moveTo(x, y, z, { speed }) { moveTo(x, y, z, { speed }) {
speed *= 60; const newNozzlePosition = new THREE.Vector2(x, y).multiplyScalar(PRECISION);
const lineLength = this._nozzlePosition.distanceTo(newNozzlePosition);
this._duration += lineLength / speed;
this._addGCode({ this._addGCode({
[MOVE]: 0, [MOVE]: 0,
[POSITION_X]: x.toFixed(3), [POSITION_X]: newNozzlePosition.x.toFixed(3),
[POSITION_Y]: y.toFixed(3), [POSITION_Y]: newNozzlePosition.y.toFixed(3),
[POSITION_Z]: z.toFixed(3), [POSITION_Z]: z.toFixed(3),
[SPEED]: speed.toFixed(3) [SPEED]: (speed * 60).toFixed(3)
}); });
this._nozzlePosition.set(x, y); this._nozzlePosition.copy(newNozzlePosition);
return this; return this;
} }
lineTo(x, y, z, { speed, flowRate }) { lineTo(x, y, z, { speed, flowRate }) {
const newNozzlePosition = new THREE.Vector2(x, y); const newNozzlePosition = new THREE.Vector2(x, y).multiplyScalar(PRECISION);
speed *= 60;
const lineLength = this._nozzlePosition.distanceTo(newNozzlePosition); const lineLength = this._nozzlePosition.distanceTo(newNozzlePosition);
this._extruder += this._nozzleToFilamentRatio * lineLength * flowRate; this._extruder += this._nozzleToFilamentRatio * lineLength * flowRate;
this._duration += lineLength / speed;
this._addGCode({ this._addGCode({
[MOVE]: 1, [MOVE]: 1,
[POSITION_X]: x.toFixed(3), [POSITION_X]: newNozzlePosition.x.toFixed(3),
[POSITION_Y]: y.toFixed(3), [POSITION_Y]: newNozzlePosition.y.toFixed(3),
[POSITION_Z]: z.toFixed(3), [POSITION_Z]: z.toFixed(3),
[SPEED]: speed.toFixed(3), [SPEED]: (speed * 60).toFixed(3),
[EXTRUDER]: this._extruder.toFixed(3) [EXTRUDER]: this._extruder.toFixed(3)
}); });
@ -99,17 +103,17 @@ export default class {
return this; return this;
} }
unRetract({ enabled, speed, minDistance }) { unRetract({ enabled, speed, minDistance, amount }) {
if (this._isRetracted && enabled) { if (this._isRetracted && enabled) {
this._isRetracted = false; this._isRetracted = false;
speed *= 60;
if (this._extruder > minDistance) { if (this._extruder > minDistance) {
this._duration += amount / speed;
this._addGCode({ this._addGCode({
[MOVE]: 0, [MOVE]: 0,
[EXTRUDER]: this._extruder.toFixed(3), [EXTRUDER]: this._extruder.toFixed(3),
[SPEED]: speed.toFixed(3) [SPEED]: (speed * 60).toFixed(3)
}); });
} }
} }
@ -121,13 +125,13 @@ export default class {
if (!this._isRetracted && enabled) { if (!this._isRetracted && enabled) {
this._isRetracted = true; this._isRetracted = true;
speed *= 60;
if (this._extruder > minDistance) { if (this._extruder > minDistance) {
this._duration += amount / speed;
this._addGCode({ this._addGCode({
[MOVE]: 0, [MOVE]: 0,
[EXTRUDER]: (this._extruder - amount).toFixed(3), [EXTRUDER]: (this._extruder - amount).toFixed(3),
[SPEED]: speed.toFixed(3) [SPEED]: (speed * 60).toFixed(3)
}); });
} }
} }
@ -136,6 +140,10 @@ export default class {
} }
getGCode() { getGCode() {
return this._gcode; return {
gcode: this._gcode,
duration: this._duration,
filament: this._extruder
};
} }
} }

View File

@ -0,0 +1,27 @@
export const subtract = (a, b) => ({
x: a.x - b.x,
y: a.y - b.y
});
export const add = (a, b) => ({
x: a.x + b.x,
y: a.y + b.y
});
export const scale = (a, factor) => ({
x: a.x * factor,
y: a.y * factor
});
export const normal = (a) => ({
x: -a.y,
y: a.x
});
export const dot = (a, b) => a.x * b.x + a.y * b.y;
export const length = (a) => Math.sqrt(a.x * a.x + a.y * a.y);
export const distanceTo = (a, b) => length(subtract(a, b));
export const normalize = (a) => {
const l = length(a);
return {
x: a.x / l,
y: a.y / l
};
}

View File

@ -0,0 +1,131 @@
import Shape from 'clipper-js';
import { subtract, add, scale, normalize, dot, length, distanceTo } from './VectorUtils.js';
import { PRECISION } from '../../constants.js';
const TOLERANCE = 5 / PRECISION;
export default function comb(outline, start, end) {
if (distanceTo(start, end) < TOLERANCE) {
return [start, end];
}
let combPath = new Shape([[start, end]], false, true, false);
for (let i = 0; i < outline.paths.length; i ++) {
let outlinePart = new Shape([outline.paths[i]], true, false, false, true);
let snappedCombPaths = outlinePart.orientation(0) ? combPath.intersect(outlinePart) : combPath.difference(outlinePart);
snappedCombPaths = snappedCombPaths.mapToLower();
outlinePart = outlinePart.mapToLower()[0];
if (distanceTo(start, outlinePart[outlinePart.length - 1]) < distanceTo(start, outlinePart[0])) {
outlinePart = outlinePart.reverse();
}
const distanceMap = new WeakMap();
for (let i = 0; i < snappedCombPaths.length; i ++) {
const snappedCombPath = snappedCombPaths[i];
const distanceStart = distanceTo(start, snappedCombPath[0]);
const distanceEnd = distanceTo(start, snappedCombPath[snappedCombPath.length - 1]);
if (distanceStart < distanceEnd) {
distanceMap.set(snappedCombPath, distanceStart);
} else {
snappedCombPath.reverse();
distanceMap.set(snappedCombPath, distanceEnd);
}
}
snappedCombPaths.sort((a, b) => distanceMap.get(a) - distanceMap.get(b));
const firstPath = snappedCombPaths[0];
const lastPath = snappedCombPaths[snappedCombPaths.length - 1];
if (snappedCombPaths.length === 0) {
snappedCombPaths.push([start], [end]);
} else if (distanceTo(firstPath[0], start) > 1.0) {
snappedCombPaths.unshift([start]);
} else if (distanceTo(lastPath[lastPath.length - 1], end) > 1.0) {
snappedCombPaths.push([end]);
}
if (snappedCombPaths.length === 1) {
continue;
}
const startPath = snappedCombPaths[0];
const startPoint = startPath[startPath.length - 1];
const endPath = snappedCombPaths[snappedCombPaths.length - 1];
const endPoint = endPath[0];
const lineIndexStart = findClosestLineOnPath(outlinePart, startPoint);
const lineIndexEnd = findClosestLineOnPath(outlinePart, endPoint);
const path = [];
if (lineIndexEnd === lineIndexStart) {
continue;
} else if (lineIndexEnd > lineIndexStart) {
if (lineIndexStart + outlinePart.length - lineIndexEnd < lineIndexEnd - lineIndexStart) {
for (let i = lineIndexStart + outlinePart.length; i > lineIndexEnd; i --) {
path.push(outlinePart[i % outlinePart.length]);
}
} else {
for (let i = lineIndexStart; i < lineIndexEnd; i ++) {
path.push(outlinePart[i + 1]);
}
}
} else {
if (lineIndexEnd + outlinePart.length - lineIndexStart < lineIndexStart - lineIndexEnd) {
for (let i = lineIndexStart; i < lineIndexEnd + outlinePart.length; i ++) {
path.push(outlinePart[(i + 1) % outlinePart.length]);
}
} else {
for (let i = lineIndexStart; i > lineIndexEnd; i --) {
path.push(outlinePart[i]);
}
}
}
combPath = new Shape([[...startPath, ...path, ...endPath]], false, true, false, true);
}
return combPath.mapToLower()[0];
}
function findClosestLineOnPath(path, point) {
let distance = Infinity;
let lineIndex;
for (let i = 0; i < path.length; i ++) {
const pointA = path[i];
const pointB = path[(i + 1) % path.length];
const tempClosestPoint = findClosestPointOnLine(pointA, pointB, point);
const tempDistance = distanceTo(tempClosestPoint, point);
if (tempDistance < distance) {
distance = tempDistance;
lineIndex = i;
}
}
return lineIndex;
}
function findClosestPointOnLine(a, b, c) {
const b_ = subtract(b, a);
const c_ = subtract(c, a);
const lambda = dot(normalize(b_), c_) / length(b_);
if (lambda >= 1) {
return b;
} else if (lambda > 0) {
return add(a, scale(b_, lambda));
} else {
return a;
}
}

View File

@ -11,7 +11,7 @@ import shapesToSlices from './shapesToSlices.js';
import slicesToGCode from './slicesToGCode.js'; import slicesToGCode from './slicesToGCode.js';
import detectOpenClosed from './detectOpenClosed.js'; import detectOpenClosed from './detectOpenClosed.js';
import applyPrecision from './applyPrecision.js'; import applyPrecision from './applyPrecision.js';
import removePrecision from './removePrecision.js'; // import removePrecision from './removePrecision.js';
export default function(settings, geometry, onProgress) { export default function(settings, geometry, onProgress) {
const totalStages = 12; const totalStages = 12;
@ -65,7 +65,7 @@ export default function(settings, geometry, onProgress) {
updateProgress('Optimizing paths'); updateProgress('Optimizing paths');
optimizePaths(slices, settings); optimizePaths(slices, settings);
removePrecision(slices); // removePrecision(slices);
updateProgress('Constructing gcode'); updateProgress('Constructing gcode');
const gcode = slicesToGCode(slices, settings); const gcode = slicesToGCode(slices, settings);

View File

@ -1,4 +1,6 @@
import GCode from './helpers/GCode.js'; import GCode from './helpers/GCode.js';
import comb from './helpers/comb.js';
import { PRECISION } from '../constants.js';
const PROFILE_TYPES = ['support', 'innerShell', 'outerShell', 'innerInfill', 'outerInfill', 'brim']; const PROFILE_TYPES = ['support', 'innerShell', 'outerShell', 'innerInfill', 'outerInfill', 'brim'];
@ -9,7 +11,8 @@ export default function slicesToGCode(slices, settings) {
nozzleDiameter, nozzleDiameter,
travelSpeed, travelSpeed,
retraction, retraction,
travel travel,
combing
} = settings; } = settings;
const filamentSurfaceArea = Math.pow((filamentThickness / 2), 2) * Math.PI; const filamentSurfaceArea = Math.pow((filamentThickness / 2), 2) * Math.PI;
@ -42,11 +45,12 @@ export default function slicesToGCode(slices, settings) {
}, {}); }, {});
if (typeof slice.brim !== 'undefined') { if (typeof slice.brim !== 'undefined') {
pathToGCode(gcode, slice.brim, true, true, z, profiles.brim); pathToGCode(null, false, 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];
const outline = part.shell[0];
if (part.closed) { if (part.closed) {
for (let i = 0; i < part.shell.length; i ++) { for (let i = 0; i < part.shell.length; i ++) {
@ -55,26 +59,26 @@ export default function slicesToGCode(slices, settings) {
const unRetract = isOuterShell; const unRetract = isOuterShell;
const profile = isOuterShell ? profiles.outerShell : profiles.innerShell; const profile = isOuterShell ? profiles.outerShell : profiles.innerShell;
pathToGCode(gcode, shell, false, unRetract, z, profile); pathToGCode(outline, combing && true, gcode, shell, false, unRetract, z, profile);
} }
pathToGCode(gcode, part.outerFill, false, false, z, profiles.outerInfill); pathToGCode(outline, combing && true, gcode, part.outerFill, false, false, z, profiles.outerInfill);
pathToGCode(gcode, part.innerFill, true, false, z, profiles.innerInfill); pathToGCode(outline, combing && true, 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, z, profiles.outerShell); pathToGCode(null, false, gcode, part.shape, retract, retract, z, profiles.outerShell);
} }
} }
if (typeof slice.support !== 'undefined') { if (typeof slice.support !== 'undefined') {
pathToGCode(gcode, slice.support, true, true, z, profiles.support); pathToGCode(null, false, gcode, slice.support, true, true, z, profiles.support);
} }
} }
return gcode.getGCode(); return gcode.getGCode();
} }
function pathToGCode(gcode, shape, retract, unRetract, z, { lineProfile, travelProfile, retractionProfile }) { function pathToGCode(outline, combing, gcode, shape, retract, unRetract, z, { lineProfile, travelProfile, retractionProfile }) {
const { closed } = shape; const { closed } = shape;
const paths = shape.mapToLower(); const paths = shape.mapToLower();
@ -86,9 +90,15 @@ function pathToGCode(gcode, shape, retract, unRetract, z, { lineProfile, travelP
const point = line[i % line.length]; const point = line[i % line.length];
if (i === 0) { if (i === 0) {
// TODO if (combing) {
// moveTo should impliment combing const combPath = comb(outline, gcode._nozzlePosition.divideScalar(PRECISION), point);
gcode.moveTo(point.x, point.y, z, travelProfile); for (let i = 0; i < combPath.length; i ++) {
const combPoint = combPath[i];
gcode.moveTo(combPoint.x, combPoint.y, z, travelProfile);
}
} else {
gcode.moveTo(point.x, point.y, z, travelProfile);
}
if (unRetract) { if (unRetract) {
gcode.unRetract(retractionProfile); gcode.unRetract(retractionProfile);