added Support

This commit is contained in:
casperlamboo 2015-06-09 21:58:22 +02:00
parent 17bd8f4f25
commit 57179fbe20
7 changed files with 219 additions and 221 deletions

BIN
models/support_test.stl Normal file

Binary file not shown.

View File

@ -14,5 +14,11 @@
"printer.speed": 50.0, "printer.speed": 50.0,
"printer.temperature": 210.0, "printer.temperature": 210.0,
"printer.topThickness": 0.8, "printer.topThickness": 0.8,
"printer.travelSpeed": 200.0 "printer.travelSpeed": 200.0,
"printer.support.minArea": 2.0,
"printer.support.distanceY": 0.15,
"printer.support.use": true,
"printer.support.size": 3,
"printer.support.margin": 1.0,
"printer.support.offset": 1.0
} }

View File

@ -36,7 +36,7 @@ function init () {
var printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS["ultimaker"]); var printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS["ultimaker"]);
var loader = new THREE.STLLoader(); var loader = new THREE.STLLoader();
loader.load("models/dom.stl", function (geometry) { loader.load('models/robot.stl', function (geometry) {
//var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1); //var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1);
//var geometry = new THREE.SphereGeometry(10, 20, 10); //var geometry = new THREE.SphereGeometry(10, 20, 10);
//var geometry = new THREE.TorusGeometry(20, 10, 30, 30); //var geometry = new THREE.TorusGeometry(20, 10, 30, 30);
@ -70,13 +70,12 @@ function init () {
mesh.rotation.x = -Math.PI/2; mesh.rotation.x = -Math.PI/2;
mesh.scale.x = mesh.scale.y = mesh.scale.z = 1; mesh.scale.x = mesh.scale.y = mesh.scale.z = 1;
mesh.position.y = -9.260265119962973e-17; mesh.position.y = -0.1;
mesh.position.x = 100; mesh.position.x = 100;
mesh.position.z = 100; mesh.position.z = 100;
scene.add(mesh); scene.add(mesh);
mesh.updateMatrix();
var slicer = new D3D.Slicer().setMesh(mesh.geometry, mesh.matrix); var slicer = new D3D.Slicer().setMesh(mesh.geometry, mesh.matrix);
//var canvas = document.getElementById("canvas"); //var canvas = document.getElementById("canvas");
@ -85,7 +84,7 @@ function init () {
//var img = slicer.drawPaths(printer, 0, 1); //var img = slicer.drawPaths(printer, 0, 1);
//context.drawImage(img, 0, 0); //context.drawImage(img, 0, 0);
gcode = slicer.getGcode(printer); gcode = slicer.getGCode(printer);
}); });
} }

View File

@ -3,19 +3,20 @@
* GCode * GCode
* *
* Manages the gcode * Manages the gcode
* Also handles different flavours of gcode
* *
******************************************************/ ******************************************************/
D3D.GCode = function () { D3D.GCode = function () {
"use strict"; "use strict";
this.gcode = [];
this.current = {}; this.current = {};
this.extruder = 0.0; this.extruder = 0.0;
this.bottom = true; this.bottom = true;
this.isRetracted = false; this.isRetracted = false;
this.isFanOn = false; this.isFanOn = false;
this.gcode = [];
this.nozzlePosition = new THREE.Vector2(0, 0); this.nozzlePosition = new THREE.Vector2(0, 0);
}; };
D3D.GCode.prototype.addGCode = function (command) { D3D.GCode.prototype.addGCode = function (command) {
@ -24,7 +25,10 @@ D3D.GCode.prototype.addGCode = function (command) {
var str = []; var str = [];
for (var i in command) { for (var i in command) {
if (this.current[i] !== command[i] || i === "G") { if (i === "G") {
str.push(i + command[i]);
}
else if (this.current[i] !== command[i]) {
str.push(i + command[i]); str.push(i + command[i]);
this.current[i] = command[i]; this.current[i] = command[i];
} }
@ -111,7 +115,7 @@ D3D.GCode.prototype.moveTo = function (extrude, x, y, layer) {
else { else {
var speed = travelSpeed * 60; var speed = travelSpeed * 60;
this.addGCode.({ this.addGCode({
"G": 0, "G": 0,
"X": x.toFixed(3), "Y": y.toFixed(3), "Z": z.toFixed(3), "X": x.toFixed(3), "Y": y.toFixed(3), "Z": z.toFixed(3),
"F": speed.toFixed(3) "F": speed.toFixed(3)
@ -126,6 +130,7 @@ D3D.GCode.prototype.moveTo = function (extrude, x, y, layer) {
D3D.GCode.prototype.unRetract = function () { D3D.GCode.prototype.unRetract = function () {
"use strict"; "use strict";
if (this.isRetracted) {
this.isRetracted = false; this.isRetracted = false;
var retractionAmount = this.settings.config["printer.retraction.amount"]; var retractionAmount = this.settings.config["printer.retraction.amount"];
@ -144,10 +149,12 @@ D3D.GCode.prototype.unRetract = function () {
} }
return this; return this;
}
}; };
D3D.GCode.prototype.retract = function () { D3D.GCode.prototype.retract = function () {
"use strict"; "use strict";
if (!this.isRetracted) {
this.isRetracted = true; this.isRetracted = true;
var retractionAmount = this.settings.config["printer.retraction.amount"]; var retractionAmount = this.settings.config["printer.retraction.amount"];
@ -166,6 +173,7 @@ D3D.GCode.prototype.retract = function () {
} }
return this; return this;
}
}; };
D3D.GCode.prototype.getGCode = function () { D3D.GCode.prototype.getGCode = function () {
"use strict"; "use strict";

View File

@ -160,6 +160,19 @@ D3D.Paths.prototype.optimizePath = function (start) {
return optimizedPaths; return optimizedPaths;
}; };
D3D.Paths.prototype.areas = function () {
"use strict";
var areas = [];
for (var i = 0; i < this.length; i ++) {
var shape = this[i];
areas.push(ClipperLib.Clipper.Area(shape));
}
return areas;
};
D3D.Paths.prototype.tresholdArea = function (minArea) { D3D.Paths.prototype.tresholdArea = function (minArea) {
//code not tested yet //code not tested yet
"use strict"; "use strict";

View File

@ -165,10 +165,6 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
intersections[index] = new THREE.Vector2(z, x); intersections[index] = new THREE.Vector2(z, x);
log.push({x: z, y: x, index: index, connects: this.lines[index].connects}); log.push({x: z, y: x, index: index, connects: this.lines[index].connects});
} }
/*if (layer === 10) {
console.log(JSON.stringify(log));
breakCode();
}*/
var done = []; var done = [];
var slice = []; var slice = [];
@ -293,15 +289,16 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var brimOffset = printer.config["printer.brimOffset"] * scale; var brimOffset = printer.config["printer.brimOffset"] * scale;
var bottomThickness = printer.config["printer.bottomThickness"] * scale; var bottomThickness = printer.config["printer.bottomThickness"] * scale;
var topThickness = printer.config["printer.topThickness"] * scale; var topThickness = printer.config["printer.topThickness"] * scale;
var useSupport = printer.config["printer.support.use"];
var supportSize = printer.config["printer.support.size"] * scale;
var supportMinArea = printer.config["printer.support.minArea"] * Math.pow(scale, 2);
var supportMargin = printer.config["printer.support.margin"] * scale;
var supportOffset = printer.config["printer.support.offset"] * scale;
var bottomSkinCount = Math.ceil(bottomThickness/layerHeight); var bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
var topSkinCount = Math.ceil(topThickness/layerHeight); var topSkinCount = Math.ceil(topThickness/layerHeight);
var nozzleRadius = nozzleDiameter / 2; var nozzleRadius = nozzleDiameter / 2;
var start = new THREE.Vector2(0, 0);
var data = [];
var lowFillTemplate = this.getFillTemplate({ var lowFillTemplate = this.getFillTemplate({
left: this.geometry.boundingBox.min.z * scale, left: this.geometry.boundingBox.min.z * scale,
top: this.geometry.boundingBox.min.x * scale, top: this.geometry.boundingBox.min.x * scale,
@ -309,45 +306,64 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
bottom: this.geometry.boundingBox.max.x * scale bottom: this.geometry.boundingBox.max.x * scale
}, fillSize, true, true); }, fillSize, true, true);
var data = [];
//generate outerLayer and insets
for (var layer = 0; layer < slices.length; layer ++) { for (var layer = 0; layer < slices.length; layer ++) {
var slice = slices[layer]; var slice = slices[layer];
var layerData = []; var layerData = [];
data.push(layerData); data.push(layerData);
var downSkin = new D3D.Paths([], true);
if (layer - bottomSkinCount >= 0) {
var downLayer = slices[layer - bottomSkinCount];
for (var i = 0; i < downLayer.length; i ++) {
downSkin.join(downLayer[i]);
}
}
var upSkin = new D3D.Paths([], true);
if (layer + topSkinCount < slices.length) {
var upLayer = slices[layer + topSkinCount];
for (var i = 0; i < upLayer.length; i ++) {
upSkin.join(upLayer[i]);
}
}
var surroundingLayer = upSkin.intersect(downSkin).scaleUp(scale);
var sliceData = [];
for (var i = 0; i < slice.length; i ++) { for (var i = 0; i < slice.length; i ++) {
var part = slice[i]; var part = slice[i];
//var outerLayer = part.clone();
var outerLayer = part.clone().scaleUp(scale).offset(-nozzleRadius); var outerLayer = part.clone().scaleUp(scale).offset(-nozzleRadius);
if (outerLayer.length > 0) {
var insets = new D3D.Paths([], true); var insets = new D3D.Paths([], true);
if (outerLayer.length > 0) {
for (var offset = nozzleDiameter; offset <= shellThickness; offset += nozzleDiameter) { for (var offset = nozzleDiameter; offset <= shellThickness; offset += nozzleDiameter) {
var inset = outerLayer.offset(-offset); var inset = outerLayer.offset(-offset);
insets.join(inset); insets.join(inset);
} }
var fillArea = (inset || outerLayer).offset(-nozzleRadius); layerData.push({
//var fillArea = (inset || outerLayer).clone(); outerLayer: outerLayer,
insets: insets
});
}
}
}
//generate infills
for (var layer = 0; layer < data.length; layer ++) {
var slice = data[layer];
var downSkin = new D3D.Paths([], true);
if (layer - bottomSkinCount >= 0) {
var downLayer = data[layer - bottomSkinCount];
for (var i = 0; i < downLayer.length; i ++) {
downSkin.join(downLayer[i].outerLayer);
}
}
var upSkin = new D3D.Paths([], true);
if (layer + topSkinCount < data.length) {
var upLayer = data[layer + topSkinCount];
for (var i = 0; i < upLayer.length; i ++) {
upSkin.join(upLayer[i].outerLayer);
}
}
var surroundingLayer = upSkin.intersect(downSkin);
var sliceData = [];
for (var i = 0; i < slice.length; i ++) {
var part = slice[i];
var outerLayer = part.outerLayer;
var insets = part.insets;
if (outerLayer.length > 0) {
var fillArea = ((insets.length > 0) ? insets : outerLayer).offset(-nozzleRadius);
var highFillArea = fillArea.difference(surroundingLayer); var highFillArea = fillArea.difference(surroundingLayer);
var lowFillArea = fillArea.difference(highFillArea); var lowFillArea = fillArea.difference(highFillArea);
@ -364,30 +380,7 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
fill.join(highFillTemplate.intersect(highFillArea)); fill.join(highFillTemplate.intersect(highFillArea));
} }
outerLayer = outerLayer.optimizePath(start); part.fill = fill;
if (insets.length > 0) {
insets = insets.optimizePath(outerLayer.lastPoint());
fill = fill.optimizePath(insets.lastPoint());
}
else {
fill = fill.optimizePath(outerLayer.lastPoint());
}
if (fill.length > 0) {
start = fill.lastPoint();
}
else if (insets.length > 0) {
start = insets.lastPoint();
}
else {
start = outerLayer.lastPoint();
}
layerData.push({
outerLayer: outerLayer.scaleDown(scale),
fill: fill.scaleDown(scale),
insets: insets.scaleDown(scale)
});
} }
} }
@ -395,8 +388,100 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
this.updateProgress(); this.updateProgress();
} }
//generate support
if (useSupport) {
var supportTemplate = this.getFillTemplate({
left: this.geometry.boundingBox.min.z * scale,
top: this.geometry.boundingBox.min.x * scale,
right: this.geometry.boundingBox.max.z * scale,
bottom: this.geometry.boundingBox.max.x * scale
}, supportSize, true, true);
var supportAreas = new D3D.Paths([], true);
for (var layer = data.length - 1; layer >= 0; layer --) {
var slice = data[layer];
if (supportAreas.length > 0) {
var currentSkin = new D3D.Paths([], true);
for (var i = 0; i < slice.length; i ++) {
currentSkin.join(slice[i].outerLayer);
}
currentSkin = currentSkin.offset(supportMargin);
supportAreas = supportAreas.difference(currentSkin);
slice[0].support = supportTemplate.intersect(supportAreas);
}
if (layer !== 0) {
var supportSkin = new D3D.Paths([], true);
if (layer - 1 >= 0) {
var supportLayer = data[layer - 1];
for (var i = 0; i < supportLayer.length; i ++) {
supportSkin.join(supportLayer[i].outerLayer);
}
}
for (var i = 0; i < slice.length; i ++) {
var slicePart = slice[i];
var outerLayer = slicePart.outerLayer;
var overlap = supportSkin.intersect(outerLayer);
var overhang = outerLayer.difference(overlap);
if (overlap.length === 0) {
var supportArea = overhang.offset(supportOffset);
supportAreas = supportAreas.union(supportArea);
}
else if (overhang.length > 0) {
var areas = overhang.areas();
for (var j = 0; j < areas.length; j ++) {
var area = areas[i];
if (area > supportMinArea) {
var supportArea = new D3D.Paths([overhang[i]], false).offset(supportOffset);
supportAreas = supportAreas.union(supportArea);
}
}
}
}
}
}
}
//finalize paths
var start = new THREE.Vector2(0, 0);
var order = ["outerLayer", "insets", "fill", "support"];
for (var layer = 0; layer < data.length; layer ++) {
var slice = data[layer];
for (var i = 0; i < slice.length; i ++) {
var part = slice[i];
for (var j = 0; j < order.length; j ++) {
var property = order[j];
if (part[property] !== undefined && part[property].length > 0) {
part[property] = part[property].optimizePath(start);
start = part[property].lastPoint();
}
}
part.outerLayer.scaleDown(100);
part.insets.scaleDown(100);
part.fill.scaleDown(100);
if (part.support !== undefined) {
part.support.scaleDown(100);
}
}
}
return data; return data;
}; };
D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) { D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) {
"use strict"; "use strict";
@ -416,123 +501,6 @@ D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) {
//return paths; //return paths;
return paths; return paths;
}; };
/*
D3D.Slicer.prototype.dataToGCode = function (data, printer) {
"use strict";
var layerHeight = printer.config["printer.layerHeight"];
var normalSpeed = printer.config["printer.speed"];
var bottomSpeed = printer.config["printer.bottomLayerSpeed"];
var firstLayerSlow = printer.config["printer.firstLayerSlow"];
var bottomFlowRate = printer.config["printer.bottomFlowRate"];
var normalFlowRate = printer.config["printer.normalFlowRate"];
var travelSpeed = printer.config["printer.travelSpeed"];
var filamentThickness = printer.config["printer.filamentThickness"];
var nozzleDiameter = printer.config["printer.nozzleDiameter"];
var enableTraveling = printer.config["printer.enableTraveling"];
var retractionEnabled = printer.config["printer.retraction.enabled"];
var retractionSpeed = printer.config["printer.retraction.speed"];
var retractionMinDistance = printer.config["printer.retraction.minDistance"];
var retractionAmount = printer.config["printer.retraction.amount"];
function sliceToGCode (path) {
var gcode = [];
for (var i = 0; i < path.length; i ++) {
var shape = path[i];
var previousPoint;
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
//add retraction
gcode.push(
"G0" +
" X" + point.X.toFixed(3) + " Y" + point.Y.toFixed(3) + " Z" + z +
" F" + (travelSpeed * 60)
);
if (extruder > retractionMinDistance && retractionEnabled && j === 0) {
gcode.push(
"G0" +
" E" + extruder.toFixed(3) +
" F" + (retractionSpeed * 60).toFixed(3)
);
}
}
else {
var a = new THREE.Vector2(point.X, point.Y);
var b = new THREE.Vector2(previousPoint.X, previousPoint.Y);
var lineLength = a.distanceTo(b);
extruder += lineLength * nozzleDiameter * layerHeight / filamentSurfaceArea * flowRate;
gcode.push(
"G1" +
" X" + point.X.toFixed(3) + " Y" + point.Y.toFixed(3) + " Z" + z +
" F" + speed +
" E" + extruder.toFixed(3)
);
}
previousPoint = point;
}
}
if (extruder > retractionMinDistance && retractionEnabled) {
gcode.push(
"G0" +
" E" + (extruder - retractionAmount).toFixed(3) +
" F" + (retractionSpeed * 60).toFixed(3)
);
}
return gcode;
}
var gcode = printer.getStartCode();
var extruder = 0.0;
var speed = firstLayerSlow ? (bottomSpeed*60).toFixed(3) : (normalSpeed*60).toFixed(3);
var filamentSurfaceArea = Math.pow((filamentThickness/2), 2) * Math.PI;
var flowRate = bottomFlowRate;
for (var layer = 0; layer < data.length; layer ++) {
var slice = data[layer];
//turn on fan on layer 1
if (layer === 1) {
gcode.push("M106");
speed = (normalSpeed*60).toFixed(3);
flowRate = normalFlowRate;
}
var z = ((layer + 1) * layerHeight).toFixed(3);
for (var i = 0; i < slice.length; i ++) {
var layerPart = slice[i];
gcode = gcode.concat(sliceToGCode(layerPart.outerLayer));
gcode = gcode.concat(sliceToGCode(layerPart.insets));
gcode = gcode.concat(sliceToGCode(layerPart.fill));
}
this.progress.gcodeLayer = layer;
this.updateProgress();
}
gcode = gcode.concat(printer.getEndCode());
return gcode;
};
*/
D3D.Slicer.prototype.dataToGCode = function (data, printer) { D3D.Slicer.prototype.dataToGCode = function (data, printer) {
"use strict"; "use strict";
@ -578,7 +546,11 @@ D3D.Slicer.prototype.dataToGCode = function (data, printer) {
sliceToGCode(layerPart.outerLayer, false, true); sliceToGCode(layerPart.outerLayer, false, true);
sliceToGCode(layerPart.insets, false, false); sliceToGCode(layerPart.insets, false, false);
sliceToGCode(layerPart.fill, true, false); sliceToGCode(layerPart.fill, (layerPart.support === undefined), false);
if (layerPart.support !== undefined) {
sliceToGCode(layerPart.support, true, false);
}
} }
this.progress.gcodeLayer = layer; this.progress.gcodeLayer = layer;

View File

@ -47,19 +47,19 @@ function init () {
var scene = createScene(); var scene = createScene();
var localIp = location.hash.substring(1); var localIp = location.hash.substring(1);
doodleBox = new D3D.Box(localIp); //doodleBox = new D3D.Box(localIp);
doodleBox.onupdate = function (data) { //doodleBox.onupdate = function (data) {
document.getElementById('state').innerHTML = data.state; // document.getElementById('state').innerHTML = data.state;
document.getElementById('bed_temp').innerHTML = data.bed; // document.getElementById('bed_temp').innerHTML = data.bed;
document.getElementById('bed_target_temp').innerHTML = data.bed_target; // document.getElementById('bed_target_temp').innerHTML = data.bed_target;
document.getElementById('nozzle_temp').innerHTML = data.hotend; // document.getElementById('nozzle_temp').innerHTML = data.hotend;
document.getElementById('nozzle_target_temp').innerHTML = data.hotend_target; // document.getElementById('nozzle_target_temp').innerHTML = data.hotend_target;
document.getElementById('current_line').innerHTML = data.current_line; // document.getElementById('current_line').innerHTML = data.current_line;
document.getElementById('buffered_lines').innerHTML = data.buffered_lines; // document.getElementById('buffered_lines').innerHTML = data.buffered_lines;
document.getElementById('total_lines').innerHTML = data.total_lines; // document.getElementById('total_lines').innerHTML = data.total_lines;
document.getElementById('print_batches').innerHTML = doodleBox.printBatches.length; // document.getElementById('print_batches').innerHTML = doodleBox.printBatches.length;
}; //};
printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS['ultimaker2go']); printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS['ultimaker2go']);
@ -92,7 +92,7 @@ function init () {
}; };
var loader = new THREE.STLLoader(); var loader = new THREE.STLLoader();
loader.load('models/dom.stl', function (geometry) { loader.load('models/robot.stl', function (geometry) {
//var geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone(); //var geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone();
var material = new THREE.MeshPhongMaterial({color: 0x00ff00, wireframe: false}); var material = new THREE.MeshPhongMaterial({color: 0x00ff00, wireframe: false});