This commit is contained in:
casperlamboo 2016-04-21 22:14:22 +02:00
parent 2b10f388f7
commit 4edb1985c8
11 changed files with 121 additions and 164 deletions

View File

@ -16,81 +16,77 @@ System.config({
}, },
map: { map: {
"babel": "npm:babel-core@5.8.21", "Doodle3D/clipper-js": "github:Doodle3D/clipper-js@0.0.2",
"babel-runtime": "npm:babel-runtime@5.8.20", "babel": "npm:babel-core@5.8.38",
"babel-runtime": "npm:babel-runtime@5.8.38",
"casperlamboo/EventDispatcher": "github:casperlamboo/EventDispatcher@master", "casperlamboo/EventDispatcher": "github:casperlamboo/EventDispatcher@master",
"clipper-lib": "npm:clipper-lib@1.0.0", "clipper-lib": "npm:clipper-lib@1.0.0",
"core-js": "npm:core-js@0.9.18", "core-js": "npm:core-js@0.9.18",
"json": "github:systemjs/plugin-json@0.1.0", "json": "github:systemjs/plugin-json@0.1.0",
"nodeca/js-yaml": "github:nodeca/js-yaml@3.3.1", "nodeca/js-yaml": "github:nodeca/js-yaml@3.5.5",
"read-yaml": "npm:read-yaml@1.0.0", "read-yaml": "npm:read-yaml@1.0.0",
"systemjs/plugin-json": "github:systemjs/plugin-json@0.1.0", "systemjs/plugin-json": "github:systemjs/plugin-json@0.1.0",
"three.js": "github:mrdoob/three.js@r72", "three.js": "github:mrdoob/three.js@r72",
"github:Doodle3D/clipper-js@0.0.2": {
"clipper-lib": "npm:clipper-lib@1.0.0"
},
"github:jspm/nodelibs-assert@0.1.0": { "github:jspm/nodelibs-assert@0.1.0": {
"assert": "npm:assert@1.3.0" "assert": "npm:assert@1.3.0"
}, },
"github:jspm/nodelibs-path@0.1.0": { "github:jspm/nodelibs-path@0.1.0": {
"path-browserify": "npm:path-browserify@0.0.0" "path-browserify": "npm:path-browserify@0.0.0"
}, },
"github:jspm/nodelibs-process@0.1.1": { "github:jspm/nodelibs-process@0.1.2": {
"process": "npm:process@0.10.1" "process": "npm:process@0.11.2"
}, },
"github:jspm/nodelibs-util@0.1.0": { "github:jspm/nodelibs-util@0.1.0": {
"util": "npm:util@0.10.3" "util": "npm:util@0.10.3"
}, },
"npm:argparse@1.0.2": { "npm:argparse@1.0.7": {
"assert": "github:jspm/nodelibs-assert@0.1.0",
"fs": "github:jspm/nodelibs-fs@0.1.2", "fs": "github:jspm/nodelibs-fs@0.1.2",
"lodash": "npm:lodash@3.10.1",
"path": "github:jspm/nodelibs-path@0.1.0", "path": "github:jspm/nodelibs-path@0.1.0",
"process": "github:jspm/nodelibs-process@0.1.1", "process": "github:jspm/nodelibs-process@0.1.2",
"sprintf-js": "npm:sprintf-js@1.0.3", "sprintf-js": "npm:sprintf-js@1.0.3",
"util": "github:jspm/nodelibs-util@0.1.0" "util": "github:jspm/nodelibs-util@0.1.0"
}, },
"npm:assert@1.3.0": { "npm:assert@1.3.0": {
"util": "npm:util@0.10.3" "util": "npm:util@0.10.3"
}, },
"npm:babel-runtime@5.8.20": { "npm:babel-runtime@5.8.38": {
"process": "github:jspm/nodelibs-process@0.1.1" "process": "github:jspm/nodelibs-process@0.1.2"
}, },
"npm:clipper-lib@1.0.0": { "npm:clipper-lib@1.0.0": {
"process": "github:jspm/nodelibs-process@0.1.1" "process": "github:jspm/nodelibs-process@0.1.2"
}, },
"npm:core-js@0.9.18": { "npm:core-js@0.9.18": {
"fs": "github:jspm/nodelibs-fs@0.1.2", "fs": "github:jspm/nodelibs-fs@0.1.2",
"process": "github:jspm/nodelibs-process@0.1.1", "process": "github:jspm/nodelibs-process@0.1.2",
"systemjs-json": "github:systemjs/plugin-json@0.1.0" "systemjs-json": "github:systemjs/plugin-json@0.1.0"
}, },
"npm:esprima@2.2.0": {
"fs": "github:jspm/nodelibs-fs@0.1.2",
"process": "github:jspm/nodelibs-process@0.1.1"
},
"npm:inherits@2.0.1": { "npm:inherits@2.0.1": {
"util": "github:jspm/nodelibs-util@0.1.0" "util": "github:jspm/nodelibs-util@0.1.0"
}, },
"npm:js-yaml@3.3.1": { "npm:js-yaml@3.5.5": {
"argparse": "npm:argparse@1.0.2", "argparse": "npm:argparse@1.0.7",
"esprima": "npm:esprima@2.2.0", "esprima": "npm:esprima@2.7.2",
"fs": "github:jspm/nodelibs-fs@0.1.2", "fs": "github:jspm/nodelibs-fs@0.1.2",
"path": "github:jspm/nodelibs-path@0.1.0", "process": "github:jspm/nodelibs-process@0.1.2",
"process": "github:jspm/nodelibs-process@0.1.1", "systemjs-json": "github:systemjs/plugin-json@0.1.0"
"systemjs-json": "github:systemjs/plugin-json@0.1.0",
"util": "github:jspm/nodelibs-util@0.1.0"
},
"npm:lodash@3.10.1": {
"process": "github:jspm/nodelibs-process@0.1.1"
}, },
"npm:path-browserify@0.0.0": { "npm:path-browserify@0.0.0": {
"process": "github:jspm/nodelibs-process@0.1.1" "process": "github:jspm/nodelibs-process@0.1.2"
},
"npm:process@0.11.2": {
"assert": "github:jspm/nodelibs-assert@0.1.0"
}, },
"npm:read-yaml@1.0.0": { "npm:read-yaml@1.0.0": {
"fs": "github:jspm/nodelibs-fs@0.1.2", "fs": "github:jspm/nodelibs-fs@0.1.2",
"js-yaml": "npm:js-yaml@3.3.1", "js-yaml": "npm:js-yaml@3.5.5",
"xtend": "npm:xtend@4.0.0" "xtend": "npm:xtend@4.0.1"
}, },
"npm:util@0.10.3": { "npm:util@0.10.3": {
"inherits": "npm:inherits@2.0.1", "inherits": "npm:inherits@2.0.1",
"process": "github:jspm/nodelibs-process@0.1.1" "process": "github:jspm/nodelibs-process@0.1.2"
} }
} }
}); });

View File

@ -5,6 +5,7 @@
"lib": "src" "lib": "src"
}, },
"dependencies": { "dependencies": {
"Doodle3D/clipper-js": "github:Doodle3D/clipper-js@^0.0.2",
"casperlamboo/EventDispatcher": "github:casperlamboo/EventDispatcher@master", "casperlamboo/EventDispatcher": "github:casperlamboo/EventDispatcher@master",
"clipper-lib": "npm:clipper-lib@^1.0.0", "clipper-lib": "npm:clipper-lib@^1.0.0",
"nodeca/js-yaml": "github:nodeca/js-yaml@^3.3.1", "nodeca/js-yaml": "github:nodeca/js-yaml@^3.3.1",

View File

@ -1,35 +1,10 @@
import Paths from './paths.js'; import Shape from 'Doodle3D/clipper-js';
export default class { export default class {
constructor () { constructor () {
this.parts = []; this.parts = [];
} }
removeSelfIntersect () {
for (var i = 0; i < this.parts.length; i ++) {
var part1 = this.parts[i].intersect;
if (!part1.closed) {
continue;
}
for (var j = i + 1; j < this.parts.length; j ++) {
var part2 = this.parts[j].intersect;
if (!part2.closed) {
continue;
}
if (part2.intersect(part1).length > 0) {
part1 = this.parts[i].intersect = part1.union(part2);
this.parts.splice(j, 1);
j --;
}
}
}
}
optimizePaths (start) { optimizePaths (start) {
if (this.brim !== undefined && this.brim.length > 0) { if (this.brim !== undefined && this.brim.length > 0) {
this.brim = this.brim.optimizePath(start); this.brim = this.brim.optimizePath(start);
@ -45,11 +20,11 @@ export default class {
for (var i = 0; i < this.parts.length; i ++) { for (var i = 0; i < this.parts.length; i ++) {
var part = this.parts[i]; var part = this.parts[i];
if (part.intersect.closed) { if (part.shape.closed) {
var bounds = part.outerLine.bounds(); var bounds = part.outerLine.bounds();
} }
else { else {
var bounds = part.intersect.bounds(); var bounds = part.shape.bounds();
} }
var top = bounds.top - start.y; var top = bounds.top - start.y;
@ -68,7 +43,7 @@ export default class {
var part = this.parts.splice(closestPart, 1)[0]; var part = this.parts.splice(closestPart, 1)[0];
parts.push(part); parts.push(part);
if (part.intersect.closed) { if (part.shape.closed) {
if (part.outerLine.length > 0) { if (part.outerLine.length > 0) {
part.outerLine = part.outerLine.optimizePath(start); part.outerLine = part.outerLine.optimizePath(start);
start = part.outerLine.lastPoint(); start = part.outerLine.lastPoint();
@ -88,8 +63,8 @@ export default class {
} }
} }
else { else {
part.intersect.optimizePath(start); part.shape.optimizePath(start);
start = part.intersect.lastPoint(); start = part.shape.lastPoint();
} }
} }
@ -105,12 +80,12 @@ export default class {
} }
getOutline () { getOutline () {
var outLines = new Paths([], true); var outLines = new Shape([], true);
for (var i = 0; i < this.parts.length; i ++) { for (var i = 0; i < this.parts.length; i ++) {
var part = this.parts[i]; var part = this.parts[i];
if (part.intersect.closed) { if (part.shape.closed) {
outLines.join(this.parts[i].outerLine); outLines.join(this.parts[i].outerLine);
} }
} }
@ -118,17 +93,15 @@ export default class {
return outLines; return outLines;
} }
add (intersect) { add (shape) {
var parts = { const part = { shape };
intersect
};
if (intersect.closed) { if (shape.closed) {
parts.innerLines = []; part.innerLines = [];
parts.outerLine = new Paths([], true); part.outerLine = new Shape([], true);
parts.fill = new Paths([], false); part.fill = new Shape([], false);
} }
this.parts.push(parts); this.parts.push(part);
} }
} }

View File

@ -41,7 +41,7 @@ export default function generateInfills(slices, settings) {
for (var i = 0; i < slice.parts.length; i ++) { for (var i = 0; i < slice.parts.length; i ++) {
var part = slice.parts[i]; var part = slice.parts[i];
if (!part.intersect.closed) { if (!part.shape.closed) {
continue; continue;
} }

View File

@ -1,10 +1,16 @@
const scale = 100; const scale = 100;
const offsetOptions = {
jointType: 'jtSquare',
endType: 'etClosedPolygon',
miterLimit: 2.0,
roundPrecision: 0.25
};
export default function generateInnerLines(slices, settings) { 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 // need to scale up everything because of clipper rounding errors
let {layerHeight, nozzleDiameter, shellThickness} = settings.config; let { layerHeight, nozzleDiameter, shellThickness } = settings.config;
nozzleDiameter *= scale; nozzleDiameter *= scale;
shellThickness *= scale; shellThickness *= scale;
var nozzleRadius = nozzleDiameter / 2; var nozzleRadius = nozzleDiameter / 2;
@ -16,23 +22,21 @@ export default function generateInnerLines(slices, settings) {
for (var i = 0; i < slice.parts.length; i ++) { for (var i = 0; i < slice.parts.length; i ++) {
var part = slice.parts[i]; var part = slice.parts[i];
if (!part.intersect.closed) { if (!part.shape.closed) continue;
continue;
}
// var outerLine = part.intersect.clone().scaleUp(scale).offset(-nozzleRadius); // var outerLine = part.shape.clone().scaleUp(scale).offset(-nozzleRadius);
var outerLine = part.intersect.scaleUp(scale).offset(-nozzleRadius); var outerLine = part.shape.scaleUp(scale).offset(-nozzleRadius, offsetOptions);
if (outerLine.length > 0) { if (outerLine.length > 0) {
part.outerLine = outerLine; part.outerLine.join(outerLine);
for (var shell = 1; shell < shells; shell += 1) { for (var shell = 1; shell < shells; shell += 1) {
var offset = shell * nozzleDiameter; var offset = shell * nozzleDiameter;
var innerLine = outerLine.offset(-offset); var innerLine = outerLine.offset(-offset, offsetOptions);
if (innerLine.length > 0) { if (innerLine.length > 0) {
part.innerLines.push(innerLine); part.innerLines.paths.push(innerLine);
} }
else { else {
break; break;

View File

@ -1,7 +1,7 @@
import Paths from '../paths.js'; import Shape from 'Doodle3D/clipper-js';
export default function getFillTemplate(bounds, size, even, uneven) { export default function getFillTemplate(bounds, size, even, uneven) {
var paths = new Paths([], false); var shape = new Shape([], false);
var left = Math.floor(bounds.left / size) * size; var left = Math.floor(bounds.left / size) * size;
var right = Math.ceil(bounds.right / size) * size; var right = Math.ceil(bounds.right / size) * size;
@ -12,7 +12,7 @@ export default function getFillTemplate(bounds, size, even, uneven) {
if (even) { if (even) {
for (var y = top; y <= bottom + width; y += size) { for (var y = top; y <= bottom + width; y += size) {
paths.push([ shape.paths.push([
{X: left, Y: y}, {X: left, Y: y},
{X: right, Y: y - width} {X: right, Y: y - width}
]); ]);
@ -20,12 +20,12 @@ export default function getFillTemplate(bounds, size, even, uneven) {
} }
if (uneven) { if (uneven) {
for (var y = top - width; y <= bottom; y += size) { for (var y = top - width; y <= bottom; y += size) {
paths.push([ shape.paths.push([
{X: left, Y: y}, {X: left, Y: y},
{X: right, Y: y + width} {X: right, Y: y + width}
]); ]);
} }
} }
return paths; return shape;
} }

View File

@ -1,10 +1,10 @@
import THREE from 'three.js'; import THREE from 'three.js';
import Paths from '../paths.js'; import Shape from 'Doodle3D/clipper-js';
export default function intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings) { export default function intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings) {
console.log("generating slices"); console.log("generating slices");
var shapes = []; var layers = [];
for (var layer = 1; layer < layerIntersectionIndexes.length; layer ++) { for (var layer = 1; layer < layerIntersectionIndexes.length; layer ++) {
var intersectionIndexes = layerIntersectionIndexes[layer]; var intersectionIndexes = layerIntersectionIndexes[layer];
@ -14,7 +14,8 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
continue; continue;
} }
var shapeParts = []; var closedShapes = [];
var openShapes = [];
for (var i = 0; i < intersectionIndexes.length; i ++) { for (var i = 0; i < intersectionIndexes.length; i ++) {
var index = intersectionIndexes[i]; var index = intersectionIndexes[i];
@ -31,7 +32,7 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
while (index !== -1) { while (index !== -1) {
var intersection = intersectionPoints[index]; var intersection = intersectionPoints[index];
// uppercase X and Y because clipper vector // uppercase X and Y because clipper vector
shape.push({X: intersection.x, Y: intersection.y}); shape.push(intersection);
delete intersectionPoints[index]; delete intersectionPoints[index];
@ -94,7 +95,7 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
while (index !== -1) { while (index !== -1) {
if (firstPoints.indexOf(index) === -1) { if (firstPoints.indexOf(index) === -1) {
var intersection = intersectionPoints[index]; var intersection = intersectionPoints[index];
shape.unshift({X: intersection.x, Y: intersection.y}); shape.unshift(intersection);
delete intersectionPoints[index]; delete intersectionPoints[index];
} }
@ -114,14 +115,16 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
} }
} }
var part = new Paths([shape], closed).clean(0.01); if (closed) {
if (part.length > 0) { closedShapes.push(shape);
shapeParts.push(part); }
else {
openShapes.push(shape);
} }
} }
shapes.push(shapeParts); layers.push({ closedShapes, openShapes });
} }
return shapes; return layers;
} }

View File

@ -1,4 +1,10 @@
import THREE from 'three.js'; import THREE from 'three.js';
const offsetOptions = {
jointType: 'jtSquare',
endType: 'etClosedPolygon',
miterLimit: 2.0,
roundPrecision: 0.25
};
export default function optimizePaths(slices, settings) { export default function optimizePaths(slices, settings) {
console.log("opimize paths"); console.log("opimize paths");
@ -14,15 +20,15 @@ export default function optimizePaths(slices, settings) {
var slice = slices[layer]; var slice = slices[layer];
if (layer === 0) { if (layer === 0) {
slice.brim = slice.getOutline().offset(brimOffset); slice.brim = slice.getOutline().offset(brimOffset, offsetOptions);
} }
start = slice.optimizePaths(start); // start = slice.optimizePaths(start);
for (var i = 0; i < slice.parts.length; i ++) { for (var i = 0; i < slice.parts.length; i ++) {
var part = slice.parts[i]; var part = slice.parts[i];
if (part.intersect.closed) { if (part.shape.closed) {
part.outerLine.scaleDown(scale); part.outerLine.scaleDown(scale);
for (var j = 0; j < part.innerLines.length; j ++) { for (var j = 0; j < part.innerLines.length; j ++) {
var innerLine = part.innerLines[j]; var innerLine = part.innerLines[j];

View File

@ -1,65 +1,37 @@
import Shape from 'Doodle3D/clipper-js';
import Slice from '../slice.js'; import Slice from '../slice.js';
export default function shapesToSlices(shapes, settings) { export default function shapesToSlices(shapes, settings) {
var slices = []; const sliceLayers = [];
for (var layer = 0; layer < shapes.length; layer ++) { for (var layer = 0; layer < shapes.length; layer ++) {
var shapeParts = shapes[layer]; var { closedShapes, openShapes } = shapes[layer];
closedShapes = new Shape(closedShapes, true, true)
.clean(0.01)
.fixOrientation()
.removeOverlap()
.seperateShapes();
openShapes = new Shape(openShapes, false, true)
.clean(0.01);
var slice = new Slice(); var slice = new Slice();
var holes = []; for (var i = 0; i < closedShapes.length; i ++) {
var outlines = []; var closedShape = closedShapes[i];
slice.add(closedShape);
for (var i = 0; i < shapeParts.length; i ++) { // if (openShapes.path.length > 0) {
var shape = shapeParts[i]; // openShapes = openShapes.difference(closedShape);
// }
if (!shape.closed) { }
slice.add(shape); if (openShapes.paths.length > 0) {
} slice.add(openShapes);
else if (shape.isHole()) {
holes.push(shape);
}
else {
slice.add(shape);
outlines.push(shape);
}
} }
outlines.sort((a, b) => { sliceLayers.push(slice);
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; return sliceLayers;
} }

View File

@ -3,15 +3,14 @@ import GCode from '../gcode.js';
export default function slicesToGCode(slices, settings) { export default function slicesToGCode(slices, settings) {
var gcode = new GCode().setSettings(settings); var gcode = new GCode().setSettings(settings);
function pathToGCode (path, retract, unRetract, type) { function pathToGCode (shape, retract, unRetract, type) {
for (var i = 0; i < shape.paths.length; i ++) {
var line = shape.paths[i];
for (var i = 0; i < path.length; i ++) { var length = shape.closed ? (line.length + 1) : line.length;
var shape = path[i];
var length = path.closed ? (shape.length + 1) : shape.length;
for (var j = 0; j < length; j ++) { for (var j = 0; j < length; j ++) {
var point = shape[j % shape.length]; var point = line[j % line.length];
if (j === 0) { if (j === 0) {
// TODO // TODO
@ -48,7 +47,7 @@ export default function slicesToGCode(slices, settings) {
for (var i = 0; i < slice.parts.length; i ++) { for (var i = 0; i < slice.parts.length; i ++) {
var part = slice.parts[i]; var part = slice.parts[i];
if (part.intersect.closed) { if (part.shape.closed) {
pathToGCode(part.outerLine, false, true, "outerLine"); pathToGCode(part.outerLine, false, true, "outerLine");
for (var j = 0; j < part.innerLines.length; j ++) { for (var j = 0; j < part.innerLines.length; j ++) {
@ -60,7 +59,7 @@ export default function slicesToGCode(slices, settings) {
} }
else { else {
var retract = !(slice.parts.length === 1 && slice.support === undefined); var retract = !(slice.parts.length === 1 && slice.support === undefined);
pathToGCode(part.intersect, retract, retract, "outerLine"); pathToGCode(part.shape, retract, retract, "outerLine");
} }
} }

View File

@ -67,15 +67,18 @@ export default class extends EventDispatcher {
this.progress.createdLines = true; this.progress.createdLines = true;
this._updateProgress(settings); this._updateProgress(settings);
var {layerIntersectionIndexes, layerIntersectionPoints} = calculateLayersIntersections(lines, settings); const {
layerIntersectionIndexes,
layerIntersectionPoints
} = calculateLayersIntersections(lines, settings);
this.progress.calculatedLayerIntersections = true; this.progress.calculatedLayerIntersections = true;
this._updateProgress(settings); this._updateProgress(settings);
var shapes = intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings); const shapes = intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings);
this.progress.sliced = true; this.progress.sliced = true;
this._updateProgress(settings); this._updateProgress(settings);
var slices = shapesToSlices(shapes, settings); const slices = shapesToSlices(shapes, settings);
this.progress.generatedSlices = true; this.progress.generatedSlices = true;
this._updateProgress(settings); this._updateProgress(settings);