/** * User: hudbrog (hudbrog@gmail.com) * Date: 10/24/12 * Time: 12:18 PM */ var gcode; var firstReport; var z_heights = {}; var model = []; var gCodeOptions = { sortLayers: false, purgeEmptyLayers: true, analyzeModel: false }; var max = {x: undefined, y: undefined, z: undefined}; var min = {x: undefined, y: undefined, z: undefined}; var modelSize = {x: undefined, y: undefined, z: undefined}; var filamentByLayer = {}; var totalFilament=0; var printTime=0; var printTimeByLayer = {}; var layerHeight=0; var layerCnt = 0; var speeds = {extrude: [], retract: [], move: []}; var speedsByLayer = {extrude: {}, retract: {}, move: {}}; var sendLayerToParent = function(layerNum, z, progress){ self.postMessage({ "cmd": "returnLayer", "msg": { cmds: model[layerNum], layerNum: layerNum, zHeightObject: {zValue: z, layer: z_heights[z]}, isEmpty: false, progress: progress } }); }; var sendMultiLayerToParent = function(layerNum, z, progress){ var tmpModel = []; var tmpZHeight = {}; for(var i=0;iparseFloat(cmds[j].x)?parseFloat(max.x):parseFloat(cmds[j].x); max.x = parseFloat(max.x)>parseFloat(cmds[j].prevX)?parseFloat(max.x):parseFloat(cmds[j].prevX); min.x = parseFloat(min.x)parseFloat(cmds[j].y)?parseFloat(max.y):parseFloat(cmds[j].y); max.y = parseFloat(max.y)>parseFloat(cmds[j].prevY)?parseFloat(max.y):parseFloat(cmds[j].prevY); min.y = parseFloat(min.y)parseFloat(cmds[j].prevZ)?parseFloat(max.z):parseFloat(cmds[j].prevZ); min.z = parseFloat(min.z)=tmp2?tmp1:tmp2; }else if(cmds[j].retract!==0){ printTimeAdd = Math.abs(parseFloat(cmds[j].extrusion)/(cmds[j].speed/60)); } printTime += printTimeAdd; if(typeof(printTimeByLayer[cmds[j].prevZ])==='undefined'){printTimeByLayer[cmds[j].prevZ]=0;} printTimeByLayer[cmds[j].prevZ] += printTimeAdd; if(cmds[j].extrude&&cmds[j].retract===0){ type = 'extrude'; }else if(cmds[j].retract!==0){ type = 'retract'; }else if(!cmds[j].extrude&&cmds[j].retract===0){ type = 'move'; // if(cmds[j].prevZ == '17.1'){ // self.postMessage({cmd: 'Got speed ' + cmds[j].speed + 'with line ' + cmds[j].gcodeLine}); // } }else { self.postMessage({cmd: 'unknown type of move'}); type = 'unknown'; } speedIndex = speeds[type].indexOf(cmds[j].speed); if (speedIndex === -1) { speeds[type].push(cmds[j].speed); speedIndex = speeds[type].indexOf(cmds[j].speed); } if(typeof(speedsByLayer[type][cmds[j].prevZ]) === 'undefined'){ speedsByLayer[type][cmds[j].prevZ] = []; } if(speedsByLayer[type][cmds[j].prevZ].indexOf(cmds[j].speed) === -1){ speedsByLayer[type][cmds[j].prevZ][speedIndex] = cmds[j].speed; } } sendSizeProgress(i/model.length*100); } purgeLayers(); modelSize.x = Math.abs(max.x - min.x); modelSize.y = Math.abs(max.y - min.y); modelSize.z = Math.abs(max.z - min.z); layerHeight = (max.z-min.z)/(layerCnt-1); sendAnalyzeDone(); }; var doParse = function(){ var argChar, numSlice; model=[]; var sendLayer = undefined; var sendLayerZ = 0; var sendMultiLayer = []; var sendMultiLayerZ = []; var lastSend = 0; // console.time("parseGCode timer"); var reg = new RegExp(/^(?:G0|G1)\s/i); var comment = new RegExp() var j, layer= 0, extrude=false, prevRetract= 0, retract=0, x, y, z=0, f, prevZ=0, prevX, prevY,lastF=4000, prev_extrude = {a: undefined, b: undefined, c: undefined, e: undefined, abs: undefined}, extrudeRelative=false; var dcExtrude=false; var assumeNonDC = false; for(var i=0;i0; if(prev_extrude["abs"]<0){ prevRetract = -1; retract = -1; } else if(prev_extrude["abs"]==0){ retract = 0; }else if(prev_extrude["abs"]>0&&prevRetract < 0){ prevRetract = 0; retract = 1; } else { retract = 0; } prev_extrude[argChar] = numSlice; break; case 'f': numSlice = args[j].slice(1); lastF = numSlice; break; default: break; } } if(dcExtrude&&!assumeNonDC){ extrude = true; prev_extrude["abs"] = Math.sqrt((prevX-x)*(prevX-x)+(prevY-y)*(prevY-y)); } if(!model[layer])model[layer]=[]; if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage}; //{x: x, y: y, z: z, extrude: extrude, retract: retract, noMove: false, extrusion: (extrude||retract)?prev_extrude["abs"]:0, prevX: prevX, prevY: prevY, prevZ: prevZ, speed: lastF, gcodeLine: i}; if(typeof(x) !== 'undefined') prevX = x; if(typeof(y) !== 'undefined') prevY = y; } else if(line.match(/^(?:M82)/i)){ extrudeRelative = false; }else if(line.match(/^(?:G91)/i)){ extrudeRelative=true; }else if(line.match(/^(?:G90)/i)){ extrudeRelative=false; }else if(line.match(/^(?:M83)/i)){ extrudeRelative=true; }else if(line.match(/^(?:M101)/i)){ dcExtrude=true; }else if(line.match(/^(?:M103)/i)){ dcExtrude=false; }else if(line.match(/^(?:G92)/i)){ var args = line.split(/\s/); for(j=0;j gcode.length*0.02 && sendMultiLayer.length != 0){ lastSend = i; sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100); sendMultiLayer = []; sendMultiLayerZ = []; } sendMultiLayer[sendMultiLayer.length] = sendLayer; sendMultiLayerZ[sendMultiLayerZ.length] = sendLayerZ; sendLayer = undefined; sendLayerZ = undefined; } } sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100); }; var parseGCode = function(message){ gcode = message.gcode; firstReport = message.options.firstReport; doParse(); gcode = []; self.postMessage({ "cmd": "returnModel", "msg": { // model: model } }); }; var runAnalyze = function(message){ analyzeModel(); model = []; z_heights = []; gcode = undefined; firstReport = undefined; z_heights = {}; model = []; max = {x: undefined, y: undefined, z: undefined}; min = {x: undefined, y: undefined, z: undefined}; modelSize = {x: undefined, y: undefined, z: undefined}; filamentByLayer = {}; totalFilament=0; printTime=0; printTimeByLayer = {}; layerHeight=0; layerCnt = 0; speeds = {extrude: [], retract: [], move: []}; speedsByLayer = {extrude: {}, retract: {}, move: {}}; }; var setOption = function(options){ for(var opt in options){ gCodeOptions[opt] = options[opt]; } }; onmessage = function (e){ var data = e.data; // for some reason firefox doesn't garbage collect when something inside closures is deleted, so we delete and recreate whole object eaech time switch (data.cmd) { case 'parseGCode': parseGCode(data.msg); break; case 'setOption': setOption(data.msg); break; case 'analyzeModel': runAnalyze(data.msg); break; default: self.postMessage('Unknown command: ' + data.msg); } };