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: {
"babel": "npm:babel-core@5.8.21",
"babel-runtime": "npm:babel-runtime@5.8.20",
"Doodle3D/clipper-js": "github:Doodle3D/clipper-js@0.0.2",
"babel": "npm:babel-core@5.8.38",
"babel-runtime": "npm:babel-runtime@5.8.38",
"casperlamboo/EventDispatcher": "github:casperlamboo/EventDispatcher@master",
"clipper-lib": "npm:clipper-lib@1.0.0",
"core-js": "npm:core-js@0.9.18",
"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",
"systemjs/plugin-json": "github:systemjs/plugin-json@0.1.0",
"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": {
"assert": "npm:assert@1.3.0"
},
"github:jspm/nodelibs-path@0.1.0": {
"path-browserify": "npm:path-browserify@0.0.0"
},
"github:jspm/nodelibs-process@0.1.1": {
"process": "npm:process@0.10.1"
"github:jspm/nodelibs-process@0.1.2": {
"process": "npm:process@0.11.2"
},
"github:jspm/nodelibs-util@0.1.0": {
"util": "npm:util@0.10.3"
},
"npm:argparse@1.0.2": {
"assert": "github:jspm/nodelibs-assert@0.1.0",
"npm:argparse@1.0.7": {
"fs": "github:jspm/nodelibs-fs@0.1.2",
"lodash": "npm:lodash@3.10.1",
"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",
"util": "github:jspm/nodelibs-util@0.1.0"
},
"npm:assert@1.3.0": {
"util": "npm:util@0.10.3"
},
"npm:babel-runtime@5.8.20": {
"process": "github:jspm/nodelibs-process@0.1.1"
"npm:babel-runtime@5.8.38": {
"process": "github:jspm/nodelibs-process@0.1.2"
},
"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": {
"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"
},
"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": {
"util": "github:jspm/nodelibs-util@0.1.0"
},
"npm:js-yaml@3.3.1": {
"argparse": "npm:argparse@1.0.2",
"esprima": "npm:esprima@2.2.0",
"npm:js-yaml@3.5.5": {
"argparse": "npm:argparse@1.0.7",
"esprima": "npm:esprima@2.7.2",
"fs": "github:jspm/nodelibs-fs@0.1.2",
"path": "github:jspm/nodelibs-path@0.1.0",
"process": "github:jspm/nodelibs-process@0.1.1",
"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"
"process": "github:jspm/nodelibs-process@0.1.2",
"systemjs-json": "github:systemjs/plugin-json@0.1.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": {
"fs": "github:jspm/nodelibs-fs@0.1.2",
"js-yaml": "npm:js-yaml@3.3.1",
"xtend": "npm:xtend@4.0.0"
"js-yaml": "npm:js-yaml@3.5.5",
"xtend": "npm:xtend@4.0.1"
},
"npm:util@0.10.3": {
"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"
},
"dependencies": {
"Doodle3D/clipper-js": "github:Doodle3D/clipper-js@^0.0.2",
"casperlamboo/EventDispatcher": "github:casperlamboo/EventDispatcher@master",
"clipper-lib": "npm:clipper-lib@^1.0.0",
"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 {
constructor () {
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) {
if (this.brim !== undefined && this.brim.length > 0) {
this.brim = this.brim.optimizePath(start);
@ -45,11 +20,11 @@ export default class {
for (var i = 0; i < this.parts.length; i ++) {
var part = this.parts[i];
if (part.intersect.closed) {
if (part.shape.closed) {
var bounds = part.outerLine.bounds();
}
else {
var bounds = part.intersect.bounds();
var bounds = part.shape.bounds();
}
var top = bounds.top - start.y;
@ -68,7 +43,7 @@ export default class {
var part = this.parts.splice(closestPart, 1)[0];
parts.push(part);
if (part.intersect.closed) {
if (part.shape.closed) {
if (part.outerLine.length > 0) {
part.outerLine = part.outerLine.optimizePath(start);
start = part.outerLine.lastPoint();
@ -88,8 +63,8 @@ export default class {
}
}
else {
part.intersect.optimizePath(start);
start = part.intersect.lastPoint();
part.shape.optimizePath(start);
start = part.shape.lastPoint();
}
}
@ -105,12 +80,12 @@ export default class {
}
getOutline () {
var outLines = new Paths([], true);
var outLines = new Shape([], true);
for (var i = 0; i < this.parts.length; i ++) {
var part = this.parts[i];
if (part.intersect.closed) {
if (part.shape.closed) {
outLines.join(this.parts[i].outerLine);
}
}
@ -118,17 +93,15 @@ export default class {
return outLines;
}
add (intersect) {
var parts = {
intersect
};
add (shape) {
const part = { shape };
if (intersect.closed) {
parts.innerLines = [];
parts.outerLine = new Paths([], true);
parts.fill = new Paths([], false);
if (shape.closed) {
part.innerLines = [];
part.outerLine = new Shape([], true);
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 ++) {
var part = slice.parts[i];
if (!part.intersect.closed) {
if (!part.shape.closed) {
continue;
}

View File

@ -1,10 +1,16 @@
const scale = 100;
const offsetOptions = {
jointType: 'jtSquare',
endType: 'etClosedPolygon',
miterLimit: 2.0,
roundPrecision: 0.25
};
export default function generateInnerLines(slices, settings) {
console.log("generating outer lines and inner lines");
// need to scale up everything because of clipper rounding errors
let {layerHeight, nozzleDiameter, shellThickness} = settings.config;
let { layerHeight, nozzleDiameter, shellThickness } = settings.config;
nozzleDiameter *= scale;
shellThickness *= scale;
var nozzleRadius = nozzleDiameter / 2;
@ -16,23 +22,21 @@ export default function generateInnerLines(slices, settings) {
for (var i = 0; i < slice.parts.length; i ++) {
var part = slice.parts[i];
if (!part.intersect.closed) {
continue;
}
if (!part.shape.closed) continue;
// var outerLine = part.intersect.clone().scaleUp(scale).offset(-nozzleRadius);
var outerLine = part.intersect.scaleUp(scale).offset(-nozzleRadius);
// var outerLine = part.shape.clone().scaleUp(scale).offset(-nozzleRadius);
var outerLine = part.shape.scaleUp(scale).offset(-nozzleRadius, offsetOptions);
if (outerLine.length > 0) {
part.outerLine = outerLine;
part.outerLine.join(outerLine);
for (var shell = 1; shell < shells; shell += 1) {
var offset = shell * nozzleDiameter;
var innerLine = outerLine.offset(-offset);
var innerLine = outerLine.offset(-offset, offsetOptions);
if (innerLine.length > 0) {
part.innerLines.push(innerLine);
part.innerLines.paths.push(innerLine);
}
else {
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) {
var paths = new Paths([], false);
var shape = new Shape([], false);
var left = Math.floor(bounds.left / size) * size;
var right = Math.ceil(bounds.right / size) * size;
@ -12,7 +12,7 @@ export default function getFillTemplate(bounds, size, even, uneven) {
if (even) {
for (var y = top; y <= bottom + width; y += size) {
paths.push([
shape.paths.push([
{X: left, Y: y},
{X: right, Y: y - width}
]);
@ -20,12 +20,12 @@ export default function getFillTemplate(bounds, size, even, uneven) {
}
if (uneven) {
for (var y = top - width; y <= bottom; y += size) {
paths.push([
shape.paths.push([
{X: left, Y: y},
{X: right, Y: y + width}
]);
}
}
return paths;
return shape;
}

View File

@ -1,10 +1,10 @@
import THREE from 'three.js';
import Paths from '../paths.js';
import Shape from 'Doodle3D/clipper-js';
export default function intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings) {
console.log("generating slices");
var shapes = [];
var layers = [];
for (var layer = 1; layer < layerIntersectionIndexes.length; layer ++) {
var intersectionIndexes = layerIntersectionIndexes[layer];
@ -14,7 +14,8 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
continue;
}
var shapeParts = [];
var closedShapes = [];
var openShapes = [];
for (var i = 0; i < intersectionIndexes.length; i ++) {
var index = intersectionIndexes[i];
@ -31,7 +32,7 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
while (index !== -1) {
var intersection = intersectionPoints[index];
// uppercase X and Y because clipper vector
shape.push({X: intersection.x, Y: intersection.y});
shape.push(intersection);
delete intersectionPoints[index];
@ -94,7 +95,7 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
while (index !== -1) {
if (firstPoints.indexOf(index) === -1) {
var intersection = intersectionPoints[index];
shape.unshift({X: intersection.x, Y: intersection.y});
shape.unshift(intersection);
delete intersectionPoints[index];
}
@ -114,14 +115,16 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
}
}
var part = new Paths([shape], closed).clean(0.01);
if (part.length > 0) {
shapeParts.push(part);
if (closed) {
closedShapes.push(shape);
}
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';
const offsetOptions = {
jointType: 'jtSquare',
endType: 'etClosedPolygon',
miterLimit: 2.0,
roundPrecision: 0.25
};
export default function optimizePaths(slices, settings) {
console.log("opimize paths");
@ -14,15 +20,15 @@ export default function optimizePaths(slices, settings) {
var slice = slices[layer];
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 ++) {
var part = slice.parts[i];
if (part.intersect.closed) {
if (part.shape.closed) {
part.outerLine.scaleDown(scale);
for (var j = 0; j < part.innerLines.length; j ++) {
var innerLine = part.innerLines[j];

View File

@ -1,65 +1,37 @@
import Shape from 'Doodle3D/clipper-js';
import Slice from '../slice.js';
export default function shapesToSlices(shapes, settings) {
var slices = [];
const sliceLayers = [];
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 holes = [];
var outlines = [];
for (var i = 0; i < closedShapes.length; i ++) {
var closedShape = closedShapes[i];
slice.add(closedShape);
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);
}
// if (openShapes.path.length > 0) {
// openShapes = openShapes.difference(closedShape);
// }
}
if (openShapes.paths.length > 0) {
slice.add(openShapes);
}
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);
sliceLayers.push(slice);
}
return slices;
return sliceLayers;
}

View File

@ -3,15 +3,14 @@ import GCode from '../gcode.js';
export default function slicesToGCode(slices, 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 shape = path[i];
var length = path.closed ? (shape.length + 1) : shape.length;
var length = shape.closed ? (line.length + 1) : line.length;
for (var j = 0; j < length; j ++) {
var point = shape[j % shape.length];
var point = line[j % line.length];
if (j === 0) {
// TODO
@ -48,7 +47,7 @@ export default function slicesToGCode(slices, settings) {
for (var i = 0; i < slice.parts.length; i ++) {
var part = slice.parts[i];
if (part.intersect.closed) {
if (part.shape.closed) {
pathToGCode(part.outerLine, false, true, "outerLine");
for (var j = 0; j < part.innerLines.length; j ++) {
@ -60,7 +59,7 @@ export default function slicesToGCode(slices, settings) {
}
else {
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._updateProgress(settings);
var {layerIntersectionIndexes, layerIntersectionPoints} = calculateLayersIntersections(lines, settings);
const {
layerIntersectionIndexes,
layerIntersectionPoints
} = calculateLayersIntersections(lines, settings);
this.progress.calculatedLayerIntersections = true;
this._updateProgress(settings);
var shapes = intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings);
const shapes = intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings);
this.progress.sliced = true;
this._updateProgress(settings);
var slices = shapesToSlices(shapes, settings);
const slices = shapesToSlices(shapes, settings);
this.progress.generatedSlices = true;
this._updateProgress(settings);