From 17bd8f4f25acd06e1fa0e37ba07edd4f5eee6d4b Mon Sep 17 00:00:00 2001 From: casperlamboo Date: Tue, 9 Jun 2015 11:08:06 +0200 Subject: [PATCH] improved gcode handling --- slice_test.html | 2 +- src/gcode.js | 102 +++++++++++++++++++++++++++++++------------- src/slicer.js | 96 +++++++++++++++++++++++------------------ src/slicerworker.js | 1 + src/utils.js | 57 ++++++++++++++++++++++++- webworker/worker.js | 3 +- webworker_test.html | 32 ++++++++------ 7 files changed, 205 insertions(+), 88 deletions(-) diff --git a/slice_test.html b/slice_test.html index 8d2641f..e0cc28c 100644 --- a/slice_test.html +++ b/slice_test.html @@ -37,7 +37,7 @@ function init () { var loader = new THREE.STLLoader(); loader.load("models/dom.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.TorusGeometry(20, 10, 30, 30); /* diff --git a/src/gcode.js b/src/gcode.js index 24795d0..f1e8ebc 100644 --- a/src/gcode.js +++ b/src/gcode.js @@ -9,12 +9,32 @@ D3D.GCode = function () { "use strict"; + this.current = {}; + this.extruder = 0.0; this.bottom = true; this.isRetracted = false; + this.isFanOn = false; this.gcode = []; this.nozzlePosition = new THREE.Vector2(0, 0); }; +D3D.GCode.prototype.addGCode = function (command) { + "use strict"; + + var str = []; + + for (var i in command) { + if (this.current[i] !== command[i] || i === "G") { + str.push(i + command[i]); + this.current[i] = command[i]; + } + } + + str = str.join(" "); + if (str.length > 0) { + this.gcode.push(str); + } +}; D3D.GCode.prototype.setSettings = function (printer) { "use strict"; @@ -22,10 +42,33 @@ D3D.GCode.prototype.setSettings = function (printer) { return this; }; -D3D.GCode.prototype.turnOnFan = function () { +D3D.GCode.prototype.turnFanOn = function (fanSpeed) { "use strict"; - this.gcode.push("M106"); + this.isFanOn = true; + + var gcode = { + "M": 106 + }; + + if (fanSpeed !== undefined) { + gcode["S"] = fanSpeed; + } + + this.addGCode(gcode); + + return this; +}; +D3D.GCode.prototype.turnFanOff = function () { + "use strict"; + + this.isFanOn = false; + + this.addGCode({ + "M": 107 + }); + + return this; }; D3D.GCode.prototype.moveTo = function (extrude, x, y, layer) { "use strict"; @@ -58,30 +101,27 @@ D3D.GCode.prototype.moveTo = function (extrude, x, y, layer) { var filamentSurfaceArea = Math.pow((filamentThickness/2), 2) * Math.PI; this.extruder += lineLength * nozzleDiameter * layerHeight / filamentSurfaceArea * flowRate; - this.gcode.push( - "G1" + - " X" + x.toFixed(3) + - " Y" + y.toFixed(3) + - ((z !== this.lastZ) ? (" Z" + z.toFixed(3)) : "") + - ((speed !== this.lastSpeed) ? (" F" + speed.toFixed(3)) : "") + - " E" + this.extruder.toFixed(3) - ); + this.addGCode({ + "G": 1, + "X": x.toFixed(3), "Y": y.toFixed(3), "Z": z.toFixed(3), + "F": speed.toFixed(3), + "E": this.extruder.toFixed(3) + }); } else { var speed = travelSpeed * 60; - this.gcode.push( - "G0" + - " X" + x.toFixed(3) + " Y" + y.toFixed(3) + " Z" + z + - " F" + speed.toFixed(3) - ); + this.addGCode.({ + "G": 0, + "X": x.toFixed(3), "Y": y.toFixed(3), "Z": z.toFixed(3), + "F": speed.toFixed(3) + }); } - this.lastSpeed = speed; - this.lastZ = z; - this.nozzlePosition = new THREE.Vector2(x, y); + + return this; }; D3D.GCode.prototype.unRetract = function () { "use strict"; @@ -96,12 +136,14 @@ D3D.GCode.prototype.unRetract = function () { var speed = retractionSpeed * 60; if (this.extruder > retractionMinDistance && retractionEnabled) { - this.gcode.push( - "G0" + - " E" + this.extruder.toFixed(3) + - " F" + (speed * 60).toFixed(3) - ); + this.addGCode({ + "G": 0, + "E": this.extruder.toFixed(3), + "F": speed.toFixed(3) + }); } + + return this; }; D3D.GCode.prototype.retract = function () { "use strict"; @@ -116,16 +158,16 @@ D3D.GCode.prototype.retract = function () { var speed = retractionSpeed * 60; if (this.extruder > retractionMinDistance && retractionEnabled) { - this.gcode.push( - "G0" + - " E" + (this.extruder - retractionAmount).toFixed(3) + - " F" + speed.toFixed(3) - ); + this.addGCode({ + "G": 0, + "E": (this.extruder - retractionAmount).toFixed(3), + "F": speed.toFixed(3) + }); } - this.lastSpeed = speed; + return this; }; -D3D.GCode.prototype.getFinal = function () { +D3D.GCode.prototype.getGCode = function () { "use strict"; return this.settings.getStartCode().concat(this.gcode, this.settings.getEndCode()); diff --git a/src/slicer.js b/src/slicer.js index d2372da..73cf1e7 100644 --- a/src/slicer.js +++ b/src/slicer.js @@ -24,26 +24,23 @@ D3D.Slicer.prototype.setMesh = function (geometry, matrix) { geometry = new THREE.Geometry().fromBufferGeometry(geometry); } - //remove duplicate vertices; + //apply mesh matrix on geometry; + geometry.applyMatrix(matrix); + geometry.mergeVertices(); + geometry.computeFaceNormals(); + geometry.computeBoundingBox(); + /* - for (var i = 0; i < geometry.vertices.length; i ++) { - var vertexA = geometry.vertices[i]; + for (var i = 0; i < geometry.faces.length; i ++) { + var face = geometry.faces[i]; + var normal = face.normal; - for (var j = i + 1; j < geometry.vertices.length; j ++) { - var vertexB = geometry.vertices[j]; - - if (vertexA.equals(vertexB)) { - geometry.vertices[j] = vertexA; - } + if (normal.x === 0 && normal.y === 0 && normal.z === 0) { + geometry.faces.splice(i, 1); + i --; } } */ - geometry.mergeVertices(); - - //apply mesh matrix on geometry; - geometry.applyMatrix(matrix); - geometry.computeFaceNormals(); - geometry.computeBoundingBox(); this.geometry = geometry; @@ -77,9 +74,7 @@ D3D.Slicer.prototype.createLines = function () { var self = this; function addLine (a, b) { - - //think lookup can only be b_a, a_b is only possible when face is flipped - var index = lineLookup[b + "_" + a] || lineLookup[a + "_" + b]; + var index = lineLookup[b + "_" + a]; if (index === undefined) { index = self.lines.length; @@ -123,6 +118,7 @@ D3D.Slicer.prototype.createLines = function () { }; D3D.Slicer.prototype.slice = function (layerHeight, height) { "use strict"; + var numLayers = height / layerHeight; var layersIntersections = []; @@ -133,7 +129,7 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) { var max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight); for (var layerIndex = min; layerIndex <= max; layerIndex ++) { - if (layerIndex >= 0 && layerIndex < height / layerHeight) { + if (layerIndex >= 0 && layerIndex < numLayers) { if (layersIntersections[layerIndex] === undefined) { layersIntersections[layerIndex] = []; } @@ -151,6 +147,7 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) { var y = layer * layerHeight; var intersections = []; + var log = []; for (var i = 0; i < layerIntersections.length; i ++) { var index = layerIntersections[i]; var line = this.lines[index].line; @@ -164,8 +161,14 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) { var x = line.end.x * alpha + line.start.x * (1 - alpha); var z = line.end.z * alpha + line.start.z * (1 - alpha); } + intersections[index] = new THREE.Vector2(z, x); + 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 slice = []; @@ -179,24 +182,33 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) { var intersection = intersections[index]; shape.push({X: intersection.x, Y: intersection.y}); - done.push(index); - var connects = this.lines[index].connects; var faceNormals = this.lines[index].normals; for (var j = 0; j < connects.length; j ++) { index = connects[j]; - if (intersections[index] && done.indexOf(index) === -1) { + if (intersections[index] !== undefined && done.indexOf(index) === -1) { + done.push(index); + var a = new THREE.Vector2(intersection.x, intersection.y); var b = intersections[index]; - var normal = a.sub(b).normal().normalize(); - var faceNormal = faceNormals[Math.floor(j/2)]; - if (normal.dot(faceNormal) > 0) { - break; + if (a.distanceTo(b) === 0) { + connects = connects.concat(this.lines[index].connects); + faceNormals = faceNormals.concat(this.lines[index].normals); + index = -1; } else { - index = -1; + var normal = a.sub(b).normal().normalize(); + var faceNormal = faceNormals[Math.floor(j/2)]; + + if (normal.dot(faceNormal) >= 0) { + //if (true) { + break; + } + else { + index = -1; + } } } else { @@ -234,6 +246,7 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) { } } + var layerParts = []; for (var i = 0; i < slice.length; i ++) { @@ -265,7 +278,6 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) { this.progress.sliceLayer = layer; this.updateProgress(); } - return slices; }; D3D.Slicer.prototype.slicesToData = function (slices, printer) { @@ -405,7 +417,7 @@ D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) { return paths; }; /* -D3D.Slicer.prototype.dataToGcode = function (data, printer) { +D3D.Slicer.prototype.dataToGCode = function (data, printer) { "use strict"; var layerHeight = printer.config["printer.layerHeight"]; @@ -423,7 +435,7 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { var retractionMinDistance = printer.config["printer.retraction.minDistance"]; var retractionAmount = printer.config["printer.retraction.amount"]; - function sliceToGcode (path) { + function sliceToGCode (path) { var gcode = []; for (var i = 0; i < path.length; i ++) { @@ -507,9 +519,9 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { 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)); + gcode = gcode.concat(sliceToGCode(layerPart.outerLayer)); + gcode = gcode.concat(sliceToGCode(layerPart.insets)); + gcode = gcode.concat(sliceToGCode(layerPart.fill)); } this.progress.gcodeLayer = layer; @@ -521,12 +533,12 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { return gcode; }; */ -D3D.Slicer.prototype.dataToGcode = function (data, printer) { +D3D.Slicer.prototype.dataToGCode = function (data, printer) { "use strict"; var gcode = new D3D.GCode().setSettings(printer); - function sliceToGcode (path, retract, unRetract) { + function sliceToGCode (path, retract, unRetract) { for (var i = 0; i < path.length; i ++) { var shape = path[i]; @@ -557,25 +569,25 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { var slice = data[layer]; if (layer === 1) { - gcode.turnOnFan(); + gcode.turnFanOn(); gcode.bottom = false; } for (var i = 0; i < slice.length; i ++) { var layerPart = slice[i]; - sliceToGcode(layerPart.outerLayer, false, true); - sliceToGcode(layerPart.insets, false, false); - sliceToGcode(layerPart.fill, true, false); + sliceToGCode(layerPart.outerLayer, false, true); + sliceToGCode(layerPart.insets, false, false); + sliceToGCode(layerPart.fill, true, false); } this.progress.gcodeLayer = layer; this.updateProgress(); } - return gcode.getFinal(); + return gcode.getGCode(); }; -D3D.Slicer.prototype.getGcode = function (printer) { +D3D.Slicer.prototype.getGCode = function (printer) { "use strict"; var layerHeight = printer.config["printer.layerHeight"]; @@ -597,7 +609,7 @@ D3D.Slicer.prototype.getGcode = function (printer) { console.log("Data: " + (end - start) + "ms"); start = new Date().getTime(); - var gcode = this.dataToGcode(data, printer); + var gcode = this.dataToGCode(data, printer); end = new Date().getTime(); console.log("Gcode: " + (end - start) + "ms"); diff --git a/src/slicerworker.js b/src/slicerworker.js index 7135383..c6980c1 100644 --- a/src/slicerworker.js +++ b/src/slicerworker.js @@ -7,6 +7,7 @@ D3D.SlicerWorker = function () { this.worker.addEventListener('message', function (event) { switch (event.data['cmd']) { case 'PROGRESS': + if (scope.onprogress !== undefined) { var progress = event.data['progress']; diff --git a/src/utils.js b/src/utils.js index 9d5efd2..d35f75b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,7 +1,7 @@ /****************************************************** * * Utils -* requires jQuery, Three.js +* dependices Three.js * ******************************************************/ @@ -14,6 +14,37 @@ var D3D = { function sendAPI (url, data, callback) { "use strict"; + /* + var form = new FormData(); + + for (var i in data) { + form.append(i, JSON.stringify(data[i])); + } + + var request = new XMLHttpRequest(); + request.open('POST', url, true); + request.send(data); + request.onreadystatechange = function () { + if (request.readyState === 4 && request.status === 200) { + var response = JSON.parse(request.responseText); + + if (response.status === "success") { + if (callback !== undefined) { + callback(response.data); + } + } + else { + console.warn(response.msg); + } + } + else { + console.log(request); + console.warn("Failed connecting to " + url); + //sendAPI(url, data, callback); + } + }; + */ + $.ajax({ url: url, type: "POST", @@ -38,7 +69,30 @@ function sendAPI (url, data, callback) { function getAPI (url, callback) { "use strict"; + /* + var request = new XMLHttpRequest(); + request.open('GET', url, true); + request.send(); + request.onreadystatechange = function () { + if (request.readyState === 4 && request.status === 200) { + var response = JSON.parse(request.responseText); + if (response.status === "success") { + if (callback !== undefined) { + callback(response.data); + } + } + else { + console.warn(response.msg); + } + } + else { + console.warn("Failed connecting to " + url); + sendAPI(url, callback); + } + };*/ + + $.ajax({ url: url, dataType: "json", @@ -57,6 +111,7 @@ function getAPI (url, callback) { console.warn("Failed connecting to " + url); getAPI(url, callback); }); + } function loadSettings (url, callback) { diff --git a/webworker/worker.js b/webworker/worker.js index 5742885..d603fff 100644 --- a/webworker/worker.js +++ b/webworker/worker.js @@ -16,7 +16,6 @@ slicer.onProgress = function (progress) { "progress": progress }); - //console.log(progress); }; self.addEventListener("message", function (event) { @@ -42,7 +41,7 @@ self.addEventListener("message", function (event) { break; case "SLICE": - var gcode = slicer.getGcode(printer); + var gcode = slicer.getGCode(printer); self.postMessage({ "cmd": "GCODE", diff --git a/webworker_test.html b/webworker_test.html index 9c2a538..71e9ce6 100644 --- a/webworker_test.html +++ b/webworker_test.html @@ -16,7 +16,7 @@ canvas {border: 1px solid black;} #progress {height: 20px; width: 200px; border: 1px solid black; overflow: hidden;} #progress_bar {height: 20px; background-color: lightblue; width: 0%;} .block {border: 1px solid black; width: 400px; height: 400px; display: inline-block;} -#start_print {display: none;} +#start_print, #download {display: none;} @@ -33,8 +33,9 @@ canvas {border: 1px solid black;}

Total Lines:

Batches To Send:

- + +