From f0d865ad066ede776012526135255f20e3df0cd2 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sat, 5 Nov 2016 10:29:36 +0100 Subject: [PATCH 01/34] docs(README): tweaks & minor improvements to readme --- README.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 19ebdd1..e517a54 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,43 @@ [![GitHub version](https://badge.fury.io/gh/LaserWeb%2Flw-gcode-parser.svg)](https://badge.fury.io/gh/LaserWeb%2Flw-gcode-parser) +## Table of Contents -## General information +- [Background](#background) +- [Installation](#installation) +- [Usage](#usage) +- [API](#api) +- [Contribute](#contribute) +- [License](#license) + + +## Background + +To a large extent based on John Lauer's & contributors work + +##Installation -To a large extent based on John Lauer's & contributors work ## Usage -## TODO +## API +## Contribute + +PRs accepted. + +Small note: If editing the Readme, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. + ## LICENSE [The MIT License (MIT)](https://github.com/LaserWeb/lw-gcode-parser/blob/master/LICENSE) - - - +[![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) + [![Build Status](https://travis-ci.org/LaserWeb/lw-gcode-parser.svg?branch=master)](https://travis-ci.org/LaserWeb/lw-gcode-parser) [![Dependency Status](https://david-dm.org/LaserWeb/lw-gcode-parser.svg)](https://david-dm.org/LaserWeb/lw-gcode-parser) [![devDependency Status](https://david-dm.org/LaserWeb/lw-gcode-parser/dev-status.svg)](https://david-dm.org/LaserWeb/lw-gcode-parser#info=devDependencies) From 7452ef21090485e50a70ff8d0057d78ed3c0f3dc Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sat, 5 Nov 2016 10:30:03 +0100 Subject: [PATCH 02/34] refactor(): spliting up old code base into to more manageable chunks (wip) --- src/gcodeHandlers.js | 300 +++++++++++++++ src/geometryUtils.js | 30 ++ src/legacy/gcode-parser-breakapart.js | 154 ++++++++ src/objFromGcode.js | 165 ++++++++ src/parse.js | 47 +++ src/parseFunctions.js | 525 ++++++++++++++++++++++++++ src/parseLine.js | 128 +++++++ src/utils.js | 7 + 8 files changed, 1356 insertions(+) create mode 100644 src/gcodeHandlers.js create mode 100644 src/geometryUtils.js create mode 100644 src/legacy/gcode-parser-breakapart.js create mode 100644 src/objFromGcode.js create mode 100644 src/parse.js create mode 100644 src/parseFunctions.js create mode 100644 src/parseLine.js create mode 100644 src/utils.js diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js new file mode 100644 index 0000000..a86b17e --- /dev/null +++ b/src/gcodeHandlers.js @@ -0,0 +1,300 @@ +const handlers = { + // set the g92 offsets for the parser - defaults to no offset + // When doing CNC, generally G0 just moves to a new location + // as fast as possible which means no milling or extruding is happening in G0. + // So, let's color it uniquely to indicate it's just a toolhead move. + G0: function (args, indx) { + var newLine = { + x: args.x !== undefined ? cofg.absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, + y: args.y !== undefined ? cofg.absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, + z: args.z !== undefined ? cofg.absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, + a: args.a !== undefined ? cofg.absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, + e: args.e !== undefined ? cofg.absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + f: args.f !== undefined ? args.f : lastLine.f, + s: 100, + } + newLine.g0 = true + cofg.addLineSegment(lastLine, newLine) + lastLine = newLine + }, + G1: function (args, indx) { + // Example: G1 Z1.0 F3000 + // G1 X99.9948 Y80.0611 Z15.0 F1500.0 E981.64869 + // G1 E104.25841 F1800.0 + // Go in a straight line from the current (X, Y) point + // to the point (90.6, 13.8), extruding material as the move + // happens from the current extruded length to a length of + // 22.4 mm. + + var newLine = { + x: args.x !== undefined ? cofg.absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, + y: args.y !== undefined ? cofg.absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, + z: args.z !== undefined ? cofg.absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, + a: args.a !== undefined ? cofg.absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, + e: args.e !== undefined ? cofg.absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + f: args.f !== undefined ? args.f : lastLine.f, + s: args.s !== undefined ? args.s : lastLine.s, + t: args.t !== undefined ? args.t : lastLine.t, + } + /* layer change detection is or made by watching Z, it's made by + watching when we extrude at a new Z position */ + if (cofg.delta(lastLine.e, newLine.e) > 0) { + newLine.extruding = cofg.delta(lastLine.e, newLine.e) > 0 + if (layer == undefined || newLine.z != layer.z) cofg.newLayer(newLine) + } + newLine.g1 = true + cofg.addLineSegment(lastLine, newLine) + lastLine = newLine + }, + G2: function (args, indx, gcp) { + // this is an arc move from lastLine's xy to the new xy. we'll + // show it as a light gray line, but we'll also sub-render the + // arc itself by figuring out the sub-segments + + args.plane = plane // set the plane for this command to whatever the current plane is + + var newLine = { + x: args.x !== undefined ? cofg.absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, + y: args.y !== undefined ? cofg.absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, + z: args.z !== undefined ? cofg.absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, + a: args.a !== undefined ? cofg.absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, + e: args.e !== undefined ? cofg.absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + f: args.f !== undefined ? args.f : lastLine.f, + s: args.s !== undefined ? args.s : lastLine.s, + t: args.t !== undefined ? args.t : lastLine.t, + arci: args.i ? args.i : null, + arcj: args.j ? args.j : null, + arck: args.k ? args.k : null, + arcr: args.r ? args.r : null, + } + newLine.arc = true + newLine.clockwise = true + if (args.clockwise === false) newLine.clockwise = args.clockwise + cofg.addSegment(lastLine, newLine, args) + lastLine = newLine + }, + G3: function (args, indx, gcp) { + // this is an arc move from lastLine's xy to the new xy. same + // as G2 but reverse + args.arc = true + args.clockwise = false + args.plane = plane // set the plane for this command to whatever the current plane is + + var newLine = { + x: args.x !== undefined ? cofg.absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, + y: args.y !== undefined ? cofg.absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, + z: args.z !== undefined ? cofg.absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, + a: args.a !== undefined ? cofg.absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, + e: args.e !== undefined ? cofg.absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + f: args.f !== undefined ? args.f : lastLine.f, + s: args.s !== undefined ? args.s : lastLine.s, + t: args.t !== undefined ? args.t : lastLine.t, + arci: args.i ? args.i : null, + arcj: args.j ? args.j : null, + arck: args.k ? args.k : null, + arcr: args.r ? args.r : null, + } + newLine.arc = true + newLine.clockwise = true + if (args.clockwise === false) newLine.clockwise = args.clockwise + cofg.addSegment(lastLine, newLine, args) + lastLine = newLine + }, + + dirG7: 0, + + G7: function (args, indx) { + // Example: G7 L68 D//////sljasflsfagdxsd,.df9078rhfnxm (68 of em) + // G7 $1 L4 DAAA= + // G7 $0 L4 D2312 + // Move right (if $1) or left (if $0) 51 steps (from L68) + // (the number of steps is found when decoding the data) + // and burn the laser with the intensity in the base64-encoded + // data in D. Data in D is 51 base64-encoded bytes with grayscale + // intensity. When base64-encoded the string becomes 68 bytes long. + // + // SpotSize comes from a previous M649 S100 R0.1 + // where S is intensity (100 is max) and R gives spotsize in mm. + // Actual laser power is then D-value * S-value in every pixel + // A direction change with $0/$1 gives a spotSize long movement in Y + // for the next row. + + var buf = atob(args.d) + + if (typeof args.dollar !== 'undefined') { // Move Y, change direction + this.dirG7 = args.dollar + var newLine = { + x: lastLine.x, + y: lastLine.y + cofg.spotSizeG7, + z: lastLine.z, + a: lastLine.a, + e: lastLine.e, + f: lastLine.f, + s: 100, + t: lastLine.t, + } + newLine.g0 = true + cofg.addLineSegment(lastLine, newLine) + lastLine = newLine + } + for (var i = 0; i < buf.length; i++) { // Process a base64-encoded chunk + var intensity = 255 - buf.charCodeAt(i); // 255 - 0 + var newLine = { + x: lastLine.x + cofg.spotSizeG7 * (this.dirG7 == 1 ? 1 : -1), + y: lastLine.y, + z: lastLine.z, + a: lastLine.a, + e: lastLine.e, + f: lastLine.f, + s: intensity, + t: lastLine.t, + } + newLine.g7 = true + cofg.addLineSegment(lastLine, newLine) + lastLine = newLine + } + }, + + G17: function (args) { + console.log('SETTING XY PLANE') + plane = 'G17' + cofg.addFakeSegment(args) + }, + + G18: function (args) { + console.log('SETTING XZ PLANE') + plane = 'G18' + cofg.addFakeSegment(args) + }, + + G19: function (args) { + console.log('SETTING YZ PLANE') + plane = 'G19' + cofg.addFakeSegment(args) + }, + + G20: function (args) { + // G21: Set Units to Inches + // We don't really have to do anything since 3d viewer is unit agnostic + // However, we need to set a global property so the trinket decorations + // like toolhead, axes, grid, and extent labels are scaled correctly + // later on when they are drawn after the gcode is rendered + // console.log("SETTING UNITS TO INCHES!!!") + cofg.isUnitsMm = false // false means inches cuz default is mm + cofg.addFakeSegment(args) + }, + + G21: function (args) { + // G21: Set Units to Millimeters + // Example: G21 + // Units from now on are in millimeters. (This is the RepRap default.) + // console.log("SETTING UNITS TO MM!!!") + cofg.isUnitsMm = true // true means mm + cofg.addFakeSegment(args) + }, + + G73: function (args, indx, gcp) { + // peck drilling. just treat as g1 + console.log('G73 gcp:', gcp) + gcp.handlers.G1(args) + }, + G90: function (args) { + // G90: Set to Absolute Positioning + // Example: G90 + // All coordinates from now on are absolute relative to the + // origin of the machine. (This is the RepRap default.) + + relative = false + cofg.addFakeSegment(args) + }, + + G91: function (args) { + // G91: Set to Relative Positioning + // Example: G91 + // All coordinates from now on are relative to the last position. + + // TODO! + relative = true + cofg.addFakeSegment(args) + }, + + G92: function (args) { // E0 + // G92: Set Position + // Example: G92 E0 + // Allows programming of absolute zero point, by reseting the + // current position to the values specified. This would set the + // machine's X coordinate to 10, and the extrude coordinate to 90. + // No physical motion will occur. + + // TODO: Only support E0 + var newLine = lastLine + + cofg.offsetG92.x = (args.x !== undefined ? (args.x === 0 ? newLine.x : newLine.x - args.x) : 0) + cofg.offsetG92.y = (args.y !== undefined ? (args.y === 0 ? newLine.y : newLine.y - args.y) : 0) + cofg.offsetG92.z = (args.z !== undefined ? (args.z === 0 ? newLine.z : newLine.z - args.z) : 0) + cofg.offsetG92.a = (args.a !== undefined ? (args.a === 0 ? newLine.a : newLine.a - args.a) : 0) + cofg.offsetG92.e = (args.e !== undefined ? (args.e === 0 ? newLine.e : newLine.e - args.e) : 0) + + // newLine.x = args.x !== undefined ? args.x + newLine.x : newLine.x + // newLine.y = args.y !== undefined ? args.y + newLine.y : newLine.y + // newLine.z = args.z !== undefined ? args.z + newLine.z : newLine.z + // newLine.e = args.e !== undefined ? args.e + newLine.e : newLine.e + + // console.log("G92", lastLine, newLine, args, cofg.offsetG92) + + // lastLine = newLine + cofg.addFakeSegment(args) + }, + M30: function (args) { + cofg.addFakeSegment(args) + }, + M82: function (args) { + // M82: Set E codes absolute (default) + // Descriped in Sprintrun source code. + + // No-op, so long as M83 is not supported. + cofg.addFakeSegment(args) + }, + + M84: function (args) { + // M84: Stop idle hold + // Example: M84 + // Stop the idle hold on all axis and extruder. In some cases the + // idle hold causes annoying noises, which can be stopped by + // disabling the hold. Be aware that by disabling idle hold during + // printing, you will get quality issues. This is recommended only + // in between or after printjobs. + + // No-op + cofg.addFakeSegment(args) + }, + + M649: function (args) { + // M649: Laser options for Marlin + // M649 S R B2 + // Intensity = lasermultiply? + if (typeof args.r !== 'undefined') { cofg.spotSizeG7 = args.r;} + }, + + // Dual Head 3D Printing Support + T0: function (args) { + // console.log('Found Tool: ', args) + lastLine.t = 0 + cofg.addFakeSegment(args) + }, + + T1: function (args) { + // console.log('Found Tool: ', args) + lastLine.t = 1 + cofg.addFakeSegment(args) + }, + + 'default': function (args, info) { + // if (!args.isComment) + // console.log('Unknown command:', args.cmd, args, info) + cofg.addFakeSegment(args) + }, +}) +// console.log("Just before parser.parse: "+ gcode) +parser.parse(gcode) +} diff --git a/src/geometryUtils.js b/src/geometryUtils.js new file mode 100644 index 0000000..1dd01c3 --- /dev/null +++ b/src/geometryUtils.js @@ -0,0 +1,30 @@ + +function convertLineGeometryToBufferGeometry (lineGeometry, color) { + var positions = new Float32Array(lineGeometry.vertices.length * 3) + var colors = new Float32Array(lineGeometry.vertices.length * 3) + + var geometry = new THREE.BufferGeometry() + + for (var i = 0; i < lineGeometry.vertices.length; i++) { + var x = lineGeometry.vertices[i].x + var y = lineGeometry.vertices[i].y + var z = lineGeometry.vertices[i].z + + // positions + positions[ i * 3 ] = x + positions[ i * 3 + 1 ] = y + positions[ i * 3 + 2 ] = z + + // colors + colors[ i * 3 ] = color.r + colors[ i * 3 + 1 ] = color.g + colors[ i * 3 + 2 ] = color.b + } + + geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3)) + geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3)) + + geometry.computeBoundingSphere() + + return geometry +} diff --git a/src/legacy/gcode-parser-breakapart.js b/src/legacy/gcode-parser-breakapart.js new file mode 100644 index 0000000..1516647 --- /dev/null +++ b/src/legacy/gcode-parser-breakapart.js @@ -0,0 +1,154 @@ +/* + + AUTHOR: John Lauer + -- S??? (laser intensity) Parameter Handling added by AUTHOR: Peter van der Walt + v19/6/2016 + +*/ + +// This is a simplified and updated version of http://gcode.joewalnes.com/ that works with the latest version of Three.js (v68). +// Updated with code from http://chilipeppr.com/tinyg's 3D viewer to support more CNC type Gcode +var totaltimemax = '' +totaltimemax = 0 + +var lineObjects = new THREE.Object3D() +lineObjects.name = 'LineObjects' + +function GCodeParser (handlers) { + handlers = handlers || {} + + lastArgs = {cmd: null} + lastFeedrate = null + isUnitsMm = true +} +colorG0: 0x00ff00 +colorG1: 0x0000ff +colorG2: 0x999900 + + + + + var bufSize = 10000; // Arbitrary - play around with! + var lineObject = {active: false, + vertexBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments + colorBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments + nLines: 0, + } + var material = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors, + opacity: 0.8, + transparent: true, + linewidth: 1, + }) + + + + + totalDist = 0 + totalTime = 0 + + var relative = false + var tool = null + + + + + var cofg = this + + //parser = new GCodeParser( + +function drawobject () { + var newObject = false + // console.log("INSIDE DRAWOBJECT") + // set what units we're using in the gcode + isUnitsMm = parser.isUnitsMm + + newObject = new THREE.Object3D() + newObject.name = 'newObject' + + // old approach of monolithic line segment + for (var lid in layers3d) { + // console.log('processing Layer ' + lid) + var layer = layers3d[lid] + for (var tid in layer.type) { + var type = layer.type[tid] + var bufferGeo = convertLineGeometryToBufferGeometry(type.geometry, type.color) + newObject.add(new THREE.Line(bufferGeo, type.material, THREE.LinePieces)) + } + } + newObject.add(new THREE.Object3D()) + // XY PLANE + extraObjects['G17'].forEach(function (obj) { + var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) + newObject.add(new THREE.Line(bufferGeo, obj.material)) + }, this) + // XZ PLANE + extraObjects['G18'].forEach(function (obj) { + // buffered approach + var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) + var tmp = new THREE.Line(bufferGeo, obj.material) + tmp.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2) + newObject.add(tmp) + }, this) + // YZ PLANE + extraObjects['G19'].forEach(function (obj) { + // buffered approach + var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) + var tmp = new THREE.Line(bufferGeo, obj.material) + tmp.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2) + tmp.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2) + newObject.add(tmp) + }, this) + + // use new approach of building 3d object where each + // gcode line is its own segment with its own userData + // object = new3dObj + + // Center + var scale = 1; // TODO: Auto size + + var center = new THREE.Vector3( + bbbox.min.x + ((bbbox.max.x - bbbox.min.x) / 2), + bbbox.min.y + ((bbbox.max.y - bbbox.min.y) / 2), + bbbox.min.z + ((bbbox.max.z - bbbox.min.z) / 2)) + + var center2 = new THREE.Vector3( + bbbox2.min.x + ((bbbox2.max.x - bbbox2.min.x) / 2), + bbbox2.min.y + ((bbbox2.max.y - bbbox2.min.y) / 2), + bbbox2.min.z + ((bbbox2.max.z - bbbox2.min.z) / 2)) + + var dX = bbbox2.max.x - bbbox2.min.x + var dY = bbbox2.max.y - bbbox2.min.y + var dZ = bbbox2.max.z - bbbox2.min.z + + function toTimeString (seconds) { + // return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0] + } + + console.log(totaltimemax + ' seconds estimated') + + // printLog('Estimated Job Time: '+totaltimemax, successcolor) + + printLog('Estimated Distance: ' + (totalDist / 1000).toFixed(1) + ' m', msgcolor, 'viewer') + $('#lasertimeqty').val((totalDist.toFixed(1)) / 10) + + if (fileParentGroup) { + var bbox2 = new THREE.Box3().setFromObject(fileParentGroup) + // console.log('bbox width: ', (bbox2.max.x - bbox2.min.x), 'height Y: ', (bbox2.max.y - bbox2.min.y) ) + width = (bbox2.max.x - bbox2.min.x) + height = (bbox2.max.y - bbox2.min.y) + $('#quoteresult').html('Job moves length: ' + totalDist.toFixed(1) + ' mm
Width: ' + width.toFixed(1) + ' mm
Height: ' + height.toFixed(1) + ' mm
Material: ' + ((width * height) / 1000).toFixed(3) + 'cm2') + $('#materialqty').val(((width * height) / 1000).toFixed(3)) + } else if (rastermesh) { + var bbox2 = new THREE.Box3().setFromObject(rastermesh) + // console.log('bbox width: ', (bbox2.max.x - bbox2.min.x), 'height Y: ', (bbox2.max.y - bbox2.min.y) ) + width = (bbox2.max.x - bbox2.min.x) + height = (bbox2.max.y - bbox2.min.y) + $('#quoteresult').html('Job moves length: ' + totalDist.toFixed(1) + ' mm
Width: ' + width.toFixed(1) + ' mm
Height: ' + height.toFixed(1) + ' mm
Material: ' + ((width * height) / 1000).toFixed(3) + 'cm2') + $('#materialqty').val(((width * height) / 1000).toFixed(3)) + } + + console.groupEnd() + return newObject + // console.groupEnd() + +} diff --git a/src/objFromGcode.js b/src/objFromGcode.js new file mode 100644 index 0000000..46414e9 --- /dev/null +++ b/src/objFromGcode.js @@ -0,0 +1,165 @@ +createObjectFromGCode = function (gcode, indxMax) { + console.group('Generating GCODE Preview') + + // console.group("Rendering GCODE Preview") + // debugger + // Credit goes to https://github.com/joewalnes/gcode-viewer + // for the initial inspiration and example code. + // + // GCode descriptions come from: + // http://reprap.org/wiki/G-code + // http://en.wikipedia.org/wiki/G-code + // SprintRun source code + + // these are extra Object3D elements added during + // the gcode rendering to attach to scene + this.extraObjects = [] + this.extraObjects['G17'] = [] + this.extraObjects['G18'] = [] + this.extraObjects['G19'] = [] + this.offsetG92 = {x: 0, y: 0, z: 0, a: 0, e: 0} + + var lastLine = { + x: 0, + y: 0, + z: 0, + a: 0, + e: 0, + f: 0, + feedrate: null, + extruding: false, + } + + // we have been using an approach where we just append + // each gcode move to one monolithic geometry. we + // are moving away from that idea and instead making each + // gcode move be it's own full-fledged line object with + // its own userData info + // G2/G3 moves are their own child of lots of lines so + // that even the simulator can follow along better + var new3dObj = new THREE.Group() + new3dObj.name = 'newobj' + plane = 'G17'; // set default plane to G17 - Assume G17 if no plane specified in gcode. + layers3d = [] + layer = undefined + lines = [] + totalDist = 0 + bbbox = { + min: { + x: 100000, + y: 100000, + z: 100000 + }, + max: { + x: -100000, + y: -100000, + z: -100000 + } + } + bbbox2 = { + min: { + x: 100000, + y: 100000, + z: 100000 + }, + max: { + x: -100000, + y: -100000, + z: -100000 + } + } + + newLayer = function (line) { + // console.log("layers3d:", layers3d, "layers3d.length", layers3d.length) + layer = { + type: {}, + layer: layers3d.length, + z: line.z, + } + layers3d.push(layer) + } + + getLineGroup = function (line, args) { + console.log('getLineGroup:', line) + if (layer == undefined) newLayer(line) + var speed = Math.round(line.e / 1000) + var opacity = line.s + var tool = parseInt(line.t, 10) + // /console.log('Speed: ' , speed , ' opacity: ', opacity) + var grouptype = speed + opacity + var color = null + // var color = new THREE.Color(0x990000) + + if (typeof line.s === 'undefined') { + opacity = 0.3 + } else { + var lasermultiply = $('#lasermultiply').val() || 100 + opacity = line.s / lasermultiply + console.log(opacity + ', ' + line.x) + // } + } + // console.log(opacity) + // LaserWeb 3D Viewer Colors + // LaserWeb 3D Viewer Colors + if (typeof line.extruding === 'undefined' && typeof line.s === 'undefined') { + // console.log('G1 without extrude', line) + grouptype = 'g0' + opacity = 0.3 + color = new THREE.Color(0x00ff00) + } else { + // console.log('G1 with extrude', line) + if (line.g0) { + grouptype = 'g0' + // color = new THREE.Color(0x00ff00) + opacity = 0.3 + color = new THREE.Color(0x00ff00) + } else if (line.g2) { + grouptype = 'g2' + // color = new THREE.Color(0x999900) + color = new THREE.Color(0x990000) + } else if (line.t == 0) { + grouptype = 't0' + // color = new THREE.Color(0x999900) + color = new THREE.Color(0x0000ff) + } else if (line.t == 1) { + grouptype = 't1' + // color = new THREE.Color(0x999900) + color = new THREE.Color(0xff00ff) + } else if (line.arc) { + grouptype = 'arc' + color = new THREE.Color(0x990000) + } else { + color = new THREE.Color(0x990000) + } + } + + // see if we have reached indxMax, if so draw, but + // make it ghosted + // if (args.indx > indxMax) { + // grouptype = "ghost" + // //console.log("args.indx > indxMax", args, indxMax) + // color = new THREE.Color(0x000000) + // } + // if (line.color) color = new THREE.Color(line.color) + if (layer.type[grouptype] == undefined) { + layer.type[grouptype] = { + type: grouptype, + feed: line.e, + extruding: line.extruding, + color: color, + segmentCount: 0, + material: new THREE.LineBasicMaterial({ + opacity: opacity, + // opacity: line.extruding ? 0.5: line.g2 ? 0.2 : 0.3, + transparent: true, + linewidth: 1, + vertexColors: THREE.FaceColors + }), + geometry: new THREE.Geometry(), + } + // if (args.indx > indxMax) { + // layer.type[grouptype].material.opacity = 0.05 + // } + } + return layer.type[grouptype] + } diff --git a/src/parse.js b/src/parse.js new file mode 100644 index 0000000..8b62297 --- /dev/null +++ b/src/parse.js @@ -0,0 +1,47 @@ +export default function parser (gcode) { + console.log('inside this.parse') + object = null + var lines = gcode.split(/\r{0,1}\n/) + var count = lines.length + var maxTimePerChunk = 500 + var index = 0 + + function now () { + return new Date().getTime() + } + + var tbody = '' + + function doChunk () { + var progress = (index / count) + NProgress.set(progress) + var startTime = now() + while (index < count && (now() - startTime) <= maxTimePerChunk) { + // console.log('parsing ' + lines[index]) + parseLine(lines[index], index) + // tbody += ''+[index]+''+lines[index]+'';//code here using lines[i] which will give you each line + ++index + } + closeLineSegment() + // console.log('done parsing ') + if (index < count) { + setTimeout(doChunk, 1) // set Timeout for async iteration + // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") + } else { + NProgress.done() + NProgress.remove() + // console.log('[GCODE PARSE] Done ') + $('#renderprogressholder').hide() + object = drawobject() + object.add(lineObjects) + // console.log('Line Objects', lineObjects) + object.translateX(laserxmax / 2 * -1) + object.translateY(laserymax / 2 * -1) + object.name = 'object' + console.log('adding to scene') + scene.add(object) + // objectsInScene.push(object) + } + } + doChunk() +} diff --git a/src/parseFunctions.js b/src/parseFunctions.js new file mode 100644 index 0000000..054bc73 --- /dev/null +++ b/src/parseFunctions.js @@ -0,0 +1,525 @@ +function drawArc(aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, plane) { + // console.log("drawArc:", aX, aY, aZ, aRadius, aStartAngle, aEndAngle, aClockwise) + var ac = new THREE.ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) + // console.log("ac:", ac) + var acmat = new THREE.LineBasicMaterial({ + color: 0x00aaff, + opacity: 0.5, + transparent: true + }) + var acgeo = new THREE.Geometry() + var ctr = 0 + var z = aZ + ac.getPoints(20).forEach(function (v) { + // console.log(v) + z = (((endaZ - aZ) / 20) * ctr) + aZ + acgeo.vertices.push(new THREE.Vector3(v.x, v.y, z)) + ctr++ + }) + var aco = new THREE.Line(acgeo, acmat) + // aco.position.set(pArc.x, pArc.y, pArc.z) + // console.log("aco:", aco) + this.extraObjects[plane].push(aco) + return aco +} + + +function drawArcFrom2PtsAndCenter (vp1, vp2, vpArc, args) { + // console.log("drawArcFrom2PtsAndCenter. vp1:", vp1, "vp2:", vp2, "vpArc:", vpArc, "args:", args) + + // var radius = vp1.distanceTo(vpArc) + // console.log("radius:", radius) + + // Find angle + var p1deltaX = vpArc.x - vp1.x + var p1deltaY = vpArc.y - vp1.y + var p1deltaZ = vpArc.z - vp1.z + + var p2deltaX = vpArc.x - vp2.x + var p2deltaY = vpArc.y - vp2.y + var p2deltaZ = vpArc.z - vp2.z + + switch (args.plane) { + case 'G18': + var anglepArcp1 = Math.atan(p1deltaZ / p1deltaX) + var anglepArcp2 = Math.atan(p2deltaZ / p2deltaX) + break + case 'G19': + var anglepArcp1 = Math.atan(p1deltaZ / p1deltaY) + var anglepArcp2 = Math.atan(p2deltaZ / p2deltaY) + break + default: + var anglepArcp1 = Math.atan(p1deltaY / p1deltaX) + var anglepArcp2 = Math.atan(p2deltaY / p2deltaX) + } + + // Draw arc from arc center + var radius = vpArc.distanceTo(vp1) + var radius2 = vpArc.distanceTo(vp2) + // console.log("radius:", radius) + + if (Number((radius).toFixed(2)) != Number((radius2).toFixed(2))) console.log('Radiuses not equal. r1:', radius, ', r2:', radius2, ' with args:', args, ' rounded vals r1:', Number((radius).toFixed(2)), ', r2:', Number((radius2).toFixed(2))) + + // arccurve + var clwise = true + if (args.clockwise === false) clwise = false + // if (anglepArcp1 < 0) clockwise = false + + switch (args.plane) { + case 'G19': + if (p1deltaY >= 0) anglepArcp1 += Math.PI + if (p2deltaY >= 0) anglepArcp2 += Math.PI + break + default: + if (p1deltaX >= 0) anglepArcp1 += Math.PI + if (p2deltaX >= 0) anglepArcp2 += Math.PI + } + + if (anglepArcp1 === anglepArcp2 && clwise === false) + // Draw full circle if angles are both zero, + // start & end points are same point... I think + switch (args.plane) { + case 'G18': + var threeObj = this.drawArc(vpArc.x, vpArc.z, (-1 * vp1.y), (-1 * vp2.y), radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G18') + break + case 'G19': + var threeObj = this.drawArc(vpArc.y, vpArc.z, vp1.x, vp2.x, radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G19') + break + default: + var threeObj = this.drawArc(vpArc.x, vpArc.y, vp1.z, vp2.z, radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G17') + } + else + switch (args.plane) { + case 'G18': + var threeObj = this.drawArc(vpArc.x, vpArc.z, (-1 * vp1.y), (-1 * vp2.y), radius, anglepArcp1, anglepArcp2, clwise, 'G18') + break + case 'G19': + var threeObj = this.drawArc(vpArc.y, vpArc.z, vp1.x, vp2.x, radius, anglepArcp1, anglepArcp2, clwise, 'G19') + break + default: + var threeObj = this.drawArc(vpArc.x, vpArc.y, vp1.z, vp2.z, radius, anglepArcp1, anglepArcp2, clwise, 'G17') + } + return threeObj +} + +function addSegment (p1, p2, args) { + closeLineSegment() + // console.log("") + // console.log("addSegment p2:", p2) + // add segment to array for later use + var group = getLineGroup(p2, args) + var geometry = group.geometry + + group.segmentCount++ + // see if we need to draw an arc + if (p2.arc) { + // console.log("") + // console.log("drawing arc. p1:", p1, ", p2:", p2) + + // var segmentCount = 12 + // figure out the 3 pts we are dealing with + // the start, the end, and the center of the arc circle + // radius is dist from p1 x/y/z to pArc x/y/z + // if(args.clockwise === false || args.cmd === "G3"){ + // var vp2 = new THREE.Vector3(p1.x, p1.y, p1.z) + // var vp1 = new THREE.Vector3(p2.x, p2.y, p2.z) + // } + // else { + var vp1 = new THREE.Vector3(p1.x, p1.y, p1.z) + var vp2 = new THREE.Vector3(p2.x, p2.y, p2.z) + // } + var vpArc + + // if this is an R arc gcode command, we're given the radius, so we + // don't have to calculate it. however we need to determine center + // of arc + if (args.r != null) { + // console.log("looks like we have an arc with R specified. args:", args) + // console.log("anglepArcp1:", anglepArcp1, "anglepArcp2:", anglepArcp2) + + radius = parseFloat(args.r) + + // First, find the distance between points 1 and 2. We'll call that q, + // and it's given by sqrt((x2-x1)^2 + (y2-y1)^2). + var q = Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(p2.z - p1.z, 2)) + + // Second, find the point halfway between your two points. We'll call it + // (x3, y3). x3 = (x1+x2)/2 and y3 = (y1+y2)/2. + var x3 = (p1.x + p2.x) / 2 + var y3 = (p1.y + p2.y) / 2 + var z3 = (p1.z + p2.z) / 2 + + // There will be two circle centers as a result of this, so + // we will have to pick the correct one. In gcode we can get + // a + or - val on the R to indicate which circle to pick + // One answer will be: + // x = x3 + sqrt(r^2-(q/2)^2)*(y1-y2)/q + // y = y3 + sqrt(r^2-(q/2)^2)*(x2-x1)/q + // The other will be: + // x = x3 - sqrt(r^2-(q/2)^2)*(y1-y2)/q + // y = y3 - sqrt(r^2-(q/2)^2)*(x2-x1)/q + var pArc_1 = undefined + var pArc_2 = undefined + var calc = Math.sqrt((radius * radius) - Math.pow(q / 2, 2)) + var angle_point = undefined + + switch (args.plane) { + case 'G18': + pArc_1 = { + x: x3 + calc * (p1.z - p2.z) / q, + y: y3 + calc * (p2.y - p1.y) / q, + z: z3 + calc * (p2.x - p1.x) / q } + pArc_2 = { + x: x3 - calc * (p1.z - p2.z) / q, + y: y3 - calc * (p2.y - p1.y) / q, + z: z3 - calc * (p2.x - p1.x) / q } + angle_point = Math.atan2(p1.z, p1.x) - Math.atan2(p2.z, p2.x) + if (((p1.x - pArc_1.x) * (p1.z + pArc_1.z)) + ((pArc_1.x - p2.x) * (pArc_1.z + p2.z)) >= + ((p1.x - pArc_2.x) * (p1.z + pArc_2.z)) + ((pArc_2.x - p2.x) * (pArc_2.z + p2.z))) { + var cw = pArc_1 + var ccw = pArc_2 + } else { + var cw = pArc_2 + var ccw = pArc_1 + } + break + case 'G19': + pArc_1 = { + x: x3 + calc * (p1.x - p2.x) / q, + y: y3 + calc * (p1.z - p2.z) / q, + z: z3 + calc * (p2.y - p1.y) / q } + pArc_2 = { + x: x3 - calc * (p1.x - p2.x) / q, + y: y3 - calc * (p1.z - p2.z) / q, + z: z3 - calc * (p2.y - p1.y) / q } + + if (((p1.y - pArc_1.y) * (p1.z + pArc_1.z)) + ((pArc_1.y - p2.y) * (pArc_1.z + p2.z)) >= + ((p1.y - pArc_2.y) * (p1.z + pArc_2.z)) + ((pArc_2.y - p2.y) * (pArc_2.z + p2.z))) { + var cw = pArc_1 + var ccw = pArc_2 + } else { + var cw = pArc_2 + var ccw = pArc_1 + } + break + default: + pArc_1 = { + x: x3 + calc * (p1.y - p2.y) / q, + y: y3 + calc * (p2.x - p1.x) / q, + z: z3 + calc * (p2.z - p1.z) / q } + pArc_2 = { + x: x3 - calc * (p1.y - p2.y) / q, + y: y3 - calc * (p2.x - p1.x) / q, + z: z3 - calc * (p2.z - p1.z) / q } + if (((p1.x - pArc_1.x) * (p1.y + pArc_1.y)) + ((pArc_1.x - p2.x) * (pArc_1.y + p2.y)) >= + ((p1.x - pArc_2.x) * (p1.y + pArc_2.y)) + ((pArc_2.x - p2.x) * (pArc_2.y + p2.y))) { + var cw = pArc_1 + var ccw = pArc_2 + } else { + var cw = pArc_2 + var ccw = pArc_1 + } + } + + if ((p2.clockwise === true && radius >= 0) || (p2.clockwise === false && radius < 0)) vpArc = new THREE.Vector3(cw.x, cw.y, cw.z) + else vpArc = new THREE.Vector3(ccw.x, ccw.y, ccw.z) + } else { + // this code deals with IJK gcode commands + /*if(args.clockwise === false || args.cmd === "G3") + var pArc = { + x: p2.arci ? p1.x + p2.arci : p1.x, + y: p2.arcj ? p1.y + p2.arcj : p1.y, + z: p2.arck ? p1.z + p2.arck : p1.z, + ¨ } + else*/ + var pArc = { + x: p2.arci ? p1.x + p2.arci : p1.x, + y: p2.arcj ? p1.y + p2.arcj : p1.y, + z: p2.arck ? p1.z + p2.arck : p1.z, + } + // console.log("new pArc:", pArc) + vpArc = new THREE.Vector3(pArc.x, pArc.y, pArc.z) + // console.log("vpArc:", vpArc) + } + + var threeObjArc = this.drawArcFrom2PtsAndCenter(vp1, vp2, vpArc, args) + + // still push the normal p1/p2 point for debug + p2.g2 = true + p2.threeObjArc = threeObjArc + group = this.getLineGroup(p2, args) + // these golden lines showing start/end of a g2 or g3 arc were confusing people + // so hiding them for now. jlauer 8/15/15 + /* + geometry = group.geometry + geometry.vertices.push( + new THREE.Vector3(p1.x, p1.y, p1.z)) + geometry.vertices.push( + new THREE.Vector3(p2.x, p2.y, p2.z)) + geometry.colors.push(group.color) + geometry.colors.push(group.color) + */ + } else { + geometry.vertices.push( + new THREE.Vector3(p1.x, p1.y, p1.z)) + geometry.vertices.push( + new THREE.Vector3(p2.x, p2.y, p2.z)) + geometry.colors.push(group.color) + geometry.colors.push(group.color) + } + + if (p2.extruding) { + bbbox.min.x = Math.min(bbbox.min.x, p2.x) + bbbox.min.y = Math.min(bbbox.min.y, p2.y) + bbbox.min.z = Math.min(bbbox.min.z, p2.z) + bbbox.max.x = Math.max(bbbox.max.x, p2.x) + bbbox.max.y = Math.max(bbbox.max.y, p2.y) + bbbox.max.z = Math.max(bbbox.max.z, p2.z) + } + if (p2.g0) { + // we're in a toolhead move, label moves + /* + if (group.segmentCount < 2) { + makeSprite(scene, "webgl", { + x: p2.x, + y: p2.y, + z: p2.z + 0, + text: group.segmentCount, + color: "#ff00ff", + size: 3, + }) + } + */ + } + // global bounding box calc + bbbox2.min.x = Math.min(bbbox2.min.x, p2.x) + bbbox2.min.y = Math.min(bbbox2.min.y, p2.y) + bbbox2.min.z = Math.min(bbbox2.min.z, p2.z) + bbbox2.max.x = Math.max(bbbox2.max.x, p2.x) + bbbox2.max.y = Math.max(bbbox2.max.y, p2.y) + bbbox2.max.z = Math.max(bbbox2.max.z, p2.z) + + // NEW METHOD OF CREATING THREE.JS OBJECTS + // create new approach for three.js objects which is + // a unique object for each line of gcode, including g2/g3's + // make sure userData is good too + var gcodeObj + + if (p2.arc) { + // use the arc that already got built + gcodeObj = p2.threeObjArc + } else { + // make a line + var color = 0X0000ff + + if (p2.extruding) { + color = 0xff00ff + } else if (p2.g0) { + color = 0x00ff00 + } else if (p2.g2) { + // color = 0x999900 + } else if (p2.arc) { + color = 0x0033ff + } + + var material = new THREE.LineBasicMaterial({ + color: color, + opacity: 0.5, + transparent: true + }) + + // var geometry = new THREE.Geometry() + // geometry.vertices.push( + // new THREE.Vector3( p1.x, p1.y, p1.z ), + // ew THREE.Vector3( p2.x, p2.y, p2.z ) + // ) + + var line = new THREE.Line(geometry, material) + gcodeObj = line + } + gcodeObj.userData.p2 = p2 + gcodeObj.userData.args = args + new3dObj.add(gcodeObj) + + // DISTANCE CALC + // add distance so we can calc estimated time to run + // see if arc + var dist = 0 + if (p2.arc) { + // calc dist of all lines + // console.log("this is an arc to calc dist for. p2.threeObjArc:", p2.threeObjArc, "p2:", p2) + var arcGeo = p2.threeObjArc.geometry + // console.log("arcGeo:", arcGeo) + + var tad2 = 0 + for (var arcLineCtr = 0; arcLineCtr < arcGeo.vertices.length - 1; arcLineCtr++) { + tad2 += arcGeo.vertices[arcLineCtr].distanceTo(arcGeo.vertices[arcLineCtr + 1]) + } + // console.log("tad2:", tad2) + + // just do straight line calc + var a = new THREE.Vector3(p1.x, p1.y, p1.z) + var b = new THREE.Vector3(p2.x, p2.y, p2.z) + var straightDist = a.distanceTo(b) + + // console.log("diff of straight line calc vs arc sum. straightDist:", straightDist) + + dist = tad2 + } else { + // just do straight line calc + var a = new THREE.Vector3(p1.x, p1.y, p1.z) + var b = new THREE.Vector3(p2.x, p2.y, p2.z) + dist = a.distanceTo(b) + } + + if (dist > 0) { + totalDist += dist + } + + // time to execute this move + // if this move is 10mm and we are moving at 100mm/min then + // this move will take 10/100 = 0.1 minutes or 6 seconds + var timeMinutes = 0 + if (dist > 0) { + var fr + if (args.feedrate > 0) { + fr = args.feedrate + } else { + fr = 100 + } + timeMinutes = dist / fr + + // adjust for acceleration, meaning estimate + // this will run longer than estimated from the math + // above because we don't start moving at full feedrate + // obviously, we have to slowly accelerate in and out + timeMinutes = timeMinutes * 1.32 + } + + // Handle Laser Sxxx parameter + sv = args.s + // console.log(sv) + + totalTime += timeMinutes + + p2.feedrate = args.feedrate + p2.dist = dist + p2.distSum = totalDist + p2.timeMins = timeMinutes + p2.timeMinsSum = totalTime + + // console.log('Total Time'+totalTime) + totaltimemax += (timeMinutes * 60) +// console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) +} + +function addLineSegment (p1, p2) { + var i = lineObject.nLines * 6 + // lineObject.vertexBuf[i+0] = p1.x // Vertices + // lineObject.vertexBuf[i+1] = p1.y + // lineObject.vertexBuf[i+2] = p1.z + // lineObject.vertexBuf[i+3] = p2.x + // lineObject.vertexBuf[i+4] = p2.y + // lineObject.vertexBuf[i+5] = p2.z + + if (p1.a != 0 || p2.a != 0) { // A axis: rotate around X + var R1 = Math.sqrt(p1.y * p1.y + p1.z * p1.z) + var R2 = Math.sqrt(p2.y * p2.y + p2.z * p2.z) + var a1 = p1.y == 0 ? Math.sign(p1.z) * 90 : Math.atan2(p1.z, p1.y) * 180.0 / Math.PI + var a2 = p2.y == 0 ? Math.sign(p2.z) * 90 : Math.atan2(p2.z, p2.y) * 180.0 / Math.PI + lineObject.vertexBuf[i + 0] = p1.x + lineObject.vertexBuf[i + 1] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) + lineObject.vertexBuf[i + 2] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) + lineObject.vertexBuf[i + 3] = p2.x + lineObject.vertexBuf[i + 4] = R2 * Math.cos((-p2.a + a2) * Math.PI / 180.0) + lineObject.vertexBuf[i + 5] = R2 * Math.sin((-p2.a + a2) * Math.PI / 180.0) + } else { + // Vertice code for A Axis as submitted by HakanBasted - commented out by PvdW else normal gcode only renders in a single Y line. + // lineObject.vertexBuf[i+0] = p1.x // Vertices + // lineObject.vertexBuf[i+1] = 0.1*p1.a + // lineObject.vertexBuf[i+2] = p1.z + // lineObject.vertexBuf[i+3] = p2.x + // lineObject.vertexBuf[i+4] = 0.1*p2.a + // lineObject.vertexBuf[i+5] = p2.z + + lineObject.vertexBuf[i + 0] = p1.x // Vertices + lineObject.vertexBuf[i + 1] = p1.y + lineObject.vertexBuf[i + 2] = p1.z + lineObject.vertexBuf[i + 3] = p2.x + lineObject.vertexBuf[i + 4] = p2.y + lineObject.vertexBuf[i + 5] = p2.z + } + // console.log("Segment " + p1) + + var dist = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)) + totalDist += dist + timeMinutes = dist / p2.f + totalTime += timeMinutes + totaltimemax = totalTime * 60 + + var col + var intensity + var lasermultiply = $('#lasermultiply').val() || 100 + if (p2.g0) { // g0 + col = {r: 0, g: 1, b: 0} + intensity = 1.0 - p2.s / lasermultiply // lasermultiply + } else if (p2.g1) { // g1 + col = {r: 0.7, g: 0, b: 0} + intensity = 1.0 - p2.s / lasermultiply // lasermultiply + } else if (p2.g7) { // g7 + col = {r: 0, g: 0, b: 1} + intensity = 1.0 - p2.s / lasermultiply // lasermultiply + } else { + col = {r: 0, g: 1, b: 1} + intensity = 1.0 - p2.s / lasermultiply // lasermultiply + } + + lineObject.colorBuf[i + 0] = col.r + (1 - col.r) * intensity // Colors + lineObject.colorBuf[i + 1] = col.g + (1 - col.g) * intensity + lineObject.colorBuf[i + 2] = col.b + (1 - col.b) * intensity + lineObject.colorBuf[i + 3] = col.r + (1 - col.r) * intensity + lineObject.colorBuf[i + 4] = col.g + (1 - col.g) * intensity + lineObject.colorBuf[i + 5] = col.b + (1 - col.b) * intensity + + lineObject.nLines++ + + if (lineObject.nLines == bufSize) + closeLineSegment() +} + + +function closeLineSegment () { + if (lineObject.nLines == 0) + return + + var vertices = new Float32Array(6 * lineObject.nLines) + var colors = new Float32Array(6 * lineObject.nLines) + vertices.set(lineObject.vertexBuf.subarray(0, lineObject.nLines * 6)) + colors.set(lineObject.colorBuf.subarray(0, lineObject.nLines * 6)) + + var geometry = new THREE.BufferGeometry() + + geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3)) + geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3)) + + var lines = new THREE.Line(geometry, material) + lineObjects.add(lines); // Feed the objects to "object" in doChunk() + + lineObject.nLines = 0 +} + + +function addFakeSegment(args) { + closeLineSegment() + // line.args = args + var arg2 = { + isFake: true, + text: args.text, + indx: args.indx + } + if (arg2.text.match(/^(;|\(|<)/)) arg2.isComment = true + lines.push({ + p2: lastLine, // since this is fake, just use lastLine as xyz + 'args': arg2 + }) +} diff --git a/src/parseLine.js b/src/parseLine.js new file mode 100644 index 0000000..a201f6d --- /dev/null +++ b/src/parseLine.js @@ -0,0 +1,128 @@ +export function parseLine (text, info) { + // console.log('Parsing: ',text) + const origtext = text + + if (text.match(/^N/i)) { // remove line numbers if exist + text = text.replace(/^N\d+\s*/ig, '')// yes, there's a line num + } + + const isG7 = text.match(/^G7/) // Is is G7 raster command? + if (!isG7) { // G7 D-data need to be untouched + text = text.replace(/G00/i, 'G0') // collapse leading zero g cmds to no leading zero + text = text.replace(/G0(\d)/i, 'G$1') // add spaces before g cmds and xyzabcijkf params + text = text.replace(/([gmtxyzabcijkfst])/ig, ' $1') // remove spaces after xyzabcijkf params because a number should be directly after them + text = text.replace(/([xyzabcijkfst])\s+/ig, '$1') // remove front and trailing space + } + text = text.trim() + + let isComment = false + if (text.match(/^(;|\(|<)/)) { // see if comment + text = origtext + isComment = true + } else { // make sure to remove inline comments + if (!isG7) + text = text.replace(/\(.*?\)/g, '') + } + + if (text && !isComment) { + if (!isG7) + text = text.replace(/(;|\().*$/, ''); // strip off end of line comment ; or () trailing + + let tokens = text.split(/\s+/) + if (tokens) { + var cmd = tokens[0] // check if a g or m cmd was included in gcode line + cmd = cmd.toUpperCase() // you are allowed to just specify coords on a line + // and it should be assumed that the last specified gcode + // cmd is what's assumed + isComment = false + if (!cmd.match(/^(G|M|T)/i)) { + cmd = this.lastArgs.cmd // we need to use the last gcode cmd + tokens.unshift(cmd) // put at spot 0 in array + } else { + // we have a normal cmd as opposed to just an xyz pos where + // it assumes you should use the last cmd + // however, need to remove inline comments (TODO. it seems parser works fine for now) + } + const args = { + 'cmd': cmd, + 'text': text, + 'origtext': origtext, + 'indx': info, + 'isComment': isComment, + 'feedrate': null, + 'plane': undefined + } + + if (tokens.length > 1 && !isComment) { + tokens.splice(1).forEach(function (token) { + if (token && token.length > 0) { + var key = token[0].toLowerCase() + if (!isG7) { + var value = parseFloat(token.substring(1)) + if (isNaN(value)) { + value = 0 + } + args[key] = value + } else { // Special treatment for G7 with D-data + if (key == '$') key = 'dollar' // '$' doesn't work so well, use 'dollar' + var value = token.substring(1) // Don't convert values to float, need the D-data + args[key] = value + } + } else { + // console.log("couldn't parse token in foreach. weird:", token) + } + }) + } + let handler = handlers[cmd] || handlers['default'] + + if (!args.isComment) { // don't save if saw a comment + lastArgs = args + } + + if (handler) { + // do extra check here for units. units are + // specified via G20 or G21. We need to scan + // each line to see if it's inside the line because + // we were only catching it when it was the first cmd + // of the line. + if (args.text.match(/\bG20\b/i)) { + console.log('SETTING UNITS TO INCHES from pre-parser!!!') + this.isUnitsMm = false // false means inches cuz default is mm + } else if (args.text.match(/\bG21\b/i)) { + console.log('SETTING UNITS TO MM!!! from pre-parser') + this.isUnitsMm = true // true means mm + } + + if (args.text.match(/F([\d.]+)/i)) { // scan for feedrate + var feedrate = parseFloat(RegExp.$1) // we have a new feedrate + args.feedrate = feedrate + this.lastFeedrate = feedrate + } else { + args.feedrate = this.lastFeedrate // use feedrate from prior lines + } + + return handler(args, info, this) + } else { + console.error('No handler for gcode command!!!') + } + } + } else { + // it was a comment or the line was empty + // we still need to create a segment with xyz in p2 + // so that when we're being asked to /gotoline we have a position + // for each gcode line, even comments. we just use the last real position + // to give each gcode line (even a blank line) a spot to go to + + // REMOVE THIS ? + + const args = { + 'cmd': 'empty or comment', + 'text': text, + 'origtext': origtext, + 'indx': info, + 'isComment': isComment + } + var handler = handlers['default'] + return handler(args, info, this) + } +} diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..2adc968 --- /dev/null +++ b/src/utils.js @@ -0,0 +1,7 @@ +export function delta (v1, v2) { + return relative ? v2 : v2 - v1 +} + +export function absolute (v1, v2) { + return relative ? v1 + v2 : v2 +} From b1314929134793a403b825935538daa2229c97f5 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sat, 5 Nov 2016 11:09:17 +0100 Subject: [PATCH 03/34] chore(split up): more code split up etc - added small 'mind map' to gain better understanding of current codebase --- src/drawObject.js | 96 ++++++++++++++++++++++ src/index.js | 20 +++++ src/legacy/gcode-parser-breakapart.js | 110 -------------------------- 3 files changed, 116 insertions(+), 110 deletions(-) create mode 100644 src/drawObject.js diff --git a/src/drawObject.js b/src/drawObject.js new file mode 100644 index 0000000..cc0f98d --- /dev/null +++ b/src/drawObject.js @@ -0,0 +1,96 @@ +function drawobject () { + var newObject = false + // console.log("INSIDE DRAWOBJECT") + // set what units we're using in the gcode + isUnitsMm = parser.isUnitsMm + + newObject = new THREE.Object3D() + newObject.name = 'newObject' + + // old approach of monolithic line segment + for (var lid in layers3d) { + // console.log('processing Layer ' + lid) + var layer = layers3d[lid] + for (var tid in layer.type) { + var type = layer.type[tid] + var bufferGeo = convertLineGeometryToBufferGeometry(type.geometry, type.color) + newObject.add(new THREE.Line(bufferGeo, type.material, THREE.LinePieces)) + } + } + newObject.add(new THREE.Object3D()) + // XY PLANE + extraObjects['G17'].forEach(function (obj) { + var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) + newObject.add(new THREE.Line(bufferGeo, obj.material)) + }, this) + // XZ PLANE + extraObjects['G18'].forEach(function (obj) { + // buffered approach + var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) + var tmp = new THREE.Line(bufferGeo, obj.material) + tmp.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2) + newObject.add(tmp) + }, this) + // YZ PLANE + extraObjects['G19'].forEach(function (obj) { + // buffered approach + var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) + var tmp = new THREE.Line(bufferGeo, obj.material) + tmp.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2) + tmp.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2) + newObject.add(tmp) + }, this) + + // use new approach of building 3d object where each + // gcode line is its own segment with its own userData + // object = new3dObj + + // Center + var scale = 1; // TODO: Auto size + + var center = new THREE.Vector3( + bbbox.min.x + ((bbbox.max.x - bbbox.min.x) / 2), + bbbox.min.y + ((bbbox.max.y - bbbox.min.y) / 2), + bbbox.min.z + ((bbbox.max.z - bbbox.min.z) / 2)) + + var center2 = new THREE.Vector3( + bbbox2.min.x + ((bbbox2.max.x - bbbox2.min.x) / 2), + bbbox2.min.y + ((bbbox2.max.y - bbbox2.min.y) / 2), + bbbox2.min.z + ((bbbox2.max.z - bbbox2.min.z) / 2)) + + var dX = bbbox2.max.x - bbbox2.min.x + var dY = bbbox2.max.y - bbbox2.min.y + var dZ = bbbox2.max.z - bbbox2.min.z + + function toTimeString (seconds) { + // return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0] + } + + console.log(totaltimemax + ' seconds estimated') + + // printLog('Estimated Job Time: '+totaltimemax, successcolor) + + printLog('Estimated Distance: ' + (totalDist / 1000).toFixed(1) + ' m', msgcolor, 'viewer') + $('#lasertimeqty').val((totalDist.toFixed(1)) / 10) + + if (fileParentGroup) { + var bbox2 = new THREE.Box3().setFromObject(fileParentGroup) + // console.log('bbox width: ', (bbox2.max.x - bbox2.min.x), 'height Y: ', (bbox2.max.y - bbox2.min.y) ) + width = (bbox2.max.x - bbox2.min.x) + height = (bbox2.max.y - bbox2.min.y) + $('#quoteresult').html('Job moves length: ' + totalDist.toFixed(1) + ' mm
Width: ' + width.toFixed(1) + ' mm
Height: ' + height.toFixed(1) + ' mm
Material: ' + ((width * height) / 1000).toFixed(3) + 'cm2') + $('#materialqty').val(((width * height) / 1000).toFixed(3)) + } else if (rastermesh) { + var bbox2 = new THREE.Box3().setFromObject(rastermesh) + // console.log('bbox width: ', (bbox2.max.x - bbox2.min.x), 'height Y: ', (bbox2.max.y - bbox2.min.y) ) + width = (bbox2.max.x - bbox2.min.x) + height = (bbox2.max.y - bbox2.min.y) + $('#quoteresult').html('Job moves length: ' + totalDist.toFixed(1) + ' mm
Width: ' + width.toFixed(1) + ' mm
Height: ' + height.toFixed(1) + ' mm
Material: ' + ((width * height) / 1000).toFixed(3) + 'cm2') + $('#materialqty').val(((width * height) / 1000).toFixed(3)) + } + + console.groupEnd() + return newObject + // console.groupEnd() + +} diff --git a/src/index.js b/src/index.js index 8bc72bb..fa501d9 100644 --- a/src/index.js +++ b/src/index.js @@ -5,4 +5,24 @@ **/ export default function makeGcodeStream (parameters = {}) { + + + /* + + //main entry point !! + createObjectFromGCode(gcode, indxMax) + => handlers = { + gcode(G1 etc): function + => drawArc + => drawArcFrom2PtsAndCenter + => addSegment + } + =>GCodeParser(handlers) + =>parse + =>doChunk + =>parseLine + + + convertLineGeometryToBufferGeometry + */ } diff --git a/src/legacy/gcode-parser-breakapart.js b/src/legacy/gcode-parser-breakapart.js index 1516647..977cbe4 100644 --- a/src/legacy/gcode-parser-breakapart.js +++ b/src/legacy/gcode-parser-breakapart.js @@ -25,9 +25,6 @@ colorG0: 0x00ff00 colorG1: 0x0000ff colorG2: 0x999900 - - - var bufSize = 10000; // Arbitrary - play around with! var lineObject = {active: false, vertexBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments @@ -39,116 +36,9 @@ colorG2: 0x999900 transparent: true, linewidth: 1, }) - - - - totalDist = 0 totalTime = 0 - var relative = false var tool = null - - - - var cofg = this - //parser = new GCodeParser( - -function drawobject () { - var newObject = false - // console.log("INSIDE DRAWOBJECT") - // set what units we're using in the gcode - isUnitsMm = parser.isUnitsMm - - newObject = new THREE.Object3D() - newObject.name = 'newObject' - - // old approach of monolithic line segment - for (var lid in layers3d) { - // console.log('processing Layer ' + lid) - var layer = layers3d[lid] - for (var tid in layer.type) { - var type = layer.type[tid] - var bufferGeo = convertLineGeometryToBufferGeometry(type.geometry, type.color) - newObject.add(new THREE.Line(bufferGeo, type.material, THREE.LinePieces)) - } - } - newObject.add(new THREE.Object3D()) - // XY PLANE - extraObjects['G17'].forEach(function (obj) { - var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) - newObject.add(new THREE.Line(bufferGeo, obj.material)) - }, this) - // XZ PLANE - extraObjects['G18'].forEach(function (obj) { - // buffered approach - var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) - var tmp = new THREE.Line(bufferGeo, obj.material) - tmp.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2) - newObject.add(tmp) - }, this) - // YZ PLANE - extraObjects['G19'].forEach(function (obj) { - // buffered approach - var bufferGeo = convertLineGeometryToBufferGeometry(obj.geometry, obj.material.color) - var tmp = new THREE.Line(bufferGeo, obj.material) - tmp.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2) - tmp.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2) - newObject.add(tmp) - }, this) - - // use new approach of building 3d object where each - // gcode line is its own segment with its own userData - // object = new3dObj - - // Center - var scale = 1; // TODO: Auto size - - var center = new THREE.Vector3( - bbbox.min.x + ((bbbox.max.x - bbbox.min.x) / 2), - bbbox.min.y + ((bbbox.max.y - bbbox.min.y) / 2), - bbbox.min.z + ((bbbox.max.z - bbbox.min.z) / 2)) - - var center2 = new THREE.Vector3( - bbbox2.min.x + ((bbbox2.max.x - bbbox2.min.x) / 2), - bbbox2.min.y + ((bbbox2.max.y - bbbox2.min.y) / 2), - bbbox2.min.z + ((bbbox2.max.z - bbbox2.min.z) / 2)) - - var dX = bbbox2.max.x - bbbox2.min.x - var dY = bbbox2.max.y - bbbox2.min.y - var dZ = bbbox2.max.z - bbbox2.min.z - - function toTimeString (seconds) { - // return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0] - } - - console.log(totaltimemax + ' seconds estimated') - - // printLog('Estimated Job Time: '+totaltimemax, successcolor) - - printLog('Estimated Distance: ' + (totalDist / 1000).toFixed(1) + ' m', msgcolor, 'viewer') - $('#lasertimeqty').val((totalDist.toFixed(1)) / 10) - - if (fileParentGroup) { - var bbox2 = new THREE.Box3().setFromObject(fileParentGroup) - // console.log('bbox width: ', (bbox2.max.x - bbox2.min.x), 'height Y: ', (bbox2.max.y - bbox2.min.y) ) - width = (bbox2.max.x - bbox2.min.x) - height = (bbox2.max.y - bbox2.min.y) - $('#quoteresult').html('Job moves length: ' + totalDist.toFixed(1) + ' mm
Width: ' + width.toFixed(1) + ' mm
Height: ' + height.toFixed(1) + ' mm
Material: ' + ((width * height) / 1000).toFixed(3) + 'cm2') - $('#materialqty').val(((width * height) / 1000).toFixed(3)) - } else if (rastermesh) { - var bbox2 = new THREE.Box3().setFromObject(rastermesh) - // console.log('bbox width: ', (bbox2.max.x - bbox2.min.x), 'height Y: ', (bbox2.max.y - bbox2.min.y) ) - width = (bbox2.max.x - bbox2.min.x) - height = (bbox2.max.y - bbox2.min.y) - $('#quoteresult').html('Job moves length: ' + totalDist.toFixed(1) + ' mm
Width: ' + width.toFixed(1) + ' mm
Height: ' + height.toFixed(1) + ' mm
Material: ' + ((width * height) / 1000).toFixed(3) + 'cm2') - $('#materialqty').val(((width * height) / 1000).toFixed(3)) - } - - console.groupEnd() - return newObject - // console.groupEnd() - -} From 5b8750386ce10087b20b8a4683f986ca4e4a1668 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sat, 5 Nov 2016 12:20:54 +0100 Subject: [PATCH 04/34] feat(gcodeHandlers): migrating gcodeHandlers & parseFunction towards more clear,'pure' functions as much as possible: - extracting state - removing explicit referenced to UI elements - passing explicit parameters when possible - reducing mutations when possible -etc --- src/gcodeHandlers.js | 598 +++++++++++++++++++++--------------------- src/parseFunctions.js | 86 +++--- src/parseLine.js | 6 +- 3 files changed, 352 insertions(+), 338 deletions(-) diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js index a86b17e..df5b0e7 100644 --- a/src/gcodeHandlers.js +++ b/src/gcodeHandlers.js @@ -1,300 +1,314 @@ -const handlers = { - // set the g92 offsets for the parser - defaults to no offset - // When doing CNC, generally G0 just moves to a new location - // as fast as possible which means no milling or extruding is happening in G0. - // So, let's color it uniquely to indicate it's just a toolhead move. - G0: function (args, indx) { - var newLine = { - x: args.x !== undefined ? cofg.absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, - y: args.y !== undefined ? cofg.absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, - z: args.z !== undefined ? cofg.absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, - a: args.a !== undefined ? cofg.absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, - e: args.e !== undefined ? cofg.absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, - f: args.f !== undefined ? args.f : lastLine.f, - s: 100, - } - newLine.g0 = true - cofg.addLineSegment(lastLine, newLine) - lastLine = newLine - }, - G1: function (args, indx) { - // Example: G1 Z1.0 F3000 - // G1 X99.9948 Y80.0611 Z15.0 F1500.0 E981.64869 - // G1 E104.25841 F1800.0 - // Go in a straight line from the current (X, Y) point - // to the point (90.6, 13.8), extruding material as the move - // happens from the current extruded length to a length of - // 22.4 mm. - - var newLine = { - x: args.x !== undefined ? cofg.absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, - y: args.y !== undefined ? cofg.absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, - z: args.z !== undefined ? cofg.absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, - a: args.a !== undefined ? cofg.absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, - e: args.e !== undefined ? cofg.absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, - f: args.f !== undefined ? args.f : lastLine.f, - s: args.s !== undefined ? args.s : lastLine.s, - t: args.t !== undefined ? args.t : lastLine.t, - } - /* layer change detection is or made by watching Z, it's made by - watching when we extrude at a new Z position */ - if (cofg.delta(lastLine.e, newLine.e) > 0) { - newLine.extruding = cofg.delta(lastLine.e, newLine.e) > 0 - if (layer == undefined || newLine.z != layer.z) cofg.newLayer(newLine) - } - newLine.g1 = true - cofg.addLineSegment(lastLine, newLine) - lastLine = newLine - }, - G2: function (args, indx, gcp) { - // this is an arc move from lastLine's xy to the new xy. we'll - // show it as a light gray line, but we'll also sub-render the - // arc itself by figuring out the sub-segments - - args.plane = plane // set the plane for this command to whatever the current plane is - - var newLine = { - x: args.x !== undefined ? cofg.absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, - y: args.y !== undefined ? cofg.absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, - z: args.z !== undefined ? cofg.absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, - a: args.a !== undefined ? cofg.absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, - e: args.e !== undefined ? cofg.absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, - f: args.f !== undefined ? args.f : lastLine.f, - s: args.s !== undefined ? args.s : lastLine.s, - t: args.t !== undefined ? args.t : lastLine.t, - arci: args.i ? args.i : null, - arcj: args.j ? args.j : null, - arck: args.k ? args.k : null, - arcr: args.r ? args.r : null, - } - newLine.arc = true - newLine.clockwise = true - if (args.clockwise === false) newLine.clockwise = args.clockwise - cofg.addSegment(lastLine, newLine, args) - lastLine = newLine - }, - G3: function (args, indx, gcp) { - // this is an arc move from lastLine's xy to the new xy. same - // as G2 but reverse - args.arc = true - args.clockwise = false - args.plane = plane // set the plane for this command to whatever the current plane is - - var newLine = { - x: args.x !== undefined ? cofg.absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, - y: args.y !== undefined ? cofg.absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, - z: args.z !== undefined ? cofg.absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, - a: args.a !== undefined ? cofg.absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, - e: args.e !== undefined ? cofg.absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, - f: args.f !== undefined ? args.f : lastLine.f, - s: args.s !== undefined ? args.s : lastLine.s, - t: args.t !== undefined ? args.t : lastLine.t, - arci: args.i ? args.i : null, - arcj: args.j ? args.j : null, - arck: args.k ? args.k : null, - arcr: args.r ? args.r : null, - } - newLine.arc = true - newLine.clockwise = true - if (args.clockwise === false) newLine.clockwise = args.clockwise - cofg.addSegment(lastLine, newLine, args) - lastLine = newLine - }, - - dirG7: 0, - - G7: function (args, indx) { - // Example: G7 L68 D//////sljasflsfagdxsd,.df9078rhfnxm (68 of em) - // G7 $1 L4 DAAA= - // G7 $0 L4 D2312 - // Move right (if $1) or left (if $0) 51 steps (from L68) - // (the number of steps is found when decoding the data) - // and burn the laser with the intensity in the base64-encoded - // data in D. Data in D is 51 base64-encoded bytes with grayscale - // intensity. When base64-encoded the string becomes 68 bytes long. - // - // SpotSize comes from a previous M649 S100 R0.1 - // where S is intensity (100 is max) and R gives spotsize in mm. - // Actual laser power is then D-value * S-value in every pixel - // A direction change with $0/$1 gives a spotSize long movement in Y - // for the next row. - - var buf = atob(args.d) - - if (typeof args.dollar !== 'undefined') { // Move Y, change direction - this.dirG7 = args.dollar - var newLine = { - x: lastLine.x, - y: lastLine.y + cofg.spotSizeG7, - z: lastLine.z, - a: lastLine.a, - e: lastLine.e, - f: lastLine.f, +import {absolute, delta} from './utils' + +export default function makeHandlers(){ + + let state = { + isUnitsMm: true, + plane: undefined, + relative: true + } + const lasermultiply = 100 + const lineObject = {} + const lastLine = undefined + //EEK !! var lasermultiply = $('#lasermultiply').val() || 100 + + const handlers = { + // set the g92 offsets for the parser - defaults to no offset + // When doing CNC, generally G0 just moves to a new location + // as fast as possible which means no milling or extruding is happening in G0. + // So, let's color it uniquely to indicate it's just a toolhead move. + G0: function (args, indx) { + const newLine = { + x: args.x !== undefined ? absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, + y: args.y !== undefined ? absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, + z: args.z !== undefined ? absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, + a: args.a !== undefined ? absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, + e: args.e !== undefined ? absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + f: args.f !== undefined ? args.f : lastLine.f, s: 100, - t: lastLine.t, } newLine.g0 = true - cofg.addLineSegment(lastLine, newLine) + addLineSegment (lastLine, newLine, lineObject, lasermultiply) lastLine = newLine - } - for (var i = 0; i < buf.length; i++) { // Process a base64-encoded chunk - var intensity = 255 - buf.charCodeAt(i); // 255 - 0 - var newLine = { - x: lastLine.x + cofg.spotSizeG7 * (this.dirG7 == 1 ? 1 : -1), - y: lastLine.y, - z: lastLine.z, - a: lastLine.a, - e: lastLine.e, - f: lastLine.f, - s: intensity, - t: lastLine.t, + }, + G1: function (args, indx) { + // Example: G1 Z1.0 F3000 + // G1 X99.9948 Y80.0611 Z15.0 F1500.0 E981.64869 + // G1 E104.25841 F1800.0 + // Go in a straight line from the current (X, Y) point + // to the point (90.6, 13.8), extruding material as the move + // happens from the current extruded length to a length of + // 22.4 mm. + + const newLine = { + x: args.x !== undefined ? absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, + y: args.y !== undefined ? absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, + z: args.z !== undefined ? absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, + a: args.a !== undefined ? absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, + e: args.e !== undefined ? absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + f: args.f !== undefined ? args.f : lastLine.f, + s: args.s !== undefined ? args.s : lastLine.s, + t: args.t !== undefined ? args.t : lastLine.t, + } + /* layer change detection is or made by watching Z, it's made by + watching when we extrude at a new Z position */ + if (delta(lastLine.e, newLine.e) > 0) { + newLine.extruding = delta(lastLine.e, newLine.e) > 0 + if (layer == undefined || newLine.z != layer.z) cofg.newLayer(newLine) + } + newLine.g1 = true + addLineSegment(lastLine, newLine, lineObject, lasermultiply) + lastLine = newLine + }, + G2: function (args, indx, gcp) { + // this is an arc move from lastLine's xy to the new xy. we'll + // show it as a light gray line, but we'll also sub-render the + // arc itself by figuring out the sub-segments + + args.plane = plane // set the plane for this command to whatever the current plane is + + const newLine = { + x: args.x !== undefined ? absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, + y: args.y !== undefined ? absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, + z: args.z !== undefined ? absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, + a: args.a !== undefined ? absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, + e: args.e !== undefined ? absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + f: args.f !== undefined ? args.f : lastLine.f, + s: args.s !== undefined ? args.s : lastLine.s, + t: args.t !== undefined ? args.t : lastLine.t, + arci: args.i ? args.i : null, + arcj: args.j ? args.j : null, + arck: args.k ? args.k : null, + arcr: args.r ? args.r : null, + + arc: true, + clockwise: !args.clockwise ? true : args.clockwise // FIXME : always true ?? + } + //if (args.clockwise === false) newLine.clockwise = args.clockwise + cofg.addSegment(lastLine, newLine, args) + lastLine = newLine + }, + G3: function (args, indx, gcp) { + // this is an arc move from lastLine's xy to the new xy. same + // as G2 but reverse + args.arc = true + args.clockwise = false + args.plane = plane // set the plane for this command to whatever the current plane is + + const newLine = { + x: args.x !== undefined ? absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, + y: args.y !== undefined ? absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, + z: args.z !== undefined ? absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, + a: args.a !== undefined ? absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, + e: args.e !== undefined ? absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + f: args.f !== undefined ? args.f : lastLine.f, + s: args.s !== undefined ? args.s : lastLine.s, + t: args.t !== undefined ? args.t : lastLine.t, + arci: args.i ? args.i : null, + arcj: args.j ? args.j : null, + arck: args.k ? args.k : null, + arcr: args.r ? args.r : null, + + arc: true, + clockwise: !args.clockwise ? true : args.clockwise // FIXME : always true ?? } - newLine.g7 = true - cofg.addLineSegment(lastLine, newLine) + //if (args.clockwise === false) newLine.clockwise = args.clockwise + cofg.addSegment(lastLine, newLine, args) lastLine = newLine + }, + + dirG7: 0, + + G7: function (args, indx) { + // Example: G7 L68 D//////sljasflsfagdxsd,.df9078rhfnxm (68 of em) + // G7 $1 L4 DAAA= + // G7 $0 L4 D2312 + // Move right (if $1) or left (if $0) 51 steps (from L68) + // (the number of steps is found when decoding the data) + // and burn the laser with the intensity in the base64-encoded + // data in D. Data in D is 51 base64-encoded bytes with grayscale + // intensity. When base64-encoded the string becomes 68 bytes long. + // + // SpotSize comes from a previous M649 S100 R0.1 + // where S is intensity (100 is max) and R gives spotsize in mm. + // Actual laser power is then D-value * S-value in every pixel + // A direction change with $0/$1 gives a spotSize long movement in Y + // for the next row. + + var buf = atob(args.d) + + if (typeof args.dollar !== 'undefined') { // Move Y, change direction + this.dirG7 = args.dollar + const newLine = { + x: lastLine.x, + y: lastLine.y + cofg.spotSizeG7, + z: lastLine.z, + a: lastLine.a, + e: lastLine.e, + f: lastLine.f, + s: 100, + t: lastLine.t, + g0: true + } + addLineSegment(lastLine, newLine, lineObject, lasermultiply) + lastLine = newLine + } + for (var i = 0; i < buf.length; i++) { // Process a base64-encoded chunk + const intensity = 255 - buf.charCodeAt(i) // 255 - 0 + const newLine = { + x: lastLine.x + cofg.spotSizeG7 * (this.dirG7 == 1 ? 1 : -1), + y: lastLine.y, + z: lastLine.z, + a: lastLine.a, + e: lastLine.e, + f: lastLine.f, + s: intensity, + t: lastLine.t, + g7: true + } + addLineSegment(lastLine, newLine, lineObject, lasermultiply) + lastLine = newLine + } + }, + + G17: function (args) { + console.log('SETTING XY PLANE') + plane = 'G17' + addFakeSegment(args, lineObject, lastLine, lines) + }, + + G18: function (args) { + console.log('SETTING XZ PLANE') + state.plane = 'G18' + addFakeSegment(args, lineObject, lastLine, lines) + }, + + G19: function (args) { + console.log('SETTING YZ PLANE') + state.plane = 'G19' + addFakeSegment(args, lineObject, lastLine, lines) + }, + + G20: function (args) { + // G21: Set Units to Inches + // We don't really have to do anything since 3d viewer is unit agnostic + // However, we need to set a global property so the trinket decorations + // like toolhead, axes, grid, and extent labels are scaled correctly + // later on when they are drawn after the gcode is rendered + // console.log("SETTING UNITS TO INCHES!!!") + state.isUnitsMm = false // false means inches cuz default is mm + addFakeSegment(args, lineObject, lastLine, lines) + }, + + G21: function (args) { + // G21: Set Units to Millimeters + // Example: G21 + // Units from now on are in millimeters. (This is the RepRap default.) + // console.log("SETTING UNITS TO MM!!!") + state.isUnitsMm = true // true means mm + addFakeSegment(args, lineObject, lastLine, lines) + }, + + G73: function (args, indx, gcp) { + // peck drilling. just treat as g1 + console.log('G73 gcp:', gcp) + gcp.handlers.G1(args) + }, + G90: function (args) { + // G90: Set to Absolute Positioning + // Example: G90 + // All coordinates from now on are absolute relative to the + // origin of the machine. (This is the RepRap default.) + + state.relative = false + addFakeSegment(args, lineObject, lastLine, lines) + }, + + G91: function (args) { + // G91: Set to Relative Positioning + // Example: G91 + // All coordinates from now on are relative to the last position. + + // TODO! + state.relative = true + addFakeSegment(args, lineObject, lastLine, lines) + }, + + G92: function (args) { // E0 + // G92: Set Position + // Example: G92 E0 + // Allows programming of absolute zero point, by reseting the + // current position to the values specified. This would set the + // machine's X coordinate to 10, and the extrude coordinate to 90. + // No physical motion will occur. + + // TODO: Only support E0 + var newLine = lastLine + + cofg.offsetG92.x = (args.x !== undefined ? (args.x === 0 ? newLine.x : newLine.x - args.x) : 0) + cofg.offsetG92.y = (args.y !== undefined ? (args.y === 0 ? newLine.y : newLine.y - args.y) : 0) + cofg.offsetG92.z = (args.z !== undefined ? (args.z === 0 ? newLine.z : newLine.z - args.z) : 0) + cofg.offsetG92.a = (args.a !== undefined ? (args.a === 0 ? newLine.a : newLine.a - args.a) : 0) + cofg.offsetG92.e = (args.e !== undefined ? (args.e === 0 ? newLine.e : newLine.e - args.e) : 0) + + // newLine.x = args.x !== undefined ? args.x + newLine.x : newLine.x + // newLine.y = args.y !== undefined ? args.y + newLine.y : newLine.y + // newLine.z = args.z !== undefined ? args.z + newLine.z : newLine.z + // newLine.e = args.e !== undefined ? args.e + newLine.e : newLine.e + + // console.log("G92", lastLine, newLine, args, cofg.offsetG92) + + // lastLine = newLine + addFakeSegment(args, lineObject, lastLine, lines) + }, + M30: function (args) { + addFakeSegment(args, lineObject, lastLine, lines) + }, + M82: function (args) { + // M82: Set E codes absolute (default) + // Descriped in Sprintrun source code. + + // No-op, so long as M83 is not supported. + addFakeSegment(args, lineObject, lastLine, lines) + }, + + M84: function (args) { + // M84: Stop idle hold + // Example: M84 + // Stop the idle hold on all axis and extruder. In some cases the + // idle hold causes annoying noises, which can be stopped by + // disabling the hold. Be aware that by disabling idle hold during + // printing, you will get quality issues. This is recommended only + // in between or after printjobs. + + // No-op + addFakeSegment(args, lineObject, lastLine, lines) + }, + + M649: function (args) { + // M649: Laser options for Marlin + // M649 S R B2 + // Intensity = lasermultiply? + if (typeof args.r !== 'undefined') { cofg.spotSizeG7 = args.r;} + }, + + // Dual Head 3D Printing Support + T0: function (args) { + // console.log('Found Tool: ', args) + lastLine.t = 0 + addFakeSegment(args, lineObject, lastLine, lines) + }, + + T1: function (args) { + // console.log('Found Tool: ', args) + lastLine.t = 1 + addFakeSegment(args, lineObject, lastLine, lines) + }, + + 'default': function (args, info) { + // if (!args.isComment) + // console.log('Unknown command:', args.cmd, args, info) + addFakeSegment(args, lineObject, lastLine, lines) } - }, - - G17: function (args) { - console.log('SETTING XY PLANE') - plane = 'G17' - cofg.addFakeSegment(args) - }, - - G18: function (args) { - console.log('SETTING XZ PLANE') - plane = 'G18' - cofg.addFakeSegment(args) - }, - - G19: function (args) { - console.log('SETTING YZ PLANE') - plane = 'G19' - cofg.addFakeSegment(args) - }, - - G20: function (args) { - // G21: Set Units to Inches - // We don't really have to do anything since 3d viewer is unit agnostic - // However, we need to set a global property so the trinket decorations - // like toolhead, axes, grid, and extent labels are scaled correctly - // later on when they are drawn after the gcode is rendered - // console.log("SETTING UNITS TO INCHES!!!") - cofg.isUnitsMm = false // false means inches cuz default is mm - cofg.addFakeSegment(args) - }, - - G21: function (args) { - // G21: Set Units to Millimeters - // Example: G21 - // Units from now on are in millimeters. (This is the RepRap default.) - // console.log("SETTING UNITS TO MM!!!") - cofg.isUnitsMm = true // true means mm - cofg.addFakeSegment(args) - }, - - G73: function (args, indx, gcp) { - // peck drilling. just treat as g1 - console.log('G73 gcp:', gcp) - gcp.handlers.G1(args) - }, - G90: function (args) { - // G90: Set to Absolute Positioning - // Example: G90 - // All coordinates from now on are absolute relative to the - // origin of the machine. (This is the RepRap default.) - - relative = false - cofg.addFakeSegment(args) - }, - - G91: function (args) { - // G91: Set to Relative Positioning - // Example: G91 - // All coordinates from now on are relative to the last position. - - // TODO! - relative = true - cofg.addFakeSegment(args) - }, - - G92: function (args) { // E0 - // G92: Set Position - // Example: G92 E0 - // Allows programming of absolute zero point, by reseting the - // current position to the values specified. This would set the - // machine's X coordinate to 10, and the extrude coordinate to 90. - // No physical motion will occur. - - // TODO: Only support E0 - var newLine = lastLine - - cofg.offsetG92.x = (args.x !== undefined ? (args.x === 0 ? newLine.x : newLine.x - args.x) : 0) - cofg.offsetG92.y = (args.y !== undefined ? (args.y === 0 ? newLine.y : newLine.y - args.y) : 0) - cofg.offsetG92.z = (args.z !== undefined ? (args.z === 0 ? newLine.z : newLine.z - args.z) : 0) - cofg.offsetG92.a = (args.a !== undefined ? (args.a === 0 ? newLine.a : newLine.a - args.a) : 0) - cofg.offsetG92.e = (args.e !== undefined ? (args.e === 0 ? newLine.e : newLine.e - args.e) : 0) - - // newLine.x = args.x !== undefined ? args.x + newLine.x : newLine.x - // newLine.y = args.y !== undefined ? args.y + newLine.y : newLine.y - // newLine.z = args.z !== undefined ? args.z + newLine.z : newLine.z - // newLine.e = args.e !== undefined ? args.e + newLine.e : newLine.e - - // console.log("G92", lastLine, newLine, args, cofg.offsetG92) - - // lastLine = newLine - cofg.addFakeSegment(args) - }, - M30: function (args) { - cofg.addFakeSegment(args) - }, - M82: function (args) { - // M82: Set E codes absolute (default) - // Descriped in Sprintrun source code. - - // No-op, so long as M83 is not supported. - cofg.addFakeSegment(args) - }, - - M84: function (args) { - // M84: Stop idle hold - // Example: M84 - // Stop the idle hold on all axis and extruder. In some cases the - // idle hold causes annoying noises, which can be stopped by - // disabling the hold. Be aware that by disabling idle hold during - // printing, you will get quality issues. This is recommended only - // in between or after printjobs. - - // No-op - cofg.addFakeSegment(args) - }, - - M649: function (args) { - // M649: Laser options for Marlin - // M649 S R B2 - // Intensity = lasermultiply? - if (typeof args.r !== 'undefined') { cofg.spotSizeG7 = args.r;} - }, - - // Dual Head 3D Printing Support - T0: function (args) { - // console.log('Found Tool: ', args) - lastLine.t = 0 - cofg.addFakeSegment(args) - }, - - T1: function (args) { - // console.log('Found Tool: ', args) - lastLine.t = 1 - cofg.addFakeSegment(args) - }, - - 'default': function (args, info) { - // if (!args.isComment) - // console.log('Unknown command:', args.cmd, args, info) - cofg.addFakeSegment(args) - }, -}) -// console.log("Just before parser.parse: "+ gcode) -parser.parse(gcode) + } } diff --git a/src/parseFunctions.js b/src/parseFunctions.js index 054bc73..857a8e0 100644 --- a/src/parseFunctions.js +++ b/src/parseFunctions.js @@ -1,4 +1,4 @@ -function drawArc(aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, plane) { +function drawArc (aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, plane) { // console.log("drawArc:", aX, aY, aZ, aRadius, aStartAngle, aEndAngle, aClockwise) var ac = new THREE.ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) // console.log("ac:", ac) @@ -23,7 +23,6 @@ function drawArc(aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, return aco } - function drawArcFrom2PtsAndCenter (vp1, vp2, vpArc, args) { // console.log("drawArcFrom2PtsAndCenter. vp1:", vp1, "vp2:", vp2, "vpArc:", vpArc, "args:", args) @@ -102,7 +101,7 @@ function drawArcFrom2PtsAndCenter (vp1, vp2, vpArc, args) { return threeObj } -function addSegment (p1, p2, args) { +export function addSegment (p1, p2, args) { closeLineSegment() // console.log("") // console.log("addSegment p2:", p2) @@ -230,7 +229,7 @@ function addSegment (p1, p2, args) { x: p2.arci ? p1.x + p2.arci : p1.x, y: p2.arcj ? p1.y + p2.arcj : p1.y, z: p2.arck ? p1.z + p2.arck : p1.z, - ¨ } + ¨ } else*/ var pArc = { x: p2.arci ? p1.x + p2.arci : p1.x, @@ -413,7 +412,22 @@ function addSegment (p1, p2, args) { // console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) } -function addLineSegment (p1, p2) { +export function addFakeSegment (args, lineObject, lastLine, lines) { + closeLineSegment(lineObject) + // line.args = args + const arg2 = { + isFake: true, + text: args.text, + indx: args.indx, + isComment: arg.text.match(/^(;|\(|<)/) + } + lines.push({ + p2: lastLine, // since this is fake, just use lastLine as xyz + 'args': arg2 + }) +} + +export function addLineSegment (p1, p2, lineObject, lasermultiply, bufSize) { var i = lineObject.nLines * 6 // lineObject.vertexBuf[i+0] = p1.x // Vertices // lineObject.vertexBuf[i+1] = p1.y @@ -422,11 +436,11 @@ function addLineSegment (p1, p2) { // lineObject.vertexBuf[i+4] = p2.y // lineObject.vertexBuf[i+5] = p2.z - if (p1.a != 0 || p2.a != 0) { // A axis: rotate around X + if (p1.a !== 0 || p2.a !== 0) { // A axis: rotate around X var R1 = Math.sqrt(p1.y * p1.y + p1.z * p1.z) var R2 = Math.sqrt(p2.y * p2.y + p2.z * p2.z) - var a1 = p1.y == 0 ? Math.sign(p1.z) * 90 : Math.atan2(p1.z, p1.y) * 180.0 / Math.PI - var a2 = p2.y == 0 ? Math.sign(p2.z) * 90 : Math.atan2(p2.z, p2.y) * 180.0 / Math.PI + var a1 = p1.y === 0 ? Math.sign(p1.z) * 90 : Math.atan2(p1.z, p1.y) * 180.0 / Math.PI + var a2 = p2.y === 0 ? Math.sign(p2.z) * 90 : Math.atan2(p2.z, p2.y) * 180.0 / Math.PI lineObject.vertexBuf[i + 0] = p1.x lineObject.vertexBuf[i + 1] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) lineObject.vertexBuf[i + 2] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) @@ -451,15 +465,8 @@ function addLineSegment (p1, p2) { } // console.log("Segment " + p1) - var dist = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)) - totalDist += dist - timeMinutes = dist / p2.f - totalTime += timeMinutes - totaltimemax = totalTime * 60 - var col var intensity - var lasermultiply = $('#lasermultiply').val() || 100 if (p2.g0) { // g0 col = {r: 0, g: 1, b: 0} intensity = 1.0 - p2.s / lasermultiply // lasermultiply @@ -483,43 +490,36 @@ function addLineSegment (p1, p2) { lineObject.nLines++ - if (lineObject.nLines == bufSize) - closeLineSegment() -} + if (lineObject.nLines === bufSize) + closeLineSegment(lineObject) + const dist = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)) + // totalDist += dist + // timeMinutes = dist / p2.f + // totalTime += timeMinutes + // totaltimemax = totalTime * 60 + + return { + dist + } +} -function closeLineSegment () { - if (lineObject.nLines == 0) +export function closeLineSegment (lineObject) { + if (lineObject.nLines === 0) return - var vertices = new Float32Array(6 * lineObject.nLines) - var colors = new Float32Array(6 * lineObject.nLines) + const vertices = new Float32Array(6 * lineObject.nLines) + const colors = new Float32Array(6 * lineObject.nLines) vertices.set(lineObject.vertexBuf.subarray(0, lineObject.nLines * 6)) colors.set(lineObject.colorBuf.subarray(0, lineObject.nLines * 6)) - var geometry = new THREE.BufferGeometry() + const lines = {vertices, colors} + lineObjects.add(lines) // Feed the objects to "object" in doChunk() + lineObject.nLines = 0 + /*var geometry = new THREE.BufferGeometry() geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3)) geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3)) - var lines = new THREE.Line(geometry, material) - lineObjects.add(lines); // Feed the objects to "object" in doChunk() - - lineObject.nLines = 0 -} - - -function addFakeSegment(args) { - closeLineSegment() - // line.args = args - var arg2 = { - isFake: true, - text: args.text, - indx: args.indx - } - if (arg2.text.match(/^(;|\(|<)/)) arg2.isComment = true - lines.push({ - p2: lastLine, // since this is fake, just use lastLine as xyz - 'args': arg2 - }) + var lines = new THREE.Line(geometry, material)*/ } diff --git a/src/parseLine.js b/src/parseLine.js index a201f6d..3e3e658 100644 --- a/src/parseLine.js +++ b/src/parseLine.js @@ -1,4 +1,4 @@ -export function parseLine (text, info) { +export function parseLine (text, info, handlers) { // console.log('Parsing: ',text) const origtext = text @@ -24,6 +24,7 @@ export function parseLine (text, info) { text = text.replace(/\(.*?\)/g, '') } + //after this , more tokenizing/ calling handlers if (text && !isComment) { if (!isG7) text = text.replace(/(;|\().*$/, ''); // strip off end of line comment ; or () trailing @@ -122,7 +123,6 @@ export function parseLine (text, info) { 'indx': info, 'isComment': isComment } - var handler = handlers['default'] - return handler(args, info, this) + return handlers['default'](args, info, this) } } From 2c1d2c817ab90e7517712982e5d833548036a237 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sat, 5 Nov 2016 13:51:11 +0100 Subject: [PATCH 05/34] refactor(geometries): further cleanup of 'geometries' (arcs, segments): - seperated segmeents and arcs - moved to sub dir - major cleanup / upgrade of the code : more es6, less three.js (still wip) --- src/geometries/arcs.js | 106 +++++++ src/{ => geometries}/geometryUtils.js | 0 .../segments.js} | 265 ++++++------------ 3 files changed, 189 insertions(+), 182 deletions(-) create mode 100644 src/geometries/arcs.js rename src/{ => geometries}/geometryUtils.js (100%) rename src/{parseFunctions.js => geometries/segments.js} (64%) diff --git a/src/geometries/arcs.js b/src/geometries/arcs.js new file mode 100644 index 0000000..ab761a1 --- /dev/null +++ b/src/geometries/arcs.js @@ -0,0 +1,106 @@ +export function drawArc (aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, plane) { + // console.log("drawArc:", aX, aY, aZ, aRadius, aStartAngle, aEndAngle, aClockwise) + var ac = new THREE.ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) + // console.log("ac:", ac) + var acmat = new THREE.LineBasicMaterial({ + color: 0x00aaff, + opacity: 0.5, + transparent: true + }) + var acgeo = new THREE.Geometry() + var ctr = 0 + var z = aZ + ac.getPoints(20).forEach(function (v) { + // console.log(v) + z = (((endaZ - aZ) / 20) * ctr) + aZ + acgeo.vertices.push(new THREE.Vector3(v.x, v.y, z)) + ctr++ + }) + var aco = new THREE.Line(acgeo, acmat) + // aco.position.set(pArc.x, pArc.y, pArc.z) + // console.log("aco:", aco) + this.extraObjects[plane].push(aco) + return aco +} + +export function drawArcFrom2PtsAndCenter (vp1, vp2, vpArc, args) { + // console.log("drawArcFrom2PtsAndCenter. vp1:", vp1, "vp2:", vp2, "vpArc:", vpArc, "args:", args) + + // var radius = vp1.distanceTo(vpArc) + // console.log("radius:", radius) + + // Find angle + const p1deltaX = vpArc.x - vp1.x + const p1deltaY = vpArc.y - vp1.y + const p1deltaZ = vpArc.z - vp1.z + + const p2deltaX = vpArc.x - vp2.x + const p2deltaY = vpArc.y - vp2.y + const p2deltaZ = vpArc.z - vp2.z + + let anglepArcp1 + let anglepArcp2 + switch (args.plane) { + case 'G18': + anglepArcp1 = Math.atan(p1deltaZ / p1deltaX) + anglepArcp2 = Math.atan(p2deltaZ / p2deltaX) + break + case 'G19': + anglepArcp1 = Math.atan(p1deltaZ / p1deltaY) + anglepArcp2 = Math.atan(p2deltaZ / p2deltaY) + break + default: + anglepArcp1 = Math.atan(p1deltaY / p1deltaX) + anglepArcp2 = Math.atan(p2deltaY / p2deltaX) + } + + // Draw arc from arc center + const radius = vpArc.distanceTo(vp1) + const radius2 = vpArc.distanceTo(vp2) + // console.log("radius:", radius) + + if (Number((radius).toFixed(2)) != Number((radius2).toFixed(2))) { + console.log('Radiuses not equal. r1:', radius, ', r2:', radius2, ' with args:', args, ' rounded vals r1:', Number((radius).toFixed(2)), ', r2:', Number((radius2).toFixed(2))) + } + + // arccurve + var clwise = args.clockwise + //if (args.clockwise === false) clwise = false + + switch (args.plane) { + case 'G19': + if (p1deltaY >= 0) anglepArcp1 += Math.PI + if (p2deltaY >= 0) anglepArcp2 += Math.PI + break + default: + if (p1deltaX >= 0) anglepArcp1 += Math.PI + if (p2deltaX >= 0) anglepArcp2 += Math.PI + } + + if (anglepArcp1 === anglepArcp2 && clwise === false) + let obj = undefined + // Draw full circle if angles are both zero, + // start & end points are same point... I think + switch (args.plane) { + case 'G18': + obj = drawArc(vpArc.x, vpArc.z, (-1 * vp1.y), (-1 * vp2.y), radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G18') + break + case 'G19': + obj = drawArc(vpArc.y, vpArc.z, vp1.x, vp2.x, radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G19') + break + default: + obj = drawArc(vpArc.x, vpArc.y, vp1.z, vp2.z, radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G17') + } + else + switch (args.plane) { + case 'G18': + obj = drawArc(vpArc.x, vpArc.z, (-1 * vp1.y), (-1 * vp2.y), radius, anglepArcp1, anglepArcp2, clwise, 'G18') + break + case 'G19': + obj = drawArc(vpArc.y, vpArc.z, vp1.x, vp2.x, radius, anglepArcp1, anglepArcp2, clwise, 'G19') + break + default: + obj = drawArc(vpArc.x, vpArc.y, vp1.z, vp2.z, radius, anglepArcp1, anglepArcp2, clwise, 'G17') + } + return threeObj +} diff --git a/src/geometryUtils.js b/src/geometries/geometryUtils.js similarity index 100% rename from src/geometryUtils.js rename to src/geometries/geometryUtils.js diff --git a/src/parseFunctions.js b/src/geometries/segments.js similarity index 64% rename from src/parseFunctions.js rename to src/geometries/segments.js index 857a8e0..c1e4951 100644 --- a/src/parseFunctions.js +++ b/src/geometries/segments.js @@ -1,113 +1,15 @@ -function drawArc (aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, plane) { - // console.log("drawArc:", aX, aY, aZ, aRadius, aStartAngle, aEndAngle, aClockwise) - var ac = new THREE.ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) - // console.log("ac:", ac) - var acmat = new THREE.LineBasicMaterial({ - color: 0x00aaff, - opacity: 0.5, - transparent: true - }) - var acgeo = new THREE.Geometry() - var ctr = 0 - var z = aZ - ac.getPoints(20).forEach(function (v) { - // console.log(v) - z = (((endaZ - aZ) / 20) * ctr) + aZ - acgeo.vertices.push(new THREE.Vector3(v.x, v.y, z)) - ctr++ - }) - var aco = new THREE.Line(acgeo, acmat) - // aco.position.set(pArc.x, pArc.y, pArc.z) - // console.log("aco:", aco) - this.extraObjects[plane].push(aco) - return aco -} - -function drawArcFrom2PtsAndCenter (vp1, vp2, vpArc, args) { - // console.log("drawArcFrom2PtsAndCenter. vp1:", vp1, "vp2:", vp2, "vpArc:", vpArc, "args:", args) - - // var radius = vp1.distanceTo(vpArc) - // console.log("radius:", radius) - - // Find angle - var p1deltaX = vpArc.x - vp1.x - var p1deltaY = vpArc.y - vp1.y - var p1deltaZ = vpArc.z - vp1.z - - var p2deltaX = vpArc.x - vp2.x - var p2deltaY = vpArc.y - vp2.y - var p2deltaZ = vpArc.z - vp2.z - - switch (args.plane) { - case 'G18': - var anglepArcp1 = Math.atan(p1deltaZ / p1deltaX) - var anglepArcp2 = Math.atan(p2deltaZ / p2deltaX) - break - case 'G19': - var anglepArcp1 = Math.atan(p1deltaZ / p1deltaY) - var anglepArcp2 = Math.atan(p2deltaZ / p2deltaY) - break - default: - var anglepArcp1 = Math.atan(p1deltaY / p1deltaX) - var anglepArcp2 = Math.atan(p2deltaY / p2deltaX) - } - - // Draw arc from arc center - var radius = vpArc.distanceTo(vp1) - var radius2 = vpArc.distanceTo(vp2) - // console.log("radius:", radius) - - if (Number((radius).toFixed(2)) != Number((radius2).toFixed(2))) console.log('Radiuses not equal. r1:', radius, ', r2:', radius2, ' with args:', args, ' rounded vals r1:', Number((radius).toFixed(2)), ', r2:', Number((radius2).toFixed(2))) - - // arccurve - var clwise = true - if (args.clockwise === false) clwise = false - // if (anglepArcp1 < 0) clockwise = false - - switch (args.plane) { - case 'G19': - if (p1deltaY >= 0) anglepArcp1 += Math.PI - if (p2deltaY >= 0) anglepArcp2 += Math.PI - break - default: - if (p1deltaX >= 0) anglepArcp1 += Math.PI - if (p2deltaX >= 0) anglepArcp2 += Math.PI - } - - if (anglepArcp1 === anglepArcp2 && clwise === false) - // Draw full circle if angles are both zero, - // start & end points are same point... I think - switch (args.plane) { - case 'G18': - var threeObj = this.drawArc(vpArc.x, vpArc.z, (-1 * vp1.y), (-1 * vp2.y), radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G18') - break - case 'G19': - var threeObj = this.drawArc(vpArc.y, vpArc.z, vp1.x, vp2.x, radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G19') - break - default: - var threeObj = this.drawArc(vpArc.x, vpArc.y, vp1.z, vp2.z, radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G17') - } - else - switch (args.plane) { - case 'G18': - var threeObj = this.drawArc(vpArc.x, vpArc.z, (-1 * vp1.y), (-1 * vp2.y), radius, anglepArcp1, anglepArcp2, clwise, 'G18') - break - case 'G19': - var threeObj = this.drawArc(vpArc.y, vpArc.z, vp1.x, vp2.x, radius, anglepArcp1, anglepArcp2, clwise, 'G19') - break - default: - var threeObj = this.drawArc(vpArc.x, vpArc.y, vp1.z, vp2.z, radius, anglepArcp1, anglepArcp2, clwise, 'G17') - } - return threeObj -} +import {getLineGroup} from './foo' export function addSegment (p1, p2, args) { closeLineSegment() + let bbbox = [] + let bbbox2 = [] + // console.log("") // console.log("addSegment p2:", p2) // add segment to array for later use - var group = getLineGroup(p2, args) - var geometry = group.geometry + let group = getLineGroup(p2, args) + let geometry = group.geometry group.segmentCount++ // see if we need to draw an arc @@ -120,12 +22,12 @@ export function addSegment (p1, p2, args) { // the start, the end, and the center of the arc circle // radius is dist from p1 x/y/z to pArc x/y/z // if(args.clockwise === false || args.cmd === "G3"){ - // var vp2 = new THREE.Vector3(p1.x, p1.y, p1.z) - // var vp1 = new THREE.Vector3(p2.x, p2.y, p2.z) + // var vp2 = [p1.x, p1.y, p1.z] + // var vp1 = [p2.x, p2.y, p2.z] // } // else { - var vp1 = new THREE.Vector3(p1.x, p1.y, p1.z) - var vp2 = new THREE.Vector3(p2.x, p2.y, p2.z) + const vp1 = [p1.x, p1.y, p1.z] + const vp2 = [p2.x, p2.y, p2.z] // } var vpArc @@ -135,18 +37,16 @@ export function addSegment (p1, p2, args) { if (args.r != null) { // console.log("looks like we have an arc with R specified. args:", args) // console.log("anglepArcp1:", anglepArcp1, "anglepArcp2:", anglepArcp2) - - radius = parseFloat(args.r) - + const radius = parseFloat(args.r) // First, find the distance between points 1 and 2. We'll call that q, // and it's given by sqrt((x2-x1)^2 + (y2-y1)^2). - var q = Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(p2.z - p1.z, 2)) + const q = Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(p2.z - p1.z, 2)) // Second, find the point halfway between your two points. We'll call it // (x3, y3). x3 = (x1+x2)/2 and y3 = (y1+y2)/2. - var x3 = (p1.x + p2.x) / 2 - var y3 = (p1.y + p2.y) / 2 - var z3 = (p1.z + p2.z) / 2 + const x3 = (p1.x + p2.x) / 2 + const y3 = (p1.y + p2.y) / 2 + const z3 = (p1.z + p2.z) / 2 // There will be two circle centers as a result of this, so // we will have to pick the correct one. In gcode we can get @@ -157,10 +57,12 @@ export function addSegment (p1, p2, args) { // The other will be: // x = x3 - sqrt(r^2-(q/2)^2)*(y1-y2)/q // y = y3 - sqrt(r^2-(q/2)^2)*(x2-x1)/q - var pArc_1 = undefined - var pArc_2 = undefined - var calc = Math.sqrt((radius * radius) - Math.pow(q / 2, 2)) - var angle_point = undefined + let pArc_1 + let pArc_2 + let calc = Math.sqrt((radius * radius) - Math.pow(q / 2, 2)) + let angle_point + let cw + let ccw switch (args.plane) { case 'G18': @@ -172,14 +74,15 @@ export function addSegment (p1, p2, args) { x: x3 - calc * (p1.z - p2.z) / q, y: y3 - calc * (p2.y - p1.y) / q, z: z3 - calc * (p2.x - p1.x) / q } + angle_point = Math.atan2(p1.z, p1.x) - Math.atan2(p2.z, p2.x) if (((p1.x - pArc_1.x) * (p1.z + pArc_1.z)) + ((pArc_1.x - p2.x) * (pArc_1.z + p2.z)) >= ((p1.x - pArc_2.x) * (p1.z + pArc_2.z)) + ((pArc_2.x - p2.x) * (pArc_2.z + p2.z))) { - var cw = pArc_1 - var ccw = pArc_2 + cw = pArc_1 + ccw = pArc_2 } else { - var cw = pArc_2 - var ccw = pArc_1 + cw = pArc_2 + ccw = pArc_1 } break case 'G19': @@ -194,11 +97,11 @@ export function addSegment (p1, p2, args) { if (((p1.y - pArc_1.y) * (p1.z + pArc_1.z)) + ((pArc_1.y - p2.y) * (pArc_1.z + p2.z)) >= ((p1.y - pArc_2.y) * (p1.z + pArc_2.z)) + ((pArc_2.y - p2.y) * (pArc_2.z + p2.z))) { - var cw = pArc_1 - var ccw = pArc_2 + cw = pArc_1 + ccw = pArc_2 } else { - var cw = pArc_2 - var ccw = pArc_1 + cw = pArc_2 + ccw = pArc_1 } break default: @@ -212,16 +115,19 @@ export function addSegment (p1, p2, args) { z: z3 - calc * (p2.z - p1.z) / q } if (((p1.x - pArc_1.x) * (p1.y + pArc_1.y)) + ((pArc_1.x - p2.x) * (pArc_1.y + p2.y)) >= ((p1.x - pArc_2.x) * (p1.y + pArc_2.y)) + ((pArc_2.x - p2.x) * (pArc_2.y + p2.y))) { - var cw = pArc_1 - var ccw = pArc_2 + cw = pArc_1 + ccw = pArc_2 } else { - var cw = pArc_2 - var ccw = pArc_1 + cw = pArc_2 + ccw = pArc_1 } } - if ((p2.clockwise === true && radius >= 0) || (p2.clockwise === false && radius < 0)) vpArc = new THREE.Vector3(cw.x, cw.y, cw.z) - else vpArc = new THREE.Vector3(ccw.x, ccw.y, ccw.z) + if ((p2.clockwise === true && radius >= 0) || (p2.clockwise === false && radius < 0)) + { + vpArc = [cw.x, cw.y, cw.z] + } + else vpArc = [ccw.x, ccw.y, ccw.z] } else { // this code deals with IJK gcode commands /*if(args.clockwise === false || args.cmd === "G3") @@ -231,38 +137,34 @@ export function addSegment (p1, p2, args) { z: p2.arck ? p1.z + p2.arck : p1.z, ¨ } else*/ - var pArc = { + const pArc = { x: p2.arci ? p1.x + p2.arci : p1.x, y: p2.arcj ? p1.y + p2.arcj : p1.y, - z: p2.arck ? p1.z + p2.arck : p1.z, + z: p2.arck ? p1.z + p2.arck : p1.z } - // console.log("new pArc:", pArc) - vpArc = new THREE.Vector3(pArc.x, pArc.y, pArc.z) - // console.log("vpArc:", vpArc) + vpArc = [pArc.x, pArc.y, pArc.z] } - var threeObjArc = this.drawArcFrom2PtsAndCenter(vp1, vp2, vpArc, args) + const threeObjArc = this.drawArcFrom2PtsAndCenter(vp1, vp2, vpArc, args) // still push the normal p1/p2 point for debug p2.g2 = true p2.threeObjArc = threeObjArc - group = this.getLineGroup(p2, args) + group = getLineGroup(p2, args) // these golden lines showing start/end of a g2 or g3 arc were confusing people // so hiding them for now. jlauer 8/15/15 /* geometry = group.geometry geometry.vertices.push( - new THREE.Vector3(p1.x, p1.y, p1.z)) + [p1.x, p1.y, p1.z]) geometry.vertices.push( - new THREE.Vector3(p2.x, p2.y, p2.z)) + [p2.x, p2.y, p2.z)) geometry.colors.push(group.color) geometry.colors.push(group.color) */ } else { - geometry.vertices.push( - new THREE.Vector3(p1.x, p1.y, p1.z)) - geometry.vertices.push( - new THREE.Vector3(p2.x, p2.y, p2.z)) + geometry.vertices.push([p1.x, p1.y, p1.z]) + geometry.vertices.push([p2.x, p2.y, p2.z]) geometry.colors.push(group.color) geometry.colors.push(group.color) } @@ -298,10 +200,11 @@ export function addSegment (p1, p2, args) { bbbox2.max.y = Math.max(bbbox2.max.y, p2.y) bbbox2.max.z = Math.max(bbbox2.max.z, p2.z) - // NEW METHOD OF CREATING THREE.JS OBJECTS - // create new approach for three.js objects which is - // a unique object for each line of gcode, including g2/g3's - // make sure userData is good too + /* NEW METHOD OF CREATING OBJECTS + create new approach for objects which is + a unique object for each line of gcode, including g2/g3's + make sure userData is good too + */ var gcodeObj if (p2.arc) { @@ -309,7 +212,12 @@ export function addSegment (p1, p2, args) { gcodeObj = p2.threeObjArc } else { // make a line - var color = 0X0000ff + let color = 0X0000ff + /*const {extruding, g0, g2, arc} = p2 + const colorMap = { + extruding: 0xff00ff, + g0: 0x00ff00 + }*/ if (p2.extruding) { color = 0xff00ff @@ -326,13 +234,6 @@ export function addSegment (p1, p2, args) { opacity: 0.5, transparent: true }) - - // var geometry = new THREE.Geometry() - // geometry.vertices.push( - // new THREE.Vector3( p1.x, p1.y, p1.z ), - // ew THREE.Vector3( p2.x, p2.y, p2.z ) - // ) - var line = new THREE.Line(geometry, material) gcodeObj = line } @@ -343,7 +244,9 @@ export function addSegment (p1, p2, args) { // DISTANCE CALC // add distance so we can calc estimated time to run // see if arc - var dist = 0 + let dist = 0 + let a + let b if (p2.arc) { // calc dist of all lines // console.log("this is an arc to calc dist for. p2.threeObjArc:", p2.threeObjArc, "p2:", p2) @@ -357,20 +260,23 @@ export function addSegment (p1, p2, args) { // console.log("tad2:", tad2) // just do straight line calc - var a = new THREE.Vector3(p1.x, p1.y, p1.z) - var b = new THREE.Vector3(p2.x, p2.y, p2.z) - var straightDist = a.distanceTo(b) - + a = [p1.x, p1.y, p1.z] + b = [p2.x, p2.y, p2.z] + // const straightDist = a.distanceTo(b) // console.log("diff of straight line calc vs arc sum. straightDist:", straightDist) - dist = tad2 } else { // just do straight line calc - var a = new THREE.Vector3(p1.x, p1.y, p1.z) - var b = new THREE.Vector3(p2.x, p2.y, p2.z) + a = [p1.x, p1.y, p1.z] + b = [p2.x, p2.y, p2.z] dist = a.distanceTo(b) } + // Handle Laser Sxxx parameter + sv = args.s + // console.log(sv) + + //time distance computation if (dist > 0) { totalDist += dist } @@ -395,10 +301,6 @@ export function addSegment (p1, p2, args) { timeMinutes = timeMinutes * 1.32 } - // Handle Laser Sxxx parameter - sv = args.s - // console.log(sv) - totalTime += timeMinutes p2.feedrate = args.feedrate @@ -410,6 +312,10 @@ export function addSegment (p1, p2, args) { // console.log('Total Time'+totalTime) totaltimemax += (timeMinutes * 60) // console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) + return { + dist, + timeMinutes + } } export function addFakeSegment (args, lineObject, lastLine, lines) { @@ -419,16 +325,16 @@ export function addFakeSegment (args, lineObject, lastLine, lines) { isFake: true, text: args.text, indx: args.indx, - isComment: arg.text.match(/^(;|\(|<)/) + isComment: args.text.match(/^(;|\(|<)/) } lines.push({ p2: lastLine, // since this is fake, just use lastLine as xyz - 'args': arg2 + args: arg2 }) } export function addLineSegment (p1, p2, lineObject, lasermultiply, bufSize) { - var i = lineObject.nLines * 6 + let i = lineObject.nLines * 6 // lineObject.vertexBuf[i+0] = p1.x // Vertices // lineObject.vertexBuf[i+1] = p1.y // lineObject.vertexBuf[i+2] = p1.z @@ -490,23 +396,24 @@ export function addLineSegment (p1, p2, lineObject, lasermultiply, bufSize) { lineObject.nLines++ - if (lineObject.nLines === bufSize) + if (lineObject.nLines === bufSize) { closeLineSegment(lineObject) + } const dist = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)) // totalDist += dist // timeMinutes = dist / p2.f // totalTime += timeMinutes // totaltimemax = totalTime * 60 - return { dist } } export function closeLineSegment (lineObject) { - if (lineObject.nLines === 0) + if (lineObject.nLines === 0) { return + } const vertices = new Float32Array(6 * lineObject.nLines) const colors = new Float32Array(6 * lineObject.nLines) @@ -516,10 +423,4 @@ export function closeLineSegment (lineObject) { const lines = {vertices, colors} lineObjects.add(lines) // Feed the objects to "object" in doChunk() lineObject.nLines = 0 - /*var geometry = new THREE.BufferGeometry() - - geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3)) - geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3)) - - var lines = new THREE.Line(geometry, material)*/ } From 39231a42d9f43edf2cf65afb7ddcdf6a70871592 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sat, 5 Nov 2016 13:52:26 +0100 Subject: [PATCH 06/34] refactor(gcodeHandlers): continued cleanup: - more data moved to 'state' variable - removed redundant code when neeeded - updated arc/segement handling to match their new apis - other various minor cleanups --- src/gcodeHandlers.js | 95 +++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js index df5b0e7..9a21e66 100644 --- a/src/gcodeHandlers.js +++ b/src/gcodeHandlers.js @@ -1,16 +1,20 @@ -import {absolute, delta} from './utils' +import { absolute, delta } from './utils' +import { addSegment, addLineSegment, addFakeSegment } from './parseFunctions' -export default function makeHandlers(){ - - let state = { +export default function makeHandlers (params) { + let state = { isUnitsMm: true, plane: undefined, - relative: true + relative: true, + offsetG92: {x: 0, y: 0, z: 0, a: 0, e: 0}, + spotSizeG7: undefined, + dirG7: 0 } const lasermultiply = 100 const lineObject = {} const lastLine = undefined - //EEK !! var lasermultiply = $('#lasermultiply').val() || 100 + const lines = undefined + // EEK !! var lasermultiply = $('#lasermultiply').val() || 100 const handlers = { // set the g92 offsets for the parser - defaults to no offset @@ -19,16 +23,16 @@ export default function makeHandlers(){ // So, let's color it uniquely to indicate it's just a toolhead move. G0: function (args, indx) { const newLine = { - x: args.x !== undefined ? absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, - y: args.y !== undefined ? absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, - z: args.z !== undefined ? absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, - a: args.a !== undefined ? absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, - e: args.e !== undefined ? absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, + y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, + z: args.z !== undefined ? absolute(lastLine.z, args.z) + state.offsetG92.z : lastLine.z, + a: args.a !== undefined ? absolute(lastLine.a, args.a) + state.offsetG92.a : lastLine.a, + e: args.e !== undefined ? absolute(lastLine.e, args.e) + state.offsetG92.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: 100, + g0: true } - newLine.g0 = true - addLineSegment (lastLine, newLine, lineObject, lasermultiply) + addLineSegment(lastLine, newLine, lineObject, lasermultiply) lastLine = newLine }, G1: function (args, indx) { @@ -41,14 +45,15 @@ export default function makeHandlers(){ // 22.4 mm. const newLine = { - x: args.x !== undefined ? absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, - y: args.y !== undefined ? absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, - z: args.z !== undefined ? absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, - a: args.a !== undefined ? absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, - e: args.e !== undefined ? absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, + y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, + z: args.z !== undefined ? absolute(lastLine.z, args.z) + state.offsetG92.z : lastLine.z, + a: args.a !== undefined ? absolute(lastLine.a, args.a) + state.offsetG92.a : lastLine.a, + e: args.e !== undefined ? absolute(lastLine.e, args.e) + state.offsetG92.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: args.s !== undefined ? args.s : lastLine.s, t: args.t !== undefined ? args.t : lastLine.t, + g1: true } /* layer change detection is or made by watching Z, it's made by watching when we extrude at a new Z position */ @@ -56,7 +61,6 @@ export default function makeHandlers(){ newLine.extruding = delta(lastLine.e, newLine.e) > 0 if (layer == undefined || newLine.z != layer.z) cofg.newLayer(newLine) } - newLine.g1 = true addLineSegment(lastLine, newLine, lineObject, lasermultiply) lastLine = newLine }, @@ -68,11 +72,11 @@ export default function makeHandlers(){ args.plane = plane // set the plane for this command to whatever the current plane is const newLine = { - x: args.x !== undefined ? absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, - y: args.y !== undefined ? absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, - z: args.z !== undefined ? absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, - a: args.a !== undefined ? absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, - e: args.e !== undefined ? absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, + y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, + z: args.z !== undefined ? absolute(lastLine.z, args.z) + state.offsetG92.z : lastLine.z, + a: args.a !== undefined ? absolute(lastLine.a, args.a) + state.offsetG92.a : lastLine.a, + e: args.e !== undefined ? absolute(lastLine.e, args.e) + state.offsetG92.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: args.s !== undefined ? args.s : lastLine.s, t: args.t !== undefined ? args.t : lastLine.t, @@ -84,8 +88,8 @@ export default function makeHandlers(){ arc: true, clockwise: !args.clockwise ? true : args.clockwise // FIXME : always true ?? } - //if (args.clockwise === false) newLine.clockwise = args.clockwise - cofg.addSegment(lastLine, newLine, args) + // if (args.clockwise === false) newLine.clockwise = args.clockwise + addSegment(lastLine, newLine, args) lastLine = newLine }, G3: function (args, indx, gcp) { @@ -96,11 +100,11 @@ export default function makeHandlers(){ args.plane = plane // set the plane for this command to whatever the current plane is const newLine = { - x: args.x !== undefined ? absolute(lastLine.x, args.x) + cofg.offsetG92.x : lastLine.x, - y: args.y !== undefined ? absolute(lastLine.y, args.y) + cofg.offsetG92.y : lastLine.y, - z: args.z !== undefined ? absolute(lastLine.z, args.z) + cofg.offsetG92.z : lastLine.z, - a: args.a !== undefined ? absolute(lastLine.a, args.a) + cofg.offsetG92.a : lastLine.a, - e: args.e !== undefined ? absolute(lastLine.e, args.e) + cofg.offsetG92.e : lastLine.e, + x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, + y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, + z: args.z !== undefined ? absolute(lastLine.z, args.z) + state.offsetG92.z : lastLine.z, + a: args.a !== undefined ? absolute(lastLine.a, args.a) + state.offsetG92.a : lastLine.a, + e: args.e !== undefined ? absolute(lastLine.e, args.e) + state.offsetG92.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: args.s !== undefined ? args.s : lastLine.s, t: args.t !== undefined ? args.t : lastLine.t, @@ -112,13 +116,11 @@ export default function makeHandlers(){ arc: true, clockwise: !args.clockwise ? true : args.clockwise // FIXME : always true ?? } - //if (args.clockwise === false) newLine.clockwise = args.clockwise - cofg.addSegment(lastLine, newLine, args) + // if (args.clockwise === false) newLine.clockwise = args.clockwise + addSegment(lastLine, newLine, args) lastLine = newLine }, - dirG7: 0, - G7: function (args, indx) { // Example: G7 L68 D//////sljasflsfagdxsd,.df9078rhfnxm (68 of em) // G7 $1 L4 DAAA= @@ -138,10 +140,11 @@ export default function makeHandlers(){ var buf = atob(args.d) if (typeof args.dollar !== 'undefined') { // Move Y, change direction - this.dirG7 = args.dollar + state.dirG7 = args.dollar + const newLine = { x: lastLine.x, - y: lastLine.y + cofg.spotSizeG7, + y: lastLine.y + state.spotSizeG7, z: lastLine.z, a: lastLine.a, e: lastLine.e, @@ -156,7 +159,7 @@ export default function makeHandlers(){ for (var i = 0; i < buf.length; i++) { // Process a base64-encoded chunk const intensity = 255 - buf.charCodeAt(i) // 255 - 0 const newLine = { - x: lastLine.x + cofg.spotSizeG7 * (this.dirG7 == 1 ? 1 : -1), + x: lastLine.x + state.spotSizeG7 * (state.dirG7 === 1 ? 1 : -1), y: lastLine.y, z: lastLine.z, a: lastLine.a, @@ -245,18 +248,18 @@ export default function makeHandlers(){ // TODO: Only support E0 var newLine = lastLine - cofg.offsetG92.x = (args.x !== undefined ? (args.x === 0 ? newLine.x : newLine.x - args.x) : 0) - cofg.offsetG92.y = (args.y !== undefined ? (args.y === 0 ? newLine.y : newLine.y - args.y) : 0) - cofg.offsetG92.z = (args.z !== undefined ? (args.z === 0 ? newLine.z : newLine.z - args.z) : 0) - cofg.offsetG92.a = (args.a !== undefined ? (args.a === 0 ? newLine.a : newLine.a - args.a) : 0) - cofg.offsetG92.e = (args.e !== undefined ? (args.e === 0 ? newLine.e : newLine.e - args.e) : 0) + state.offsetG92.x = (args.x !== undefined ? (args.x === 0 ? newLine.x : newLine.x - args.x) : 0) + state.offsetG92.y = (args.y !== undefined ? (args.y === 0 ? newLine.y : newLine.y - args.y) : 0) + state.offsetG92.z = (args.z !== undefined ? (args.z === 0 ? newLine.z : newLine.z - args.z) : 0) + state.offsetG92.a = (args.a !== undefined ? (args.a === 0 ? newLine.a : newLine.a - args.a) : 0) + state.offsetG92.e = (args.e !== undefined ? (args.e === 0 ? newLine.e : newLine.e - args.e) : 0) // newLine.x = args.x !== undefined ? args.x + newLine.x : newLine.x // newLine.y = args.y !== undefined ? args.y + newLine.y : newLine.y // newLine.z = args.z !== undefined ? args.z + newLine.z : newLine.z // newLine.e = args.e !== undefined ? args.e + newLine.e : newLine.e - // console.log("G92", lastLine, newLine, args, cofg.offsetG92) + // console.log("G92", lastLine, newLine, args, state.offsetG92) // lastLine = newLine addFakeSegment(args, lineObject, lastLine, lines) @@ -289,7 +292,7 @@ export default function makeHandlers(){ // M649: Laser options for Marlin // M649 S R B2 // Intensity = lasermultiply? - if (typeof args.r !== 'undefined') { cofg.spotSizeG7 = args.r;} + if (typeof args.r !== 'undefined') { state.spotSizeG7 = args.r} }, // Dual Head 3D Printing Support @@ -311,4 +314,6 @@ export default function makeHandlers(){ addFakeSegment(args, lineObject, lastLine, lines) } } + + return handlers } From ea03a95298ba0822216371e83905e9f7cb2b4f49 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sat, 5 Nov 2016 13:53:51 +0100 Subject: [PATCH 07/34] refactor(objFromGcode): split out layers & lineGroup code into seperate modules --- src/layers.js | 10 ++++ src/lineGroup.js | 84 +++++++++++++++++++++++++++++++ src/objFromGcode.js | 120 +++++++------------------------------------- 3 files changed, 111 insertions(+), 103 deletions(-) create mode 100644 src/layers.js create mode 100644 src/lineGroup.js diff --git a/src/layers.js b/src/layers.js new file mode 100644 index 0000000..7fee7b5 --- /dev/null +++ b/src/layers.js @@ -0,0 +1,10 @@ +export function newLayer (line, layers3d) { + // console.log("layers3d:", layers3d, "layers3d.length", layers3d.length) + layer = { + type: {}, + layer: layers3d.length, + z: line.z + } + layers3d.push(layer) + return layer +} diff --git a/src/lineGroup.js b/src/lineGroup.js new file mode 100644 index 0000000..a31e70a --- /dev/null +++ b/src/lineGroup.js @@ -0,0 +1,84 @@ +getLineGroup = function (line, args) { + console.log('getLineGroup:', line) + if (layer == undefined) newLayer(line) + var speed = Math.round(line.e / 1000) + var opacity = line.s + var tool = parseInt(line.t, 10) + // /console.log('Speed: ' , speed , ' opacity: ', opacity) + var grouptype = speed + opacity + var color = null + // var color = new THREE.Color(0x990000) + + if (typeof line.s === 'undefined') { + opacity = 0.3 + } else { + var lasermultiply = $('#lasermultiply').val() || 100 + opacity = line.s / lasermultiply + console.log(opacity + ', ' + line.x) + // } + } + // console.log(opacity) + // LaserWeb 3D Viewer Colors + // LaserWeb 3D Viewer Colors + if (typeof line.extruding === 'undefined' && typeof line.s === 'undefined') { + // console.log('G1 without extrude', line) + grouptype = 'g0' + opacity = 0.3 + color = new THREE.Color(0x00ff00) + } else { + // console.log('G1 with extrude', line) + if (line.g0) { + grouptype = 'g0' + // color = new THREE.Color(0x00ff00) + opacity = 0.3 + color = new THREE.Color(0x00ff00) + } else if (line.g2) { + grouptype = 'g2' + // color = new THREE.Color(0x999900) + color = new THREE.Color(0x990000) + } else if (line.t == 0) { + grouptype = 't0' + // color = new THREE.Color(0x999900) + color = new THREE.Color(0x0000ff) + } else if (line.t == 1) { + grouptype = 't1' + // color = new THREE.Color(0x999900) + color = new THREE.Color(0xff00ff) + } else if (line.arc) { + grouptype = 'arc' + color = new THREE.Color(0x990000) + } else { + color = new THREE.Color(0x990000) + } + } + + // see if we have reached indxMax, if so draw, but + // make it ghosted + // if (args.indx > indxMax) { + // grouptype = "ghost" + // //console.log("args.indx > indxMax", args, indxMax) + // color = new THREE.Color(0x000000) + // } + // if (line.color) color = new THREE.Color(line.color) + if (layer.type[grouptype] == undefined) { + layer.type[grouptype] = { + type: grouptype, + feed: line.e, + extruding: line.extruding, + color: color, + segmentCount: 0, + material: new THREE.LineBasicMaterial({ + opacity: opacity, + // opacity: line.extruding ? 0.5: line.g2 ? 0.2 : 0.3, + transparent: true, + linewidth: 1, + vertexColors: THREE.FaceColors + }), + geometry: new THREE.Geometry(), + } + // if (args.indx > indxMax) { + // layer.type[grouptype].material.opacity = 0.05 + // } + } + return layer.type[grouptype] +} diff --git a/src/objFromGcode.js b/src/objFromGcode.js index 46414e9..bb19896 100644 --- a/src/objFromGcode.js +++ b/src/objFromGcode.js @@ -1,6 +1,5 @@ createObjectFromGCode = function (gcode, indxMax) { console.group('Generating GCODE Preview') - // console.group("Rendering GCODE Preview") // debugger // Credit goes to https://github.com/joewalnes/gcode-viewer @@ -13,13 +12,17 @@ createObjectFromGCode = function (gcode, indxMax) { // these are extra Object3D elements added during // the gcode rendering to attach to scene - this.extraObjects = [] - this.extraObjects['G17'] = [] - this.extraObjects['G18'] = [] - this.extraObjects['G19'] = [] - this.offsetG92 = {x: 0, y: 0, z: 0, a: 0, e: 0} - var lastLine = { + const state = { + extraObjects: { + 'G17': [], + 'G18': [], + 'G19': [] + }, + offsetG92 : {x: 0, y: 0, z: 0, a: 0, e: 0} + } + + let lastLine = { x: 0, y: 0, z: 0, @@ -39,11 +42,16 @@ createObjectFromGCode = function (gcode, indxMax) { // that even the simulator can follow along better var new3dObj = new THREE.Group() new3dObj.name = 'newobj' - plane = 'G17'; // set default plane to G17 - Assume G17 if no plane specified in gcode. + + plane = 'G17' // set default plane to G17 - Assume G17 if no plane specified in gcode. + layers3d = [] layer = undefined + lines = [] + totalDist = 0 + bbbox = { min: { x: 100000, @@ -68,98 +76,4 @@ createObjectFromGCode = function (gcode, indxMax) { z: -100000 } } - - newLayer = function (line) { - // console.log("layers3d:", layers3d, "layers3d.length", layers3d.length) - layer = { - type: {}, - layer: layers3d.length, - z: line.z, - } - layers3d.push(layer) - } - - getLineGroup = function (line, args) { - console.log('getLineGroup:', line) - if (layer == undefined) newLayer(line) - var speed = Math.round(line.e / 1000) - var opacity = line.s - var tool = parseInt(line.t, 10) - // /console.log('Speed: ' , speed , ' opacity: ', opacity) - var grouptype = speed + opacity - var color = null - // var color = new THREE.Color(0x990000) - - if (typeof line.s === 'undefined') { - opacity = 0.3 - } else { - var lasermultiply = $('#lasermultiply').val() || 100 - opacity = line.s / lasermultiply - console.log(opacity + ', ' + line.x) - // } - } - // console.log(opacity) - // LaserWeb 3D Viewer Colors - // LaserWeb 3D Viewer Colors - if (typeof line.extruding === 'undefined' && typeof line.s === 'undefined') { - // console.log('G1 without extrude', line) - grouptype = 'g0' - opacity = 0.3 - color = new THREE.Color(0x00ff00) - } else { - // console.log('G1 with extrude', line) - if (line.g0) { - grouptype = 'g0' - // color = new THREE.Color(0x00ff00) - opacity = 0.3 - color = new THREE.Color(0x00ff00) - } else if (line.g2) { - grouptype = 'g2' - // color = new THREE.Color(0x999900) - color = new THREE.Color(0x990000) - } else if (line.t == 0) { - grouptype = 't0' - // color = new THREE.Color(0x999900) - color = new THREE.Color(0x0000ff) - } else if (line.t == 1) { - grouptype = 't1' - // color = new THREE.Color(0x999900) - color = new THREE.Color(0xff00ff) - } else if (line.arc) { - grouptype = 'arc' - color = new THREE.Color(0x990000) - } else { - color = new THREE.Color(0x990000) - } - } - - // see if we have reached indxMax, if so draw, but - // make it ghosted - // if (args.indx > indxMax) { - // grouptype = "ghost" - // //console.log("args.indx > indxMax", args, indxMax) - // color = new THREE.Color(0x000000) - // } - // if (line.color) color = new THREE.Color(line.color) - if (layer.type[grouptype] == undefined) { - layer.type[grouptype] = { - type: grouptype, - feed: line.e, - extruding: line.extruding, - color: color, - segmentCount: 0, - material: new THREE.LineBasicMaterial({ - opacity: opacity, - // opacity: line.extruding ? 0.5: line.g2 ? 0.2 : 0.3, - transparent: true, - linewidth: 1, - vertexColors: THREE.FaceColors - }), - geometry: new THREE.Geometry(), - } - // if (args.indx > indxMax) { - // layer.type[grouptype].material.opacity = 0.05 - // } - } - return layer.type[grouptype] - } +} From 6f58a507c1b6873316cc5b0caaa60755bbe31fcc Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 6 Nov 2016 10:26:15 +0100 Subject: [PATCH 08/34] refactor(): continued restructure/reorganize/regroup of logical variables etc --- src/geometries/segments.js | 4 +- src/legacy/gcode-parser-breakapart.js | 3 +- src/objFromGcode.js | 72 +++++++++++++-------------- src/parse.js | 16 +++--- src/parseLine.js | 36 ++++++++------ 5 files changed, 67 insertions(+), 64 deletions(-) diff --git a/src/geometries/segments.js b/src/geometries/segments.js index c1e4951..913c35f 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -1,7 +1,7 @@ import {getLineGroup} from './foo' -export function addSegment (p1, p2, args) { - closeLineSegment() +export function addSegment (p1, p2, args, lineObject) { + closeLineSegment(lineObject) let bbbox = [] let bbbox2 = [] diff --git a/src/legacy/gcode-parser-breakapart.js b/src/legacy/gcode-parser-breakapart.js index 977cbe4..516f486 100644 --- a/src/legacy/gcode-parser-breakapart.js +++ b/src/legacy/gcode-parser-breakapart.js @@ -8,8 +8,7 @@ // This is a simplified and updated version of http://gcode.joewalnes.com/ that works with the latest version of Three.js (v68). // Updated with code from http://chilipeppr.com/tinyg's 3D viewer to support more CNC type Gcode -var totaltimemax = '' -totaltimemax = 0 + var lineObjects = new THREE.Object3D() lineObjects.name = 'LineObjects' diff --git a/src/objFromGcode.js b/src/objFromGcode.js index bb19896..6a464f8 100644 --- a/src/objFromGcode.js +++ b/src/objFromGcode.js @@ -14,12 +14,43 @@ createObjectFromGCode = function (gcode, indxMax) { // the gcode rendering to attach to scene const state = { + lineObjects: { + name: 'LineObjects' + }, extraObjects: { 'G17': [], 'G18': [], 'G19': [] }, - offsetG92 : {x: 0, y: 0, z: 0, a: 0, e: 0} + offsetG92: {x: 0, y: 0, z: 0, a: 0, e: 0}, + plane: 'G17', // set default plane to G17 - Assume G17 if no plane specified in gcode. + isUnitsMm: true, + lines: [], + + layers: { + layers3d: [], + layer: undefined + }, + + metrics: { + totaltimemax: 0, + totalDist: 0 + }, + + previous: { + lastArgs: {cmd: null}, + lastFeedrate: null + }, + + bbbox: { + min: [100000, 100000, 100000], + max: [-100000, -100000, -100000] + }, + + bbbox2: { + min: [100000, 100000, 100000], + max: [-100000, -100000, -100000] + } } let lastLine = { @@ -30,7 +61,7 @@ createObjectFromGCode = function (gcode, indxMax) { e: 0, f: 0, feedrate: null, - extruding: false, + extruding: false } // we have been using an approach where we just append @@ -40,40 +71,7 @@ createObjectFromGCode = function (gcode, indxMax) { // its own userData info // G2/G3 moves are their own child of lots of lines so // that even the simulator can follow along better - var new3dObj = new THREE.Group() - new3dObj.name = 'newobj' - - plane = 'G17' // set default plane to G17 - Assume G17 if no plane specified in gcode. - - layers3d = [] - layer = undefined - - lines = [] - - totalDist = 0 - - bbbox = { - min: { - x: 100000, - y: 100000, - z: 100000 - }, - max: { - x: -100000, - y: -100000, - z: -100000 - } - } - bbbox2 = { - min: { - x: 100000, - y: 100000, - z: 100000 - }, - max: { - x: -100000, - y: -100000, - z: -100000 - } + let new3dObj = { + name : 'newobj' } } diff --git a/src/parse.js b/src/parse.js index 8b62297..9e7cfc4 100644 --- a/src/parse.js +++ b/src/parse.js @@ -1,4 +1,8 @@ -export default function parser (gcode) { +export default function parser (gcode, progressCallback, doneCallback) { + lineObjects + laserxmax + laserymax + console.log('inside this.parse') object = null var lines = gcode.split(/\r{0,1}\n/) @@ -10,16 +14,14 @@ export default function parser (gcode) { return new Date().getTime() } - var tbody = '' function doChunk () { var progress = (index / count) - NProgress.set(progress) + progressCallback(progress) var startTime = now() while (index < count && (now() - startTime) <= maxTimePerChunk) { // console.log('parsing ' + lines[index]) parseLine(lines[index], index) - // tbody += ''+[index]+''+lines[index]+'';//code here using lines[i] which will give you each line ++index } closeLineSegment() @@ -28,10 +30,7 @@ export default function parser (gcode) { setTimeout(doChunk, 1) // set Timeout for async iteration // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") } else { - NProgress.done() - NProgress.remove() - // console.log('[GCODE PARSE] Done ') - $('#renderprogressholder').hide() + doneCallback() object = drawobject() object.add(lineObjects) // console.log('Line Objects', lineObjects) @@ -40,7 +39,6 @@ export default function parser (gcode) { object.name = 'object' console.log('adding to scene') scene.add(object) - // objectsInScene.push(object) } } doChunk() diff --git a/src/parseLine.js b/src/parseLine.js index 3e3e658..7e5d6b7 100644 --- a/src/parseLine.js +++ b/src/parseLine.js @@ -1,9 +1,15 @@ export function parseLine (text, info, handlers) { // console.log('Parsing: ',text) + let lastArgs = { + cmd: undefined + } + const state = { + isUnitsMm: true + } const origtext = text if (text.match(/^N/i)) { // remove line numbers if exist - text = text.replace(/^N\d+\s*/ig, '')// yes, there's a line num + text = text.replace(/^N\d+\s*/ig, '') // yes, there's a line num } const isG7 = text.match(/^G7/) // Is is G7 raster command? @@ -20,15 +26,16 @@ export function parseLine (text, info, handlers) { text = origtext isComment = true } else { // make sure to remove inline comments - if (!isG7) + if (!isG7) { text = text.replace(/\(.*?\)/g, '') + } } - //after this , more tokenizing/ calling handlers + // after this , more tokenizing/ calling handlers if (text && !isComment) { - if (!isG7) - text = text.replace(/(;|\().*$/, ''); // strip off end of line comment ; or () trailing - + if (!isG7) { + text = text.replace(/(;|\().*$/, '') // strip off end of line comment ; or () trailing + } let tokens = text.split(/\s+/) if (tokens) { var cmd = tokens[0] // check if a g or m cmd was included in gcode line @@ -37,7 +44,7 @@ export function parseLine (text, info, handlers) { // cmd is what's assumed isComment = false if (!cmd.match(/^(G|M|T)/i)) { - cmd = this.lastArgs.cmd // we need to use the last gcode cmd + cmd = lastArgs.cmd // we need to use the last gcode cmd tokens.unshift(cmd) // put at spot 0 in array } else { // we have a normal cmd as opposed to just an xyz pos where @@ -57,16 +64,17 @@ export function parseLine (text, info, handlers) { if (tokens.length > 1 && !isComment) { tokens.splice(1).forEach(function (token) { if (token && token.length > 0) { - var key = token[0].toLowerCase() + let key = token[0].toLowerCase() + let value if (!isG7) { - var value = parseFloat(token.substring(1)) + value = parseFloat(token.substring(1)) if (isNaN(value)) { value = 0 } args[key] = value } else { // Special treatment for G7 with D-data - if (key == '$') key = 'dollar' // '$' doesn't work so well, use 'dollar' - var value = token.substring(1) // Don't convert values to float, need the D-data + if (key === '$') key = 'dollar' // '$' doesn't work so well, use 'dollar' + value = token.substring(1) // Don't convert values to float, need the D-data args[key] = value } } else { @@ -88,14 +96,14 @@ export function parseLine (text, info, handlers) { // of the line. if (args.text.match(/\bG20\b/i)) { console.log('SETTING UNITS TO INCHES from pre-parser!!!') - this.isUnitsMm = false // false means inches cuz default is mm + state.isUnitsMm = false // false means inches cuz default is mm } else if (args.text.match(/\bG21\b/i)) { console.log('SETTING UNITS TO MM!!! from pre-parser') - this.isUnitsMm = true // true means mm + state.isUnitsMm = true // true means mm } if (args.text.match(/F([\d.]+)/i)) { // scan for feedrate - var feedrate = parseFloat(RegExp.$1) // we have a new feedrate + const feedrate = parseFloat(RegExp.$1) // we have a new feedrate args.feedrate = feedrate this.lastFeedrate = feedrate } else { From ca47ad37136648c8189c7a8431ec8c6c61617a5a Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 6 Nov 2016 10:28:24 +0100 Subject: [PATCH 09/34] fix(): minor typos fix --- src/index.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/index.js b/src/index.js index fa501d9..aa6f95c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,14 +1,13 @@ /** + * @author kaosat-dev / https://github.com/kaosat-dev * @author kaosat-dev / https://github.com/kaosat-dev * - * Description: A gcode parser for STL ASCII files & BINARY, + * Description: A gcode parser, **/ export default function makeGcodeStream (parameters = {}) { - - /* - + OLD code structure , for reference ! //main entry point !! createObjectFromGCode(gcode, indxMax) => handlers = { @@ -21,8 +20,7 @@ export default function makeGcodeStream (parameters = {}) { =>parse =>doChunk =>parseLine - - convertLineGeometryToBufferGeometry */ + } From 5f98e7788b6296617f1bb5a6c229b1106fd1b2d6 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 00:19:13 +0100 Subject: [PATCH 10/34] test(): tweaked data type, added data for basic test --- test/data/Rotary Axis GCode.gcode | 363 ++++++++++++++++++++++++++++++ test/gcodeParser.spec.js | 9 +- test/tmptest.js | 7 + 3 files changed, 376 insertions(+), 3 deletions(-) create mode 100644 test/data/Rotary Axis GCode.gcode create mode 100644 test/tmptest.js diff --git a/test/data/Rotary Axis GCode.gcode b/test/data/Rotary Axis GCode.gcode new file mode 100644 index 0000000..d5a2a45 --- /dev/null +++ b/test/data/Rotary Axis GCode.gcode @@ -0,0 +1,363 @@ +(G Code Wrapped by the Chestnut Pens GCodeWrapper Program.) +(Toolpath Creation Program © R.W.Williams, 2013) +(Max Straight segment length = 1.0000mm) +(Max arc angle of segment around centre = 1.0000degrees) +(Note: All dimensions are converted to mm) +(Total Running Time minimum = 2 Minutes, 45.79 Seconds. ) +(Original file Axis height Z = 0.0000) +(Original file Nominal Work height Z = 60.0000) +(This file Axis height Z = 0.0000) +(Y axis is wrapped...) +(...onto the A axis) +G0 F3600 A58.2335 X0.0000 +G1 F1200 Z60.0000 +M3 +G1 F1200 X18.5400 S255 +G1 F1200 A15.0468 S255 +G1 F1200 X47.4760 S255 +G1 F1200 A0.9377 S255 +G1 F1200 X0.0000 S255 +G1 F1200 A58.2335 S255 +M5 +G0 A28.9993 X69.9860 +G1 F1200 +M3 +G1 F1200 A30.6017 X54.0650 S255 +G1 F1200 A34.1636 X55.1650 S255 +G1 F1200 A36.8746 X56.6640 S255 +G1 F1200 A39.0098 X58.7360 S255 +G1 F1200 A40.8414 X61.5550 S255 +G1 F1200 A41.9166 X64.2770 S255 +G1 F1200 A42.7178 X67.8580 S255 +G1 F1200 A43.3825 X76.5350 S255 +G1 F1200 A43.1819 X83.2880 S255 +G1 F1200 A42.5813 X88.5680 S255 +G1 F1200 A41.3446 X92.7320 S255 +G1 F1200 A39.2390 X96.1390 S255 +G1 F1200 A37.1143 X98.0420 S255 +G1 F1200 A34.2562 X99.4950 S255 +G1 F1200 A31.1049 X100.4160 S255 +G1 F1200 A28.1007 X100.7230 S255 +G1 F1200 A9.7708 S255 +G1 F1200 A5.1786 X101.1120 S255 +G1 F1200 A0.9377 X102.8100 S255 +G1 F1200 X87.1760 S255 +G1 F1200 A3.3805 X85.9480 S255 +G1 F1200 A6.0189 X85.3750 S255 +G1 F1200 A3.4397 X82.1110 S255 +G1 F1200 A1.7198 X78.8680 S255 +G1 F1200 A0.4297 X74.0890 S255 +G1 F1200 A0.0000 X68.5950 S255 +G1 F1200 A0.2149 X64.9410 S255 +G1 F1200 A0.8594 X61.7550 S255 +G1 F1200 A1.9347 X59.0370 S255 +G1 F1200 A3.4397 X56.7870 S255 +G1 F1200 A5.2588 X55.0230 S255 +G1 F1200 A7.2794 X53.7640 S255 +G1 F1200 A9.4996 X53.0080 S255 +G1 F1200 A11.9204 X52.7560 S255 +G1 F1200 A16.2290 X53.4820 S255 +G1 F1200 A19.6983 X55.6620 S255 +G1 F1200 A21.1240 X57.4220 S255 +G1 F1200 A22.3559 X59.7950 S255 +G1 F1200 A24.2313 X66.3850 S255 +G1 F1200 A26.7524 X78.5400 S255 +G1 F1200 A28.6479 X84.4340 S255 +G1 F1200 A31.1393 X84.1170 S255 +G1 F1200 A32.7512 X83.1650 S255 +G1 F1200 A33.6307 X81.4150 S255 +G1 F1200 A33.9239 X78.7040 S255 +G1 F1200 A33.6116 X75.1230 S255 +G1 F1200 A32.6739 X72.5650 S255 +G1 F1200 A31.2663 X71.1220 S255 +G1 F1200 A28.9993 X69.9860 S255 +M5 +G0 A20.6360 X84.4340 +G1 F1200 +M3 +G1 F1200 A18.5648 X77.2710 S255 +G1 F1200 A17.2842 X73.1280 S255 +G1 F1200 A16.0237 X70.8460 S255 +G1 F1200 A14.6467 X69.8020 S255 +G1 F1200 A13.0930 X69.4540 S255 +G1 F1200 A11.3875 X69.7970 S255 +G1 F1200 A10.0249 X70.8250 S255 +G1 F1200 A9.1310 X72.5190 S255 +G1 F1200 A8.8331 X74.8570 S255 +G1 F1200 A9.1549 X77.5430 S255 +G1 F1200 A10.1223 X80.0340 S255 +G1 F1200 A11.5537 X82.0800 S255 +G1 F1200 A13.2687 X83.4310 S255 +G1 F1200 A15.4040 X84.1830 S255 +G1 F1200 A18.0959 X84.4340 S255 +G1 F1200 A20.6360 S255 +M5 +G0 A12.4676 X107.7630 +G1 F1200 +M3 +G1 F1200 A13.9525 X124.2970 S255 +G1 F1200 A11.5394 X125.5250 S255 +G1 F1200 A9.9274 X127.1620 S255 +G1 F1200 A9.0184 X129.3110 S255 +G1 F1200 A8.7156 X132.0740 S255 +G1 F1200 A9.0575 X135.0510 S255 +G1 F1200 A10.0821 X137.2710 S255 +G1 F1200 A11.2233 X138.3460 S255 +G1 F1200 A12.6184 X138.7040 S255 +G1 F1200 A14.1406 X138.2330 S255 +G1 F1200 A15.2722 X136.8210 S255 +G1 F1200 A16.9108 X129.6590 S255 +G1 F1200 A18.3022 X122.3070 S255 +G1 F1200 A19.5856 X117.6060 S255 +G1 F1200 A21.2395 X114.4950 S255 +G1 F1200 A23.7434 X111.9170 S255 +G1 F1200 A26.8765 X110.1820 S255 +G1 F1200 A30.4193 X109.6040 S255 +G1 F1200 A34.2361 X110.2290 S255 +G1 F1200 A37.4867 X112.1010 S255 +G1 F1200 A40.0784 X115.0680 S255 +G1 F1200 A41.9185 X118.9770 S255 +G1 F1200 A43.0158 X124.1030 S255 +G1 F1200 A43.3825 X130.7230 S255 +G1 F1200 A43.0988 X137.4810 S255 +G1 F1200 A42.2490 X142.2030 S255 +G1 F1200 A40.8032 X145.6000 S255 +G1 F1200 A38.7310 X148.3830 S255 +G1 F1200 A35.9273 X150.6500 S255 +G1 F1200 A32.2824 X152.4970 S255 +G1 F1200 A30.7974 X136.6980 S255 +G1 F1200 A32.5268 X135.8800 S255 +G1 F1200 A33.7291 X134.6520 S255 +G1 F1200 A34.6668 X132.4830 S255 +G1 F1200 A34.9791 X129.9050 S255 +G1 F1200 A34.7403 X127.4640 S255 +G1 F1200 A34.0232 X125.7910 S255 +G1 F1200 A32.9651 X124.8240 S255 +G1 F1200 A31.7018 X124.5020 S255 +G1 F1200 A30.3649 X124.9110 S255 +G1 F1200 A29.3994 X126.1390 S255 +G1 F1200 A28.6574 X128.7380 S255 +G1 F1200 A27.9938 X133.2610 S255 +G1 F1200 A26.9204 X140.5050 S255 +G1 F1200 A25.4957 X145.6210 S255 +G1 F1200 A23.5533 X149.1970 S255 +G1 F1200 A20.9273 X151.8210 S255 +G1 F1200 A17.8142 X153.4330 S255 +G1 F1200 A14.4070 X153.9700 S255 +G1 F1200 A10.8642 X153.4020 S255 +G1 F1200 A7.4188 X151.6980 S255 +G1 F1200 A4.3678 X148.7720 S255 +G1 F1200 A2.0111 X144.5360 S255 +G1 F1200 A0.5023 X138.7600 S255 +G1 F1200 A0.0000 X131.2140 S255 +G1 F1200 A0.2024 X125.6880 S255 +G1 F1200 A0.8107 X121.0180 S255 +G1 F1200 A1.8249 X117.2050 S255 +G1 F1200 A3.2439 X114.2500 S255 +G1 F1200 A5.0373 X111.9490 S255 +G1 F1200 A7.1715 X110.1010 S255 +G1 F1200 A9.6486 X108.7050 S255 +G1 F1200 A12.4676 X107.7630 S255 +M5 +G0 A17.7435 X210.1640 +G1 F1200 +M3 +G1 F1200 X176.7670 S255 +G1 F1200 A14.4022 X177.5340 S255 +G1 F1200 A12.0378 X178.9360 S255 +G1 F1200 A10.0153 X181.7190 S255 +G1 F1200 A9.3411 X185.2390 S255 +G1 F1200 A9.6343 X187.6330 S255 +G1 F1200 A10.5138 X189.9050 S255 +G1 F1200 A13.1322 X192.8100 S255 +G1 F1200 A11.6855 X209.2220 S255 +G1 F1200 A6.3169 X205.0680 S255 +G1 F1200 A4.2953 X202.7000 S255 +G1 F1200 A2.7158 X200.1360 S255 +G1 F1200 A1.5279 X197.1870 S255 +G1 F1200 A0.6790 X193.6600 S255 +G1 F1200 A0.0000 X184.8700 S255 +G1 F1200 A0.5816 X177.1560 S255 +G1 F1200 A2.3253 X171.2820 S255 +G1 F1200 A5.3352 X166.7550 S255 +G1 F1200 A9.7126 X163.0760 S255 +G1 F1200 A12.3539 X161.6530 S255 +G1 F1200 A15.2178 X160.6360 S255 +G1 F1200 A21.6129 X159.8230 S255 +G1 F1200 A26.2462 X160.2310 S255 +G1 F1200 A30.4164 X161.4550 S255 +G1 F1200 A34.1215 X163.4950 S255 +G1 F1200 A37.3635 X166.3510 S255 +G1 F1200 A39.9963 X169.9250 S255 +G1 F1200 A41.8775 X174.1220 S255 +G1 F1200 A43.0062 X178.9400 S255 +G1 F1200 A43.3825 X184.3790 S255 +G1 F1200 A42.7083 X192.7290 S255 +G1 F1200 A41.8651 X196.1660 S255 +G1 F1200 A40.6857 X199.1130 S255 +G1 F1200 A37.3826 X203.8710 S255 +G1 F1200 A32.8687 X207.3400 S255 +G1 F1200 A30.1156 X208.5750 S255 +G1 F1200 A26.9768 X209.4580 S255 +G1 F1200 A19.5417 X210.1640 S255 +G1 F1200 A17.7435 S255 +M5 +G0 A25.3648 X193.2200 +G1 F1200 +M3 +G1 F1200 A29.3221 X192.3240 S255 +G1 F1200 A31.9701 X190.6210 S255 +G1 F1200 A33.4646 X188.1800 S255 +G1 F1200 A33.9630 X185.0750 S255 +G1 F1200 A33.2105 X181.5040 S255 +G1 F1200 A30.9540 X178.7310 S255 +G1 F1200 A28.6183 X177.4930 S255 +G1 F1200 A25.3648 X176.8080 S255 +G1 F1200 X193.2200 S255 +M5 +G0 A42.4438 X217.9810 +G1 F1200 +M3 +G1 F1200 X233.5740 S255 +G1 F1200 A35.6437 S255 +G1 F1200 A39.3717 X235.8610 S255 +G1 F1200 A41.7209 X238.2200 S255 +G1 F1200 A42.9671 X240.8950 S255 +G1 F1200 A43.3825 X244.1340 S255 +G1 F1200 A42.8353 X247.9910 S255 +G1 F1200 A41.1938 X252.1960 S255 +G1 F1200 A29.8597 X247.0400 S255 +G1 F1200 A31.0323 X242.3740 S255 +G1 F1200 A30.3868 X239.4680 S255 +G1 F1200 A28.4521 X237.2990 S255 +G1 F1200 A26.2396 X236.1710 S255 +G1 F1200 A23.2353 X235.3650 S255 +G1 F1200 A14.8520 X234.7200 S255 +G1 F1200 A0.9377 S255 +G1 F1200 X217.9810 S255 +G1 F1200 A42.4438 S255 +M5 +G0 A58.2335 X249.9450 +G1 F1200 +M3 +G1 F1200 X267.5550 S255 +G1 F1200 A26.2376 X273.9190 S255 +G1 F1200 A58.2335 X283.1750 S255 +G1 F1200 X300.7200 S255 +G1 F1200 A26.2014 X310.0230 S255 +G1 F1200 A58.2335 X316.3700 S255 +G1 F1200 X333.8880 S255 +G1 F1200 A0.9377 X320.6630 S255 +G1 F1200 X302.4820 S255 +G1 F1200 A37.0121 X291.9580 S255 +G1 F1200 A0.9377 X281.4750 S255 +G1 F1200 X263.2940 S255 +G1 F1200 A58.2335 X249.9450 S255 +M5 +G0 A17.7435 X387.0940 +G1 F1200 +M3 +G1 F1200 X353.6970 S255 +G1 F1200 A14.4022 X354.4650 S255 +G1 F1200 A12.0378 X355.8660 S255 +G1 F1200 A10.0153 X358.6490 S255 +G1 F1200 A9.3411 X362.1690 S255 +G1 F1200 A9.6343 X364.5630 S255 +G1 F1200 A10.5138 X366.8350 S255 +G1 F1200 A13.1322 X369.7410 S255 +G1 F1200 A11.6855 X386.1530 S255 +G1 F1200 A6.3169 X381.9990 S255 +G1 F1200 A4.2953 X379.6300 S255 +G1 F1200 A2.7158 X377.0670 S255 +G1 F1200 A1.5279 X374.1170 S255 +G1 F1200 A0.6790 X370.5900 S255 +G1 F1200 A0.0000 X361.8010 S255 +G1 F1200 A0.5816 X354.0860 S255 +G1 F1200 A2.3253 X348.2130 S255 +G1 F1200 A5.3352 X343.6850 S255 +G1 F1200 A9.7126 X340.0070 S255 +G1 F1200 A12.3539 X338.5830 S255 +G1 F1200 A15.2178 X337.5670 S255 +G1 F1200 A21.6129 X336.7530 S255 +G1 F1200 A26.2462 X337.1610 S255 +G1 F1200 A30.4164 X338.3850 S255 +G1 F1200 A34.1215 X340.4250 S255 +G1 F1200 A37.3635 X343.2810 S255 +G1 F1200 A39.9963 X346.8560 S255 +G1 F1200 A41.8775 X351.0520 S255 +G1 F1200 A43.0062 X355.8700 S255 +G1 F1200 A43.3825 X361.3100 S255 +G1 F1200 A42.7083 X369.6590 S255 +G1 F1200 A41.8651 X373.0970 S255 +G1 F1200 A40.6857 X376.0440 S255 +G1 F1200 A37.3826 X380.8020 S255 +G1 F1200 A32.8687 X384.2700 S255 +G1 F1200 A30.1156 X385.5060 S255 +G1 F1200 A26.9768 X386.3880 S255 +G1 F1200 A19.5417 X387.0940 S255 +G1 F1200 A17.7435 S255 +M5 +G0 A25.3648 X370.1500 +G1 F1200 +M3 +G1 F1200 A29.3221 X369.2550 S255 +G1 F1200 A31.9701 X367.5510 S255 +G1 F1200 A33.4646 X365.1110 S255 +G1 F1200 A33.9630 X362.0050 S255 +G1 F1200 A33.2105 X358.4350 S255 +G1 F1200 A30.9540 X355.6620 S255 +G1 F1200 A28.6183 X354.4240 S255 +G1 F1200 A25.3648 X353.7380 S255 +G1 F1200 X370.1500 S255 +M5 +G0 A58.2335 X394.8290 +G1 F1200 +M3 +G1 F1200 X411.6510 S255 +G1 F1200 A38.3796 S255 +G1 F1200 A40.5683 X414.3160 S255 +G1 F1200 A42.1315 X417.3190 S255 +G1 F1200 A43.0692 X420.6600 S255 +G1 F1200 A43.3825 X424.3380 S255 +G1 F1200 A43.0415 X428.1370 S255 +G1 F1200 A42.0188 X431.5930 S255 +G1 F1200 A40.3152 X434.7060 S255 +G1 F1200 A37.9298 X437.4760 S255 +G1 F1200 A34.9075 X439.7500 S255 +G1 F1200 A31.2911 X441.3740 S255 +G1 F1200 A27.0809 X442.3490 S255 +G1 F1200 A22.2776 X442.6740 S255 +G1 F1200 A15.8824 X442.0800 S255 +G1 F1200 A10.2980 X440.3000 S255 +G1 F1200 A5.7745 X437.4710 S255 +G1 F1200 A2.5602 X433.7310 S255 +G1 F1200 A0.6398 X429.3060 S255 +G1 F1200 A0.0000 X424.4200 S255 +G1 F1200 A0.4498 X420.2250 S255 +G1 F1200 A1.7981 X416.3980 S255 +G1 F1200 A3.8207 X413.5330 S255 +G1 F1200 A7.0741 X410.4230 S255 +G1 F1200 A0.9377 S255 +G1 F1200 X394.8290 S255 +G1 F1200 A58.2335 S255 +M5 +G0 A21.8087 X411.5280 +G1 F1200 +M3 +G1 F1200 A17.1916 X412.0550 S255 +G1 F1200 A14.0499 X413.6360 S255 +G1 F1200 A12.2479 X416.0250 S255 +G1 F1200 A11.6463 X418.9770 S255 +G1 F1200 A12.2374 X421.7240 S255 +G1 F1200 A14.0117 X423.9900 S255 +G1 F1200 A17.1820 X425.5100 S255 +G1 F1200 A21.9643 X426.0160 S255 +G1 F1200 A26.2348 X425.5200 S255 +G1 F1200 A29.1951 X424.0310 S255 +G1 F1200 A30.9244 X421.8370 S255 +G1 F1200 A31.5012 X419.2220 S255 +G1 F1200 A30.8996 X416.1370 S255 +G1 F1200 A29.0977 X413.6770 S255 +G1 F1200 A26.0734 X412.0650 S255 +G1 F1200 A21.8087 X411.5280 S255 +M5 diff --git a/test/gcodeParser.spec.js b/test/gcodeParser.spec.js index 267095a..c35da0c 100644 --- a/test/gcodeParser.spec.js +++ b/test/gcodeParser.spec.js @@ -1,12 +1,15 @@ import test from 'ava' // import fs from 'fs' //does not work with babel + brfs const fs = require('fs') +import parse from '../src/index' -test.cb('gcode parser tests: can parse ascii gcode files', t => { +test.cb('gcode parser tests: can parse gcode files', t => { + const gcode = fs.readFileSync('./data/Rotary Axis GCode.gcode','utf8') + parse(gcode) // this.timeout(5000) - fs.createReadStream('./data/test.gcode', { encoding: null, highWaterMark: 512 * 1024 }) // 'binary' + /*fs.createReadStream('./data/test.gcode', { encoding: null, highWaterMark: 512 * 1024 }) // 'binary' .pipe(makeStlStream()) .pipe(concatStream(function (parsedgcode) { t.end() - })) + }))*/ }) diff --git a/test/tmptest.js b/test/tmptest.js new file mode 100644 index 0000000..29ee6f3 --- /dev/null +++ b/test/tmptest.js @@ -0,0 +1,7 @@ +import test from 'ava' +// import fs from 'fs' //does not work with babel + brfs +const fs = require('fs') +import parse from '../src/parse' + +const gcode = fs.readFileSync('./data/Rotary Axis GCode.gcode') +parse(gcode) From 848d37b46078b5c100a7052c7792a330e6851333 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 00:19:58 +0100 Subject: [PATCH 11/34] refactor(): continued overall reshape: - started adding basics within main index - restructuring of parseLine - lots of stripping out of parseAsChunks (prev pars.js) - etc --- src/drawObject.js | 2 +- src/gcodeHandlers.js | 16 +-- src/index.js | 25 +++- src/legacy/gcode-parser-breakapart.js | 14 +-- src/objFromGcode.js | 33 ++++- src/parse.js | 45 ------- src/parseAsChunks.js | 74 +++++++++++ src/parseLine.js | 174 ++++++++++++++------------ src/timeAndDistance.js | 11 ++ 9 files changed, 237 insertions(+), 157 deletions(-) delete mode 100644 src/parse.js create mode 100644 src/parseAsChunks.js create mode 100644 src/timeAndDistance.js diff --git a/src/drawObject.js b/src/drawObject.js index cc0f98d..9d032fc 100644 --- a/src/drawObject.js +++ b/src/drawObject.js @@ -1,4 +1,4 @@ -function drawobject () { +export default function drawobject () { var newObject = false // console.log("INSIDE DRAWOBJECT") // set what units we're using in the gcode diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js index 9a21e66..16bb616 100644 --- a/src/gcodeHandlers.js +++ b/src/gcodeHandlers.js @@ -12,8 +12,8 @@ export default function makeHandlers (params) { } const lasermultiply = 100 const lineObject = {} - const lastLine = undefined - const lines = undefined + let lastLine = undefined + let lines = undefined // EEK !! var lasermultiply = $('#lasermultiply').val() || 100 const handlers = { @@ -21,7 +21,7 @@ export default function makeHandlers (params) { // When doing CNC, generally G0 just moves to a new location // as fast as possible which means no milling or extruding is happening in G0. // So, let's color it uniquely to indicate it's just a toolhead move. - G0: function (args, indx) { + G0: function (args, index) { const newLine = { x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, @@ -35,7 +35,7 @@ export default function makeHandlers (params) { addLineSegment(lastLine, newLine, lineObject, lasermultiply) lastLine = newLine }, - G1: function (args, indx) { + G1: function (args, index) { // Example: G1 Z1.0 F3000 // G1 X99.9948 Y80.0611 Z15.0 F1500.0 E981.64869 // G1 E104.25841 F1800.0 @@ -64,7 +64,7 @@ export default function makeHandlers (params) { addLineSegment(lastLine, newLine, lineObject, lasermultiply) lastLine = newLine }, - G2: function (args, indx, gcp) { + G2: function (args, index, gcp) { // this is an arc move from lastLine's xy to the new xy. we'll // show it as a light gray line, but we'll also sub-render the // arc itself by figuring out the sub-segments @@ -92,7 +92,7 @@ export default function makeHandlers (params) { addSegment(lastLine, newLine, args) lastLine = newLine }, - G3: function (args, indx, gcp) { + G3: function (args, index, gcp) { // this is an arc move from lastLine's xy to the new xy. same // as G2 but reverse args.arc = true @@ -121,7 +121,7 @@ export default function makeHandlers (params) { lastLine = newLine }, - G7: function (args, indx) { + G7: function (args, index) { // Example: G7 L68 D//////sljasflsfagdxsd,.df9078rhfnxm (68 of em) // G7 $1 L4 DAAA= // G7 $0 L4 D2312 @@ -212,7 +212,7 @@ export default function makeHandlers (params) { addFakeSegment(args, lineObject, lastLine, lines) }, - G73: function (args, indx, gcp) { + G73: function (args, index, gcp) { // peck drilling. just treat as g1 console.log('G73 gcp:', gcp) gcp.handlers.G1(args) diff --git a/src/index.js b/src/index.js index aa6f95c..7dd0e27 100644 --- a/src/index.js +++ b/src/index.js @@ -5,8 +5,25 @@ * Description: A gcode parser, **/ -export default function makeGcodeStream (parameters = {}) { - /* +//import makeHandlers from './gcodeHandlers' +import parseAsChunks from './parseAsChunks' +import makeBaseData from './objFromGcode' + +export default function parse(data, parameters={}){ + + const defaults ={ + laserxmax: 0, + laserymax: 0 + } + + const {state} = makeBaseData() + parseAsChunks(data, state, defaults) + //const gCodeHandlers = makeHandlers() +} + + + /*export default function makeGcodeStream (parameters = {}) { + OLD code structure , for reference ! //main entry point !! createObjectFromGCode(gcode, indxMax) @@ -21,6 +38,4 @@ export default function makeGcodeStream (parameters = {}) { =>doChunk =>parseLine convertLineGeometryToBufferGeometry - */ - -} +}*/ diff --git a/src/legacy/gcode-parser-breakapart.js b/src/legacy/gcode-parser-breakapart.js index 516f486..138d15b 100644 --- a/src/legacy/gcode-parser-breakapart.js +++ b/src/legacy/gcode-parser-breakapart.js @@ -16,15 +16,9 @@ lineObjects.name = 'LineObjects' function GCodeParser (handlers) { handlers = handlers || {} - lastArgs = {cmd: null} - lastFeedrate = null - isUnitsMm = true } -colorG0: 0x00ff00 -colorG1: 0x0000ff -colorG2: 0x999900 - var bufSize = 10000; // Arbitrary - play around with! + var lineObject = {active: false, vertexBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments colorBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments @@ -35,9 +29,3 @@ colorG2: 0x999900 transparent: true, linewidth: 1, }) - totalDist = 0 - totalTime = 0 - var relative = false - var tool = null - var cofg = this - //parser = new GCodeParser( diff --git a/src/objFromGcode.js b/src/objFromGcode.js index 6a464f8..ebd982f 100644 --- a/src/objFromGcode.js +++ b/src/objFromGcode.js @@ -1,5 +1,5 @@ -createObjectFromGCode = function (gcode, indxMax) { - console.group('Generating GCODE Preview') +export default function createObjectFromGCode(gcode, indxMax) { + console.log('Generating GCODE Preview') // console.group("Rendering GCODE Preview") // debugger // Credit goes to https://github.com/joewalnes/gcode-viewer @@ -13,7 +13,11 @@ createObjectFromGCode = function (gcode, indxMax) { // these are extra Object3D elements added during // the gcode rendering to attach to scene - const state = { + let state = { + tool: null, + relative: false, + isUnitsMm: true, + lineObjects: { name: 'LineObjects' }, @@ -24,7 +28,6 @@ createObjectFromGCode = function (gcode, indxMax) { }, offsetG92: {x: 0, y: 0, z: 0, a: 0, e: 0}, plane: 'G17', // set default plane to G17 - Assume G17 if no plane specified in gcode. - isUnitsMm: true, lines: [], layers: { @@ -33,14 +36,18 @@ createObjectFromGCode = function (gcode, indxMax) { }, metrics: { + totalTime: 0, totaltimemax: 0, totalDist: 0 }, - previous: { + + /*previous: { lastArgs: {cmd: null}, lastFeedrate: null - }, + },*/ + lastArgs: {cmd: null}, + lastFeedrate: null, bbbox: { min: [100000, 100000, 100000], @@ -50,7 +57,17 @@ createObjectFromGCode = function (gcode, indxMax) { bbbox2: { min: [100000, 100000, 100000], max: [-100000, -100000, -100000] + }, + + bufSize : 10000, // Arbitrary - play around with! + colors: { + 'G0': 0x00ff00, + 'G1': 0x0000ff, + 'G2': 0x999900 } + /*colorG0: 0x00ff00, + colorG1: 0x0000ff, + colorG2: 0x999900,*/ } let lastLine = { @@ -74,4 +91,8 @@ createObjectFromGCode = function (gcode, indxMax) { let new3dObj = { name : 'newobj' } + + return { + state, lastLine, new3dObj + } } diff --git a/src/parse.js b/src/parse.js deleted file mode 100644 index 9e7cfc4..0000000 --- a/src/parse.js +++ /dev/null @@ -1,45 +0,0 @@ -export default function parser (gcode, progressCallback, doneCallback) { - lineObjects - laserxmax - laserymax - - console.log('inside this.parse') - object = null - var lines = gcode.split(/\r{0,1}\n/) - var count = lines.length - var maxTimePerChunk = 500 - var index = 0 - - function now () { - return new Date().getTime() - } - - - function doChunk () { - var progress = (index / count) - progressCallback(progress) - var startTime = now() - while (index < count && (now() - startTime) <= maxTimePerChunk) { - // console.log('parsing ' + lines[index]) - parseLine(lines[index], index) - ++index - } - closeLineSegment() - // console.log('done parsing ') - if (index < count) { - setTimeout(doChunk, 1) // set Timeout for async iteration - // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") - } else { - doneCallback() - object = drawobject() - object.add(lineObjects) - // console.log('Line Objects', lineObjects) - object.translateX(laserxmax / 2 * -1) - object.translateY(laserymax / 2 * -1) - object.name = 'object' - console.log('adding to scene') - scene.add(object) - } - } - doChunk() -} diff --git a/src/parseAsChunks.js b/src/parseAsChunks.js new file mode 100644 index 0000000..b370280 --- /dev/null +++ b/src/parseAsChunks.js @@ -0,0 +1,74 @@ +import parseLine from './parseLine' + +function now () { + return new Date().getTime() +} + +export default function parseAsChunks(gcode, state, params){ + const {lineObjects, laserxmax, laserymax} = params + + const lines = gcode.split(/\r{0,1}\n/) + const count = lines.length + const maxTimePerChunk = 500 + let index = 0 + + function doChunk () { + const progress = (index / count) + + let startTime = now() + while (index < count && (now() - startTime) <= maxTimePerChunk) { + //console.log('parsing ' + lines[index]) + parseLine(lines[index], index, state) + ++index + } + //closeLineSegment() //FIXME : add this back .??? or not + + // console.log('done parsing ') + if (index < count) { + setTimeout(doChunk, 1) // set Timeout for async iteration + // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") + } else { + console.log('done parsing') + } + } + + doChunk() +} + +//"old" for reference +export function __parser (gcode, params, progressCallback, doneCallback) { + + console.log('inside this.parse') + object = null + function doChunk () { + const progress = (index / count) + progressCallback(progress) + + let startTime = now() + while (index < count && (now() - startTime) <= maxTimePerChunk) { + // console.log('parsing ' + lines[index]) + parseLine(lines[index], index) + ++index + } + //closeLineSegment() //FIXME : add this back !! + + // console.log('done parsing ') + if (index < count) { + setTimeout(doChunk, 1) // set Timeout for async iteration + // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") + } else { + doneCallback() + object = drawobject() + object.add(lineObjects) + // console.log('Line Objects', lineObjects) + object.translateX(laserxmax / 2 * -1) + object.translateY(laserymax / 2 * -1) + object.name = 'object' + console.log('adding to scene') + scene.add(object) + } + } + + //start it + doChunk() +} diff --git a/src/parseLine.js b/src/parseLine.js index 7e5d6b7..01baff6 100644 --- a/src/parseLine.js +++ b/src/parseLine.js @@ -1,11 +1,5 @@ -export function parseLine (text, info, handlers) { - // console.log('Parsing: ',text) - let lastArgs = { - cmd: undefined - } - const state = { - isUnitsMm: true - } +export default function parseLine (text, index, state, handlers) { + console.log('Parsing: ', text) const origtext = text if (text.match(/^N/i)) { // remove line numbers if exist @@ -13,36 +7,60 @@ export function parseLine (text, info, handlers) { } const isG7 = text.match(/^G7/) // Is is G7 raster command? - if (!isG7) { // G7 D-data need to be untouched - text = text.replace(/G00/i, 'G0') // collapse leading zero g cmds to no leading zero - text = text.replace(/G0(\d)/i, 'G$1') // add spaces before g cmds and xyzabcijkf params - text = text.replace(/([gmtxyzabcijkfst])/ig, ' $1') // remove spaces after xyzabcijkf params because a number should be directly after them - text = text.replace(/([xyzabcijkfst])\s+/ig, '$1') // remove front and trailing space - } + const baseParse = isG7 ? parseRaster(text, origtext) : parseDefault(text, origtext) + const isComment = baseParse.isComment + text = baseParse.text + + return generateArgs(state, text, origtext, index, isComment, isG7) +} + +function parseDefault (text, origtext) { + let isComment = false + + text = text.replace(/G00/i, 'G0') // collapse leading zero g cmds to no leading zero + text = text.replace(/G0(\d)/i, 'G$1') // add spaces before g cmds and xyzabcijkf params + text = text.replace(/([gmtxyzabcijkfst])/ig, ' $1') // remove spaces after xyzabcijkf params because a number should be directly after them + text = text.replace(/([xyzabcijkfst])\s+/ig, '$1') // remove front and trailing space text = text.trim() + if (text.match(/^(;|\(|<)/)) { // see if comment + text = origtext + isComment = true + } else { + text = text.replace(/\(.*?\)/g, '') + } + + text = text.replace(/(;|\().*$/, '') // strip off end of line comment ; or () trailing + + return {text, isComment} +} + +function parseRaster (text, origtext) { let isComment = false + text = text.trim() if (text.match(/^(;|\(|<)/)) { // see if comment text = origtext isComment = true - } else { // make sure to remove inline comments - if (!isG7) { - text = text.replace(/\(.*?\)/g, '') - } } + return {text, isComment} +} + +function generateArgs (state, text, origtext, index, isComment, isG7) { + let {lastArgs} = state + let args = { // defaults to an empty/comment line args + cmd: 'empty or comment', + text, + origtext, + index, + isComment} - // after this , more tokenizing/ calling handlers if (text && !isComment) { - if (!isG7) { - text = text.replace(/(;|\().*$/, '') // strip off end of line comment ; or () trailing - } let tokens = text.split(/\s+/) if (tokens) { - var cmd = tokens[0] // check if a g or m cmd was included in gcode line - cmd = cmd.toUpperCase() // you are allowed to just specify coords on a line + let cmd = tokens[0].toUpperCase() // check if a g or m cmd was included in gcode line + // you are allowed to just specify coords on a line // and it should be assumed that the last specified gcode // cmd is what's assumed - isComment = false if (!cmd.match(/^(G|M|T)/i)) { cmd = lastArgs.cmd // we need to use the last gcode cmd tokens.unshift(cmd) // put at spot 0 in array @@ -51,17 +69,18 @@ export function parseLine (text, info, handlers) { // it assumes you should use the last cmd // however, need to remove inline comments (TODO. it seems parser works fine for now) } - const args = { - 'cmd': cmd, - 'text': text, - 'origtext': origtext, - 'indx': info, - 'isComment': isComment, - 'feedrate': null, - 'plane': undefined + + args = { + cmd, + text, + origtext, + index, + isComment, + feedrate: null, + plane: undefined } - if (tokens.length > 1 && !isComment) { + if (tokens.length > 1) { tokens.splice(1).forEach(function (token) { if (token && token.length > 0) { let key = token[0].toLowerCase() @@ -82,55 +101,52 @@ export function parseLine (text, info, handlers) { } }) } - let handler = handlers[cmd] || handlers['default'] if (!args.isComment) { // don't save if saw a comment - lastArgs = args - } - - if (handler) { - // do extra check here for units. units are - // specified via G20 or G21. We need to scan - // each line to see if it's inside the line because - // we were only catching it when it was the first cmd - // of the line. - if (args.text.match(/\bG20\b/i)) { - console.log('SETTING UNITS TO INCHES from pre-parser!!!') - state.isUnitsMm = false // false means inches cuz default is mm - } else if (args.text.match(/\bG21\b/i)) { - console.log('SETTING UNITS TO MM!!! from pre-parser') - state.isUnitsMm = true // true means mm - } - - if (args.text.match(/F([\d.]+)/i)) { // scan for feedrate - const feedrate = parseFloat(RegExp.$1) // we have a new feedrate - args.feedrate = feedrate - this.lastFeedrate = feedrate - } else { - args.feedrate = this.lastFeedrate // use feedrate from prior lines - } - - return handler(args, info, this) - } else { - console.error('No handler for gcode command!!!') + state.lastArgs = args } } + } + // OTHERWISE it was a comment or the line was empty + // we still need to create a segment with xyz in p2 + // so that when we're being asked to /gotoline we have a position + // for each gcode line, even comments. we just use the last real position + // to give each gcode line (even a blank line) a spot to go to + + // REMOVE THIS ? + // return handlers['default'](args, index) + let handlers = {} + let handler = handlers[args.cmd] || handlers['default'] + if (handler) { + adaptUnitsAndFeedrateForHandler(args, state) + // return handler(args, index) } else { - // it was a comment or the line was empty - // we still need to create a segment with xyz in p2 - // so that when we're being asked to /gotoline we have a position - // for each gcode line, even comments. we just use the last real position - // to give each gcode line (even a blank line) a spot to go to - - // REMOVE THIS ? - - const args = { - 'cmd': 'empty or comment', - 'text': text, - 'origtext': origtext, - 'indx': info, - 'isComment': isComment - } - return handlers['default'](args, info, this) + console.error('No handler for gcode command!!!') + } + + return args +} + +//FIXME: switch to non mutating ? +function adaptUnitsAndFeedrateForHandler (args, state) { + // do extra check here for units. units are + // specified via G20 or G21. We need to scan + // each line to see if it's inside the line because + // we were only catching it when it was the first cmd + // of the line. + if (args.text.match(/\bG20\b/i)) { + console.log('SETTING UNITS TO INCHES from pre-parser!!!') + state.isUnitsMm = false // false means inches cuz default is mm + } else if (args.text.match(/\bG21\b/i)) { + console.log('SETTING UNITS TO MM!!! from pre-parser') + state.isUnitsMm = true // true means mm + } + + if (args.text.match(/F([\d.]+)/i)) { // scan for feedrate + const feedrate = parseFloat(RegExp.$1) // we have a new feedrate + args.feedrate = feedrate + state.lastFeedrate = feedrate + } else { + args.feedrate = state.lastFeedrate // use feedrate from prior lines } } diff --git a/src/timeAndDistance.js b/src/timeAndDistance.js new file mode 100644 index 0000000..d17d8dd --- /dev/null +++ b/src/timeAndDistance.js @@ -0,0 +1,11 @@ + +export function updateTimeAndDistance(currentState, input){ + + totaltimemax += (timeMinutes * 60) + totalTime += timeMinutes + + return { + totalTime, + totaltimemax + } +} From 8184f4a384cec1fb0cd577a7cefccf4273227c42 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 22:07:22 +0100 Subject: [PATCH 12/34] refactor(): very basic parsing works! - modified parameters of many function to take in the current 'state' - removed/replaced some three.js specific code - adjustement to the api & internals of segments & arc - minor variable renamings for more clarity - some more 'es6' ification - lots of various fixes & tweaks --- src/drawObject.js | 9 +- src/gcodeHandlers.js | 182 ++++++++++++++------------ src/geometries/arcs.js | 25 ++-- src/geometries/segments.js | 132 ++++++++++--------- src/index.js | 23 ++-- src/layers.js | 2 +- src/legacy/gcode-parser-breakapart.js | 6 +- src/lineGroup.js | 69 ++++------ src/objFromGcode.js | 61 +++++++-- src/parseAsChunks.js | 19 ++- src/parseLine.js | 13 +- src/utils.js | 4 +- 12 files changed, 297 insertions(+), 248 deletions(-) diff --git a/src/drawObject.js b/src/drawObject.js index 9d032fc..330291d 100644 --- a/src/drawObject.js +++ b/src/drawObject.js @@ -1,11 +1,12 @@ -export default function drawobject () { +export default function drawobject (state) { var newObject = false // console.log("INSIDE DRAWOBJECT") // set what units we're using in the gcode - isUnitsMm = parser.isUnitsMm + isUnitsMm = state.isUnitsMm - newObject = new THREE.Object3D() - newObject.name = 'newObject' + newObject = { + name:'newObject' + } // old approach of monolithic line segment for (var lid in layers3d) { diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js index 16bb616..ae27c95 100644 --- a/src/gcodeHandlers.js +++ b/src/gcodeHandlers.js @@ -1,8 +1,9 @@ import { absolute, delta } from './utils' -import { addSegment, addLineSegment, addFakeSegment } from './parseFunctions' +import { addSegment, addLineSegment, addFakeSegment } from './geometries/segments' +import { newLayer } from './layers' export default function makeHandlers (params) { - let state = { + /*let state = { isUnitsMm: true, plane: undefined, relative: true, @@ -10,32 +11,39 @@ export default function makeHandlers (params) { spotSizeG7: undefined, dirG7: 0 } - const lasermultiply = 100 const lineObject = {} let lastLine = undefined let lines = undefined - // EEK !! var lasermultiply = $('#lasermultiply').val() || 100 + + var lineObject = {active: false, + vertexBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments + colorBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments + nLines: 0, + } + */ const handlers = { // set the g92 offsets for the parser - defaults to no offset // When doing CNC, generally G0 just moves to a new location // as fast as possible which means no milling or extruding is happening in G0. // So, let's color it uniquely to indicate it's just a toolhead move. - G0: function (args, index) { + G0: function (state, args, index) { + const {lastLine} = state const newLine = { - x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, - y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, - z: args.z !== undefined ? absolute(lastLine.z, args.z) + state.offsetG92.z : lastLine.z, - a: args.a !== undefined ? absolute(lastLine.a, args.a) + state.offsetG92.a : lastLine.a, - e: args.e !== undefined ? absolute(lastLine.e, args.e) + state.offsetG92.e : lastLine.e, + x: args.x !== undefined ? absolute(state.relative, lastLine.x, args.x) + state.specifics.G92.offset.x : lastLine.x, + y: args.y !== undefined ? absolute(state.relative, lastLine.y, args.y) + state.specifics.G92.offset.y : lastLine.y, + z: args.z !== undefined ? absolute(state.relative, lastLine.z, args.z) + state.specifics.G92.offset.z : lastLine.z, + a: args.a !== undefined ? absolute(state.relative, lastLine.a, args.a) + state.specifics.G92.offset.a : lastLine.a, + e: args.e !== undefined ? absolute(state.relative, lastLine.e, args.e) + state.specifics.G92.offset.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: 100, g0: true } - addLineSegment(lastLine, newLine, lineObject, lasermultiply) - lastLine = newLine + addLineSegment(state, args, lastLine, newLine) + state.lastLine = newLine }, - G1: function (args, index) { + G1: function (state, args, index) { + const {lastLine, layer} = state // Example: G1 Z1.0 F3000 // G1 X99.9948 Y80.0611 Z15.0 F1500.0 E981.64869 // G1 E104.25841 F1800.0 @@ -45,11 +53,11 @@ export default function makeHandlers (params) { // 22.4 mm. const newLine = { - x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, - y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, - z: args.z !== undefined ? absolute(lastLine.z, args.z) + state.offsetG92.z : lastLine.z, - a: args.a !== undefined ? absolute(lastLine.a, args.a) + state.offsetG92.a : lastLine.a, - e: args.e !== undefined ? absolute(lastLine.e, args.e) + state.offsetG92.e : lastLine.e, + x: args.x !== undefined ? absolute(state.relative, lastLine.x, args.x) + state.specifics.G92.offset.x : lastLine.x, + y: args.y !== undefined ? absolute(state.relative, lastLine.y, args.y) + state.specifics.G92.offset.y : lastLine.y, + z: args.z !== undefined ? absolute(state.relative, lastLine.z, args.z) + state.specifics.G92.offset.z : lastLine.z, + a: args.a !== undefined ? absolute(state.relative, lastLine.a, args.a) + state.specifics.G92.offset.a : lastLine.a, + e: args.e !== undefined ? absolute(state.relative, lastLine.e, args.e) + state.specifics.G92.offset.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: args.s !== undefined ? args.s : lastLine.s, t: args.t !== undefined ? args.t : lastLine.t, @@ -59,12 +67,13 @@ export default function makeHandlers (params) { watching when we extrude at a new Z position */ if (delta(lastLine.e, newLine.e) > 0) { newLine.extruding = delta(lastLine.e, newLine.e) > 0 - if (layer == undefined || newLine.z != layer.z) cofg.newLayer(newLine) + if (layer === undefined || newLine.z !== layer.z) cofg.newLayer(newLine) } - addLineSegment(lastLine, newLine, lineObject, lasermultiply) - lastLine = newLine + addLineSegment(state, args, lastLine, newLine) + state.lastLine = newLine }, - G2: function (args, index, gcp) { + G2: function (state, args, index, gcp) { + const {plane, lastLine} = state // this is an arc move from lastLine's xy to the new xy. we'll // show it as a light gray line, but we'll also sub-render the // arc itself by figuring out the sub-segments @@ -72,11 +81,11 @@ export default function makeHandlers (params) { args.plane = plane // set the plane for this command to whatever the current plane is const newLine = { - x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, - y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, - z: args.z !== undefined ? absolute(lastLine.z, args.z) + state.offsetG92.z : lastLine.z, - a: args.a !== undefined ? absolute(lastLine.a, args.a) + state.offsetG92.a : lastLine.a, - e: args.e !== undefined ? absolute(lastLine.e, args.e) + state.offsetG92.e : lastLine.e, + x: args.x !== undefined ? absolute(state.relative, lastLine.x, args.x) + state.specifics.G92.offset.x : lastLine.x, + y: args.y !== undefined ? absolute(state.relative, lastLine.y, args.y) + state.specifics.G92.offset.y : lastLine.y, + z: args.z !== undefined ? absolute(state.relative, lastLine.z, args.z) + state.specifics.G92.offset.z : lastLine.z, + a: args.a !== undefined ? absolute(state.relative, lastLine.a, args.a) + state.specifics.G92.offset.a : lastLine.a, + e: args.e !== undefined ? absolute(state.relative, lastLine.e, args.e) + state.specifics.G92.offset.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: args.s !== undefined ? args.s : lastLine.s, t: args.t !== undefined ? args.t : lastLine.t, @@ -89,10 +98,12 @@ export default function makeHandlers (params) { clockwise: !args.clockwise ? true : args.clockwise // FIXME : always true ?? } // if (args.clockwise === false) newLine.clockwise = args.clockwise - addSegment(lastLine, newLine, args) - lastLine = newLine + addSegment(state, args, lastLine, newLine) + state.lastLine = newLine }, - G3: function (args, index, gcp) { + G3: function (state, args, index, gcp) { + const {plane, lastLine} = state + // this is an arc move from lastLine's xy to the new xy. same // as G2 but reverse args.arc = true @@ -100,11 +111,11 @@ export default function makeHandlers (params) { args.plane = plane // set the plane for this command to whatever the current plane is const newLine = { - x: args.x !== undefined ? absolute(lastLine.x, args.x) + state.offsetG92.x : lastLine.x, - y: args.y !== undefined ? absolute(lastLine.y, args.y) + state.offsetG92.y : lastLine.y, - z: args.z !== undefined ? absolute(lastLine.z, args.z) + state.offsetG92.z : lastLine.z, - a: args.a !== undefined ? absolute(lastLine.a, args.a) + state.offsetG92.a : lastLine.a, - e: args.e !== undefined ? absolute(lastLine.e, args.e) + state.offsetG92.e : lastLine.e, + x: args.x !== undefined ? absolute(state.relative, lastLine.x, args.x) + state.specifics.G92.offset.x : lastLine.x, + y: args.y !== undefined ? absolute(state.relative, lastLine.y, args.y) + state.specifics.G92.offset.y : lastLine.y, + z: args.z !== undefined ? absolute(state.relative, lastLine.z, args.z) + state.specifics.G92.offset.z : lastLine.z, + a: args.a !== undefined ? absolute(state.relative, lastLine.a, args.a) + state.specifics.G92.offset.a : lastLine.a, + e: args.e !== undefined ? absolute(state.relative, lastLine.e, args.e) + state.specifics.G92.offset.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: args.s !== undefined ? args.s : lastLine.s, t: args.t !== undefined ? args.t : lastLine.t, @@ -117,11 +128,12 @@ export default function makeHandlers (params) { clockwise: !args.clockwise ? true : args.clockwise // FIXME : always true ?? } // if (args.clockwise === false) newLine.clockwise = args.clockwise - addSegment(lastLine, newLine, args) - lastLine = newLine + addSegment(state, args, lastLine, newLine) + state.lastLine = newLine }, - G7: function (args, index) { + G7: function (state, args, index) { + const {lasermultiply, lastLine, lineObject, layer} = state // Example: G7 L68 D//////sljasflsfagdxsd,.df9078rhfnxm (68 of em) // G7 $1 L4 DAAA= // G7 $0 L4 D2312 @@ -140,11 +152,11 @@ export default function makeHandlers (params) { var buf = atob(args.d) if (typeof args.dollar !== 'undefined') { // Move Y, change direction - state.dirG7 = args.dollar + state.specifics.G7.dir = args.dollar const newLine = { x: lastLine.x, - y: lastLine.y + state.spotSizeG7, + y: lastLine.y + state.specifics.G7.spotSize, z: lastLine.z, a: lastLine.a, e: lastLine.e, @@ -153,13 +165,13 @@ export default function makeHandlers (params) { t: lastLine.t, g0: true } - addLineSegment(lastLine, newLine, lineObject, lasermultiply) - lastLine = newLine + addLineSegment(state, args, lastLine, newLine) + state.lastLine = newLine } for (var i = 0; i < buf.length; i++) { // Process a base64-encoded chunk const intensity = 255 - buf.charCodeAt(i) // 255 - 0 const newLine = { - x: lastLine.x + state.spotSizeG7 * (state.dirG7 === 1 ? 1 : -1), + x: lastLine.x + state.specifics.G7.spotSize * (state.specifics.G7.dir === 1 ? 1 : -1), y: lastLine.y, z: lastLine.z, a: lastLine.a, @@ -169,30 +181,30 @@ export default function makeHandlers (params) { t: lastLine.t, g7: true } - addLineSegment(lastLine, newLine, lineObject, lasermultiply) - lastLine = newLine + addLineSegment(state, args, lastLine, newLine) + state.lastLine = newLine } }, - G17: function (args) { + G17: function (state, args) { console.log('SETTING XY PLANE') - plane = 'G17' - addFakeSegment(args, lineObject, lastLine, lines) + state.plane = 'G17' + addFakeSegment(state, args) }, - G18: function (args) { + G18: function (state, args) { console.log('SETTING XZ PLANE') state.plane = 'G18' - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - G19: function (args) { + G19: function (state, args) { console.log('SETTING YZ PLANE') state.plane = 'G19' - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - G20: function (args) { + G20: function (state, args) { // G21: Set Units to Inches // We don't really have to do anything since 3d viewer is unit agnostic // However, we need to set a global property so the trinket decorations @@ -200,44 +212,44 @@ export default function makeHandlers (params) { // later on when they are drawn after the gcode is rendered // console.log("SETTING UNITS TO INCHES!!!") state.isUnitsMm = false // false means inches cuz default is mm - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - G21: function (args) { + G21: function (state, args) { // G21: Set Units to Millimeters // Example: G21 // Units from now on are in millimeters. (This is the RepRap default.) // console.log("SETTING UNITS TO MM!!!") state.isUnitsMm = true // true means mm - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - G73: function (args, index, gcp) { + G73: function (state, args, index, gcp) { // peck drilling. just treat as g1 console.log('G73 gcp:', gcp) gcp.handlers.G1(args) }, - G90: function (args) { + G90: function (state, args) { // G90: Set to Absolute Positioning // Example: G90 // All coordinates from now on are absolute relative to the // origin of the machine. (This is the RepRap default.) state.relative = false - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - G91: function (args) { + G91: function (state, args) { // G91: Set to Relative Positioning // Example: G91 // All coordinates from now on are relative to the last position. // TODO! state.relative = true - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - G92: function (args) { // E0 + G92: function (state, args) { // E0 // G92: Set Position // Example: G92 E0 // Allows programming of absolute zero point, by reseting the @@ -246,36 +258,36 @@ export default function makeHandlers (params) { // No physical motion will occur. // TODO: Only support E0 - var newLine = lastLine + var newLine = state.lastLine - state.offsetG92.x = (args.x !== undefined ? (args.x === 0 ? newLine.x : newLine.x - args.x) : 0) - state.offsetG92.y = (args.y !== undefined ? (args.y === 0 ? newLine.y : newLine.y - args.y) : 0) - state.offsetG92.z = (args.z !== undefined ? (args.z === 0 ? newLine.z : newLine.z - args.z) : 0) - state.offsetG92.a = (args.a !== undefined ? (args.a === 0 ? newLine.a : newLine.a - args.a) : 0) - state.offsetG92.e = (args.e !== undefined ? (args.e === 0 ? newLine.e : newLine.e - args.e) : 0) + state.specifics.G92.offset.x = (args.x !== undefined ? (args.x === 0 ? newLine.x : newLine.x - args.x) : 0) + state.specifics.G92.offset.y = (args.y !== undefined ? (args.y === 0 ? newLine.y : newLine.y - args.y) : 0) + state.specifics.G92.offset.z = (args.z !== undefined ? (args.z === 0 ? newLine.z : newLine.z - args.z) : 0) + state.specifics.G92.offset.a = (args.a !== undefined ? (args.a === 0 ? newLine.a : newLine.a - args.a) : 0) + state.specifics.G92.offset.e = (args.e !== undefined ? (args.e === 0 ? newLine.e : newLine.e - args.e) : 0) // newLine.x = args.x !== undefined ? args.x + newLine.x : newLine.x // newLine.y = args.y !== undefined ? args.y + newLine.y : newLine.y // newLine.z = args.z !== undefined ? args.z + newLine.z : newLine.z // newLine.e = args.e !== undefined ? args.e + newLine.e : newLine.e - // console.log("G92", lastLine, newLine, args, state.offsetG92) + // console.log("G92", lastLine, newLine, state, args.specifics.G92.offset) - // lastLine = newLine - addFakeSegment(args, lineObject, lastLine, lines) + // state.lastLine = newLine + addFakeSegment(state, args) }, - M30: function (args) { - addFakeSegment(args, lineObject, lastLine, lines) + M30: function (state, args) { + addFakeSegment(state, args) }, - M82: function (args) { + M82: function (state, args) { // M82: Set E codes absolute (default) // Descriped in Sprintrun source code. // No-op, so long as M83 is not supported. - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - M84: function (args) { + M84: function (state, args) { // M84: Stop idle hold // Example: M84 // Stop the idle hold on all axis and extruder. In some cases the @@ -285,33 +297,33 @@ export default function makeHandlers (params) { // in between or after printjobs. // No-op - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - M649: function (args) { + M649: function (state, args) { // M649: Laser options for Marlin // M649 S R B2 // Intensity = lasermultiply? - if (typeof args.r !== 'undefined') { state.spotSizeG7 = args.r} + if (typeof args.r !== 'undefined') { state.specifics.G7.spotSize = args.r } }, // Dual Head 3D Printing Support - T0: function (args) { + T0: function (state, args) { // console.log('Found Tool: ', args) lastLine.t = 0 - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - T1: function (args) { + T1: function (state, args) { // console.log('Found Tool: ', args) lastLine.t = 1 - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) }, - 'default': function (args, info) { + 'default': function (state, args, index) { // if (!args.isComment) // console.log('Unknown command:', args.cmd, args, info) - addFakeSegment(args, lineObject, lastLine, lines) + addFakeSegment(state, args) } } diff --git a/src/geometries/arcs.js b/src/geometries/arcs.js index ab761a1..0998f10 100644 --- a/src/geometries/arcs.js +++ b/src/geometries/arcs.js @@ -1,25 +1,24 @@ -export function drawArc (aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, plane) { +export function drawArc (state, aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, plane) { // console.log("drawArc:", aX, aY, aZ, aRadius, aStartAngle, aEndAngle, aClockwise) - var ac = new THREE.ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) + let ac = new THREE.ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) // console.log("ac:", ac) - var acmat = new THREE.LineBasicMaterial({ + const material = { color: 0x00aaff, - opacity: 0.5, - transparent: true - }) - var acgeo = new THREE.Geometry() - var ctr = 0 - var z = aZ + opacity: 0.5 + } + let acgeo = [] + let ctr = 0 + let z = aZ ac.getPoints(20).forEach(function (v) { // console.log(v) z = (((endaZ - aZ) / 20) * ctr) + aZ - acgeo.vertices.push(new THREE.Vector3(v.x, v.y, z)) + acgeo.push(v.x, v.y, z) ctr++ }) - var aco = new THREE.Line(acgeo, acmat) + const aco = {geometry: acgeo, material} // aco.position.set(pArc.x, pArc.y, pArc.z) // console.log("aco:", aco) - this.extraObjects[plane].push(aco) + state.extraObjects[plane].push(aco) return aco } @@ -78,6 +77,7 @@ export function drawArcFrom2PtsAndCenter (vp1, vp2, vpArc, args) { } if (anglepArcp1 === anglepArcp2 && clwise === false) + { let obj = undefined // Draw full circle if angles are both zero, // start & end points are same point... I think @@ -90,6 +90,7 @@ export function drawArcFrom2PtsAndCenter (vp1, vp2, vpArc, args) { break default: obj = drawArc(vpArc.x, vpArc.y, vp1.z, vp2.z, radius, anglepArcp1, (anglepArcp2 + (2 * Math.PI)), clwise, 'G17') + } } else switch (args.plane) { diff --git a/src/geometries/segments.js b/src/geometries/segments.js index 913c35f..7473c72 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -1,7 +1,11 @@ -import {getLineGroup} from './foo' +import { getLineGroup } from '../layers' +import {drawArcFrom2PtsAndCenter} from './arcs' -export function addSegment (p1, p2, args, lineObject) { - closeLineSegment(lineObject) +export function addSegment (state, args, p1, p2) { + if(state.debug){ + console.log('addSegment') + } + closeLineSegment(state) let bbbox = [] let bbbox2 = [] @@ -17,19 +21,19 @@ export function addSegment (p1, p2, args, lineObject) { // console.log("") // console.log("drawing arc. p1:", p1, ", p2:", p2) - // var segmentCount = 12 + // let segmentCount = 12 // figure out the 3 pts we are dealing with // the start, the end, and the center of the arc circle // radius is dist from p1 x/y/z to pArc x/y/z // if(args.clockwise === false || args.cmd === "G3"){ - // var vp2 = [p1.x, p1.y, p1.z] - // var vp1 = [p2.x, p2.y, p2.z] + // let vp2 = [p1.x, p1.y, p1.z] + // let vp1 = [p2.x, p2.y, p2.z] // } // else { const vp1 = [p1.x, p1.y, p1.z] const vp2 = [p2.x, p2.y, p2.z] // } - var vpArc + let vpArc // if this is an R arc gcode command, we're given the radius, so we // don't have to calculate it. however we need to determine center @@ -123,15 +127,14 @@ export function addSegment (p1, p2, args, lineObject) { } } - if ((p2.clockwise === true && radius >= 0) || (p2.clockwise === false && radius < 0)) - { + if ((p2.clockwise === true && radius >= 0) || (p2.clockwise === false && radius < 0)) { vpArc = [cw.x, cw.y, cw.z] } else vpArc = [ccw.x, ccw.y, ccw.z] } else { // this code deals with IJK gcode commands /*if(args.clockwise === false || args.cmd === "G3") - var pArc = { + let pArc = { x: p2.arci ? p1.x + p2.arci : p1.x, y: p2.arcj ? p1.y + p2.arcj : p1.y, z: p2.arck ? p1.z + p2.arck : p1.z, @@ -145,11 +148,11 @@ export function addSegment (p1, p2, args, lineObject) { vpArc = [pArc.x, pArc.y, pArc.z] } - const threeObjArc = this.drawArcFrom2PtsAndCenter(vp1, vp2, vpArc, args) + const arcObj = drawArcFrom2PtsAndCenter(vp1, vp2, vpArc, args) // still push the normal p1/p2 point for debug p2.g2 = true - p2.threeObjArc = threeObjArc + p2.arcObj = arcObj group = getLineGroup(p2, args) // these golden lines showing start/end of a g2 or g3 arc were confusing people // so hiding them for now. jlauer 8/15/15 @@ -205,11 +208,11 @@ export function addSegment (p1, p2, args, lineObject) { a unique object for each line of gcode, including g2/g3's make sure userData is good too */ - var gcodeObj + let gcodeObj if (p2.arc) { // use the arc that already got built - gcodeObj = p2.threeObjArc + gcodeObj = p2.arcObj } else { // make a line let color = 0X0000ff @@ -229,13 +232,11 @@ export function addSegment (p1, p2, args, lineObject) { color = 0x0033ff } - var material = new THREE.LineBasicMaterial({ + const material = { color: color, - opacity: 0.5, - transparent: true - }) - var line = new THREE.Line(geometry, material) - gcodeObj = line + opacity: 0.5 + } + gcodeObj = {geometry, material} } gcodeObj.userData.p2 = p2 gcodeObj.userData.args = args @@ -249,12 +250,12 @@ export function addSegment (p1, p2, args, lineObject) { let b if (p2.arc) { // calc dist of all lines - // console.log("this is an arc to calc dist for. p2.threeObjArc:", p2.threeObjArc, "p2:", p2) - var arcGeo = p2.threeObjArc.geometry + // console.log("this is an arc to calc dist for. p2.arcObj:", p2.arcObj, "p2:", p2) + let arcGeo = p2.arcObj.geometry // console.log("arcGeo:", arcGeo) - var tad2 = 0 - for (var arcLineCtr = 0; arcLineCtr < arcGeo.vertices.length - 1; arcLineCtr++) { + let tad2 = 0 + for (let arcLineCtr = 0; arcLineCtr < arcGeo.vertices.length - 1; arcLineCtr++) { tad2 += arcGeo.vertices[arcLineCtr].distanceTo(arcGeo.vertices[arcLineCtr + 1]) } // console.log("tad2:", tad2) @@ -276,7 +277,7 @@ export function addSegment (p1, p2, args, lineObject) { sv = args.s // console.log(sv) - //time distance computation + // time distance computation if (dist > 0) { totalDist += dist } @@ -284,15 +285,15 @@ export function addSegment (p1, p2, args, lineObject) { // time to execute this move // if this move is 10mm and we are moving at 100mm/min then // this move will take 10/100 = 0.1 minutes or 6 seconds - var timeMinutes = 0 + let timeMinutes = 0 if (dist > 0) { - var fr + let feedrate if (args.feedrate > 0) { - fr = args.feedrate + feedrate = args.feedrate } else { - fr = 100 + feedrate = 100 } - timeMinutes = dist / fr + timeMinutes = dist / feedrate // adjust for acceleration, meaning estimate // this will run longer than estimated from the math @@ -311,29 +312,32 @@ export function addSegment (p1, p2, args, lineObject) { // console.log('Total Time'+totalTime) totaltimemax += (timeMinutes * 60) -// console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) + // console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) return { dist, - timeMinutes - } + timeMinutes} } -export function addFakeSegment (args, lineObject, lastLine, lines) { - closeLineSegment(lineObject) +export function addFakeSegment (state, args) { // lineObject, lastLine, lines) { + if (state.debug) { + console.log('addFakeSegment') + } + closeLineSegment(state) // line.args = args const arg2 = { isFake: true, text: args.text, - indx: args.indx, + index: args.index, isComment: args.text.match(/^(;|\(|<)/) } - lines.push({ - p2: lastLine, // since this is fake, just use lastLine as xyz + state.lines.push({ + p2: state.lastLine, // since this is fake, just use lastLine as xyz args: arg2 }) } -export function addLineSegment (p1, p2, lineObject, lasermultiply, bufSize) { +export function addLineSegment (state, args, p1, p2) { + let {lineObject, lasermultiply, bufSize} = state let i = lineObject.nLines * 6 // lineObject.vertexBuf[i+0] = p1.x // Vertices // lineObject.vertexBuf[i+1] = p1.y @@ -343,10 +347,10 @@ export function addLineSegment (p1, p2, lineObject, lasermultiply, bufSize) { // lineObject.vertexBuf[i+5] = p2.z if (p1.a !== 0 || p2.a !== 0) { // A axis: rotate around X - var R1 = Math.sqrt(p1.y * p1.y + p1.z * p1.z) - var R2 = Math.sqrt(p2.y * p2.y + p2.z * p2.z) - var a1 = p1.y === 0 ? Math.sign(p1.z) * 90 : Math.atan2(p1.z, p1.y) * 180.0 / Math.PI - var a2 = p2.y === 0 ? Math.sign(p2.z) * 90 : Math.atan2(p2.z, p2.y) * 180.0 / Math.PI + const R1 = Math.sqrt(p1.y * p1.y + p1.z * p1.z) + const R2 = Math.sqrt(p2.y * p2.y + p2.z * p2.z) + const a1 = p1.y === 0 ? Math.sign(p1.z) * 90 : Math.atan2(p1.z, p1.y) * 180.0 / Math.PI + const a2 = p2.y === 0 ? Math.sign(p2.z) * 90 : Math.atan2(p2.z, p2.y) * 180.0 / Math.PI lineObject.vertexBuf[i + 0] = p1.x lineObject.vertexBuf[i + 1] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) lineObject.vertexBuf[i + 2] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) @@ -371,33 +375,33 @@ export function addLineSegment (p1, p2, lineObject, lasermultiply, bufSize) { } // console.log("Segment " + p1) - var col - var intensity + let color + let intensity if (p2.g0) { // g0 - col = {r: 0, g: 1, b: 0} - intensity = 1.0 - p2.s / lasermultiply // lasermultiply + color = {r: 0, g: 1, b: 0} + intensity = 1.0 - p2.s / lasermultiply } else if (p2.g1) { // g1 - col = {r: 0.7, g: 0, b: 0} - intensity = 1.0 - p2.s / lasermultiply // lasermultiply + color = {r: 0.7, g: 0, b: 0} + intensity = 1.0 - p2.s / lasermultiply } else if (p2.g7) { // g7 - col = {r: 0, g: 0, b: 1} - intensity = 1.0 - p2.s / lasermultiply // lasermultiply + color = {r: 0, g: 0, b: 1} + intensity = 1.0 - p2.s / lasermultiply } else { - col = {r: 0, g: 1, b: 1} - intensity = 1.0 - p2.s / lasermultiply // lasermultiply + color = {r: 0, g: 1, b: 1} + intensity = 1.0 - p2.s / lasermultiply } - lineObject.colorBuf[i + 0] = col.r + (1 - col.r) * intensity // Colors - lineObject.colorBuf[i + 1] = col.g + (1 - col.g) * intensity - lineObject.colorBuf[i + 2] = col.b + (1 - col.b) * intensity - lineObject.colorBuf[i + 3] = col.r + (1 - col.r) * intensity - lineObject.colorBuf[i + 4] = col.g + (1 - col.g) * intensity - lineObject.colorBuf[i + 5] = col.b + (1 - col.b) * intensity + lineObject.colorBuf[i + 0] = color.r + (1 - color.r) * intensity // Colors + lineObject.colorBuf[i + 1] = color.g + (1 - color.g) * intensity + lineObject.colorBuf[i + 2] = color.b + (1 - color.b) * intensity + lineObject.colorBuf[i + 3] = color.r + (1 - color.r) * intensity + lineObject.colorBuf[i + 4] = color.g + (1 - color.g) * intensity + lineObject.colorBuf[i + 5] = color.b + (1 - color.b) * intensity lineObject.nLines++ if (lineObject.nLines === bufSize) { - closeLineSegment(lineObject) + closeLineSegment(state) } const dist = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)) @@ -405,12 +409,10 @@ export function addLineSegment (p1, p2, lineObject, lasermultiply, bufSize) { // timeMinutes = dist / p2.f // totalTime += timeMinutes // totaltimemax = totalTime * 60 - return { - dist - } + return {dist} } -export function closeLineSegment (lineObject) { +export function closeLineSegment ({lineObject, lineObjects}) { if (lineObject.nLines === 0) { return } @@ -421,6 +423,6 @@ export function closeLineSegment (lineObject) { colors.set(lineObject.colorBuf.subarray(0, lineObject.nLines * 6)) const lines = {vertices, colors} - lineObjects.add(lines) // Feed the objects to "object" in doChunk() + lineObjects.lines.push(lines) // Feed the objects to "object" in doChunk() lineObject.nLines = 0 } diff --git a/src/index.js b/src/index.js index 7dd0e27..882d5fb 100644 --- a/src/index.js +++ b/src/index.js @@ -5,20 +5,25 @@ * Description: A gcode parser, **/ -//import makeHandlers from './gcodeHandlers' +import makeHandlers from './gcodeHandlers' import parseAsChunks from './parseAsChunks' import makeBaseData from './objFromGcode' export default function parse(data, parameters={}){ + //const params = Object.assign({}, machineDefaults, parameters) - const defaults ={ - laserxmax: 0, - laserymax: 0 - } + const handlers = makeHandlers() + let state = makeBaseData().state - const {state} = makeBaseData() - parseAsChunks(data, state, defaults) - //const gCodeHandlers = makeHandlers() + //FIXME: not sure AT ALL where/when lineObject is supposed to be created + state.lineObject = { + active: false, + vertexBuf: new Float32Array(6 * state.bufSize), // Start with bufSize line segments + colorBuf: new Float32Array(6 * state.bufSize), // Start with bufSize line segments + nLines: 0 + }, + + parseAsChunks(state, handlers, data) } @@ -26,7 +31,7 @@ export default function parse(data, parameters={}){ OLD code structure , for reference ! //main entry point !! - createObjectFromGCode(gcode, indxMax) + createObjectFromGCode(gcode, indexMax) => handlers = { gcode(G1 etc): function => drawArc diff --git a/src/layers.js b/src/layers.js index 7fee7b5..c79cc46 100644 --- a/src/layers.js +++ b/src/layers.js @@ -1,6 +1,6 @@ export function newLayer (line, layers3d) { // console.log("layers3d:", layers3d, "layers3d.length", layers3d.length) - layer = { + let layer = { type: {}, layer: layers3d.length, z: line.z diff --git a/src/legacy/gcode-parser-breakapart.js b/src/legacy/gcode-parser-breakapart.js index 138d15b..5a68c16 100644 --- a/src/legacy/gcode-parser-breakapart.js +++ b/src/legacy/gcode-parser-breakapart.js @@ -19,11 +19,7 @@ function GCodeParser (handlers) { } - var lineObject = {active: false, - vertexBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments - colorBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments - nLines: 0, - } + var material = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors, opacity: 0.8, transparent: true, diff --git a/src/lineGroup.js b/src/lineGroup.js index a31e70a..82b9131 100644 --- a/src/lineGroup.js +++ b/src/lineGroup.js @@ -1,84 +1,71 @@ -getLineGroup = function (line, args) { +export function getLineGroup (state, line, args) { console.log('getLineGroup:', line) - if (layer == undefined) newLayer(line) - var speed = Math.round(line.e / 1000) - var opacity = line.s - var tool = parseInt(line.t, 10) - // /console.log('Speed: ' , speed , ' opacity: ', opacity) - var grouptype = speed + opacity - var color = null - // var color = new THREE.Color(0x990000) + if (state.layer === undefined) newLayer(line) + const speed = Math.round(line.e / 1000) + let opacity = line.s + let tool = parseInt(line.t, 10) + let grouptype = speed + opacity + let color = null if (typeof line.s === 'undefined') { opacity = 0.3 } else { - var lasermultiply = $('#lasermultiply').val() || 100 - opacity = line.s / lasermultiply - console.log(opacity + ', ' + line.x) - // } + opacity = line.s / state.lasermultiply } - // console.log(opacity) - // LaserWeb 3D Viewer Colors // LaserWeb 3D Viewer Colors if (typeof line.extruding === 'undefined' && typeof line.s === 'undefined') { // console.log('G1 without extrude', line) grouptype = 'g0' opacity = 0.3 - color = new THREE.Color(0x00ff00) + color = 0x00ff00 } else { // console.log('G1 with extrude', line) if (line.g0) { grouptype = 'g0' - // color = new THREE.Color(0x00ff00) opacity = 0.3 - color = new THREE.Color(0x00ff00) + color = 0x00ff00 } else if (line.g2) { grouptype = 'g2' - // color = new THREE.Color(0x999900) - color = new THREE.Color(0x990000) - } else if (line.t == 0) { + color = 0x990000 + } else if (line.t === 0) { grouptype = 't0' - // color = new THREE.Color(0x999900) - color = new THREE.Color(0x0000ff) - } else if (line.t == 1) { + color = 0x0000ff + } else if (line.t === 1) { grouptype = 't1' - // color = new THREE.Color(0x999900) - color = new THREE.Color(0xff00ff) + color = 0xff00ff } else if (line.arc) { grouptype = 'arc' - color = new THREE.Color(0x990000) + color = 0x990000 } else { - color = new THREE.Color(0x990000) + color = 0x990000 } } - // see if we have reached indxMax, if so draw, but + // see if we have reached indexMax, if so draw, but // make it ghosted - // if (args.indx > indxMax) { + // if (args.index > indexMax) { // grouptype = "ghost" - // //console.log("args.indx > indxMax", args, indxMax) - // color = new THREE.Color(0x000000) + // //console.log("args.index > indexMax", args, indexMax) + // color = 0x000000) // } - // if (line.color) color = new THREE.Color(line.color) - if (layer.type[grouptype] == undefined) { - layer.type[grouptype] = { + // if (line.color) color = line.color) + if (state.layer.type[grouptype] === undefined) { + state.layer.type[grouptype] = { type: grouptype, feed: line.e, extruding: line.extruding, color: color, segmentCount: 0, - material: new THREE.LineBasicMaterial({ + //FIXME: how to deal with the things below ? + /*material: new THREE.LineBasicMaterial({ opacity: opacity, // opacity: line.extruding ? 0.5: line.g2 ? 0.2 : 0.3, transparent: true, linewidth: 1, vertexColors: THREE.FaceColors }), - geometry: new THREE.Geometry(), + geometry: new THREE.Geometry(),*/ } - // if (args.indx > indxMax) { - // layer.type[grouptype].material.opacity = 0.05 - // } } - return layer.type[grouptype] + return state.layer.type[grouptype] } diff --git a/src/objFromGcode.js b/src/objFromGcode.js index ebd982f..33d177b 100644 --- a/src/objFromGcode.js +++ b/src/objFromGcode.js @@ -1,4 +1,4 @@ -export default function createObjectFromGCode(gcode, indxMax) { +export default function createObjectFromGCode (gcode, indexMax) { console.log('Generating GCODE Preview') // console.group("Rendering GCODE Preview") // debugger @@ -14,19 +14,23 @@ export default function createObjectFromGCode(gcode, indxMax) { // the gcode rendering to attach to scene let state = { + debug: true, + tool: null, relative: false, isUnitsMm: true, lineObjects: { + lines: [], + nLines: 0, name: 'LineObjects' }, + extraObjects: { 'G17': [], 'G18': [], 'G19': [] }, - offsetG92: {x: 0, y: 0, z: 0, a: 0, e: 0}, plane: 'G17', // set default plane to G17 - Assume G17 if no plane specified in gcode. lines: [], @@ -41,13 +45,22 @@ export default function createObjectFromGCode(gcode, indxMax) { totalDist: 0 }, - /*previous: { lastArgs: {cmd: null}, lastFeedrate: null },*/ lastArgs: {cmd: null}, lastFeedrate: null, + lastLine: { + x: 0, + y: 0, + z: 0, + a: 0, + e: 0, + f: 0, + feedrate: null, + extruding: false + }, bbbox: { min: [100000, 100000, 100000], @@ -59,15 +72,48 @@ export default function createObjectFromGCode(gcode, indxMax) { max: [-100000, -100000, -100000] }, - bufSize : 10000, // Arbitrary - play around with! + bufSize: 10000, // Arbitrary - play around with! colors: { 'G0': 0x00ff00, 'G1': 0x0000ff, 'G2': 0x999900 - } + }, /*colorG0: 0x00ff00, colorG1: 0x0000ff, colorG2: 0x999900,*/ + + lasermultiply: 100, + laserxmax: undefined, + laserymax: undefined, + + // command specific settings, not sure about this: + specifics: { + G0: { + color: 0x00ff00, + }, + G1: { + color: 0x0000ff, + }, + G2: { + color: 0x999900, + }, + G7: { + dir: 0, + spotSize: undefined + }, + G17: { + extraObjects: [] + }, + G18: { + extraObjects: [] + }, + G19: { + extraObjects: [] + }, + G92: { + offset: {x: 0, y: 0, z: 0, a: 0, e: 0} + } + } } let lastLine = { @@ -89,10 +135,9 @@ export default function createObjectFromGCode(gcode, indxMax) { // G2/G3 moves are their own child of lots of lines so // that even the simulator can follow along better let new3dObj = { - name : 'newobj' + name: 'newobj' } return { - state, lastLine, new3dObj - } + state, lastLine, new3dObj} } diff --git a/src/parseAsChunks.js b/src/parseAsChunks.js index b370280..c6cece1 100644 --- a/src/parseAsChunks.js +++ b/src/parseAsChunks.js @@ -4,8 +4,8 @@ function now () { return new Date().getTime() } -export default function parseAsChunks(gcode, state, params){ - const {lineObjects, laserxmax, laserymax} = params +export default function parseAsChunks (state, handlers, gcode) { + const {lineObjects, laserxmax, laserymax} = state const lines = gcode.split(/\r{0,1}\n/) const count = lines.length @@ -17,27 +17,26 @@ export default function parseAsChunks(gcode, state, params){ let startTime = now() while (index < count && (now() - startTime) <= maxTimePerChunk) { - //console.log('parsing ' + lines[index]) - parseLine(lines[index], index, state) + // console.log('parsing ' + lines[index]) + parseLine(state, handlers, lines[index], index) ++index } - //closeLineSegment() //FIXME : add this back .??? or not + // closeLineSegment() //FIXME : add this back .??? or not // console.log('done parsing ') if (index < count) { setTimeout(doChunk, 1) // set Timeout for async iteration // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") } else { - console.log('done parsing') + console.log('done parsing')//, state.lineObjects.lines) } } doChunk() } -//"old" for reference +// "old" for reference export function __parser (gcode, params, progressCallback, doneCallback) { - console.log('inside this.parse') object = null function doChunk () { @@ -50,7 +49,7 @@ export function __parser (gcode, params, progressCallback, doneCallback) { parseLine(lines[index], index) ++index } - //closeLineSegment() //FIXME : add this back !! + // closeLineSegment() //FIXME : add this back !! // console.log('done parsing ') if (index < count) { @@ -69,6 +68,6 @@ export function __parser (gcode, params, progressCallback, doneCallback) { } } - //start it + // start it doChunk() } diff --git a/src/parseLine.js b/src/parseLine.js index 01baff6..3048712 100644 --- a/src/parseLine.js +++ b/src/parseLine.js @@ -1,4 +1,4 @@ -export default function parseLine (text, index, state, handlers) { +export default function parseLine (state, handlers, text, index) { console.log('Parsing: ', text) const origtext = text @@ -11,9 +11,10 @@ export default function parseLine (text, index, state, handlers) { const isComment = baseParse.isComment text = baseParse.text - return generateArgs(state, text, origtext, index, isComment, isG7) + return generateArgs(state, handlers, text, origtext, index, isComment, isG7) } +/*parses 'default' text , ie non raster/G7*/ function parseDefault (text, origtext) { let isComment = false @@ -35,6 +36,7 @@ function parseDefault (text, origtext) { return {text, isComment} } +/* parses...raster text ! (surprising isn't it?)*/ function parseRaster (text, origtext) { let isComment = false text = text.trim() @@ -45,7 +47,7 @@ function parseRaster (text, origtext) { return {text, isComment} } -function generateArgs (state, text, origtext, index, isComment, isG7) { +function generateArgs (state, handlers, text, origtext, index, isComment, isG7) { let {lastArgs} = state let args = { // defaults to an empty/comment line args cmd: 'empty or comment', @@ -115,16 +117,15 @@ function generateArgs (state, text, origtext, index, isComment, isG7) { // REMOVE THIS ? // return handlers['default'](args, index) - let handlers = {} let handler = handlers[args.cmd] || handlers['default'] if (handler) { adaptUnitsAndFeedrateForHandler(args, state) - // return handler(args, index) + return handler(state, args, index) } else { console.error('No handler for gcode command!!!') } - return args + //return args } //FIXME: switch to non mutating ? diff --git a/src/utils.js b/src/utils.js index 2adc968..e02354d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,7 +1,7 @@ -export function delta (v1, v2) { +export function delta (relative, v1, v2) { return relative ? v2 : v2 - v1 } -export function absolute (v1, v2) { +export function absolute (relative, v1, v2) { return relative ? v1 + v2 : v2 } From 6233981c4c0a2d7905b60105a256845e8cbe580b Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 23:26:33 +0100 Subject: [PATCH 13/34] test(): fleshed out basic test a bit --- test/gcodeParser.spec.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/gcodeParser.spec.js b/test/gcodeParser.spec.js index c35da0c..0b8bf8d 100644 --- a/test/gcodeParser.spec.js +++ b/test/gcodeParser.spec.js @@ -5,7 +5,14 @@ import parse from '../src/index' test.cb('gcode parser tests: can parse gcode files', t => { const gcode = fs.readFileSync('./data/Rotary Axis GCode.gcode','utf8') - parse(gcode) + parse(gcode, function(data){ + console.log('done with parsing',data.metrics) + t.deepEqual(data.lineObjects.lines.length, 24) + //t.deepEqual(data.positions.length / 3, 864) // we divide by three because each entry is 3 long + //t.deepEqual(data.positions[0], -0.025066649541258812) + //t.deepEqual(data.positions[data.positions.length - 1], 0.019999999552965164) + t.end() + }) // this.timeout(5000) /*fs.createReadStream('./data/test.gcode', { encoding: null, highWaterMark: 512 * 1024 }) // 'binary' .pipe(makeStlStream()) From de6de70e52da7df95218c440322794b26d5bdc7d Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 23:27:20 +0100 Subject: [PATCH 14/34] refactor(makebasestate): renamed, cleaned up --- src/{objFromGcode.js => makeBaseState.js} | 60 ++++++----------------- 1 file changed, 15 insertions(+), 45 deletions(-) rename src/{objFromGcode.js => makeBaseState.js} (64%) diff --git a/src/objFromGcode.js b/src/makeBaseState.js similarity index 64% rename from src/objFromGcode.js rename to src/makeBaseState.js index 33d177b..ed0044d 100644 --- a/src/objFromGcode.js +++ b/src/makeBaseState.js @@ -1,18 +1,4 @@ -export default function createObjectFromGCode (gcode, indexMax) { - console.log('Generating GCODE Preview') - // console.group("Rendering GCODE Preview") - // debugger - // Credit goes to https://github.com/joewalnes/gcode-viewer - // for the initial inspiration and example code. - // - // GCode descriptions come from: - // http://reprap.org/wiki/G-code - // http://en.wikipedia.org/wiki/G-code - // SprintRun source code - - // these are extra Object3D elements added during - // the gcode rendering to attach to scene - +export default function makeBaseState (gcode, indexMax) { let state = { debug: true, @@ -26,7 +12,8 @@ export default function createObjectFromGCode (gcode, indexMax) { name: 'LineObjects' }, - extraObjects: { + extraObjects: {// these are extra Object3D elements added during + // the gcode rendering to attach to scene 'G17': [], 'G18': [], 'G19': [] @@ -62,25 +49,17 @@ export default function createObjectFromGCode (gcode, indexMax) { extruding: false }, - bbbox: { + bbox: { min: [100000, 100000, 100000], max: [-100000, -100000, -100000] }, - bbbox2: { + bbox2: { min: [100000, 100000, 100000], max: [-100000, -100000, -100000] }, bufSize: 10000, // Arbitrary - play around with! - colors: { - 'G0': 0x00ff00, - 'G1': 0x0000ff, - 'G2': 0x999900 - }, - /*colorG0: 0x00ff00, - colorG1: 0x0000ff, - colorG2: 0x999900,*/ lasermultiply: 100, laserxmax: undefined, @@ -89,13 +68,13 @@ export default function createObjectFromGCode (gcode, indexMax) { // command specific settings, not sure about this: specifics: { G0: { - color: 0x00ff00, + color: 0x00ff00 }, G1: { - color: 0x0000ff, + color: 0x0000ff }, G2: { - color: 0x999900, + color: 0x999900 }, G7: { dir: 0, @@ -113,18 +92,13 @@ export default function createObjectFromGCode (gcode, indexMax) { G92: { offset: {x: 0, y: 0, z: 0, a: 0, e: 0} } - } - } + }, - let lastLine = { - x: 0, - y: 0, - z: 0, - a: 0, - e: 0, - f: 0, - feedrate: null, - extruding: false + //container object/group + container: { + name: 'newobj', + children: [] + } } // we have been using an approach where we just append @@ -134,10 +108,6 @@ export default function createObjectFromGCode (gcode, indexMax) { // its own userData info // G2/G3 moves are their own child of lots of lines so // that even the simulator can follow along better - let new3dObj = { - name: 'newobj' - } - return { - state, lastLine, new3dObj} + return state } From 4b6e9b3044f83cf14c3bfe1ae599dc19dac65e0c Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 23:28:06 +0100 Subject: [PATCH 15/34] refactor(): modified data structure to be more generic , less three.js --- src/geometries/arcs.js | 11 ++-- src/geometries/segments.js | 127 +++++++++++++++++++------------------ 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/src/geometries/arcs.js b/src/geometries/arcs.js index 0998f10..32e3395 100644 --- a/src/geometries/arcs.js +++ b/src/geometries/arcs.js @@ -1,21 +1,23 @@ export function drawArc (state, aX, aY, aZ, endaZ, aRadius, aStartAngle, aEndAngle, aClockwise, plane) { // console.log("drawArc:", aX, aY, aZ, aRadius, aStartAngle, aEndAngle, aClockwise) - let ac = new THREE.ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) + let ac = new THREE.ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) // FIXME a harder one ... // console.log("ac:", ac) const material = { color: 0x00aaff, opacity: 0.5 } - let acgeo = [] + let geometry = { + positions: [] + } let ctr = 0 let z = aZ ac.getPoints(20).forEach(function (v) { // console.log(v) z = (((endaZ - aZ) / 20) * ctr) + aZ - acgeo.push(v.x, v.y, z) + geometry.positions.push(v.x, v.y, z) ctr++ }) - const aco = {geometry: acgeo, material} + const aco = {geometry, material} // aco.position.set(pArc.x, pArc.y, pArc.z) // console.log("aco:", aco) state.extraObjects[plane].push(aco) @@ -103,5 +105,4 @@ export function drawArcFrom2PtsAndCenter (vp1, vp2, vpArc, args) { default: obj = drawArc(vpArc.x, vpArc.y, vp1.z, vp2.z, radius, anglepArcp1, anglepArcp2, clwise, 'G17') } - return threeObj } diff --git a/src/geometries/segments.js b/src/geometries/segments.js index 7473c72..288a29b 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -6,9 +6,7 @@ export function addSegment (state, args, p1, p2) { console.log('addSegment') } closeLineSegment(state) - let bbbox = [] - let bbbox2 = [] - + let {bbox, bbox2} = state // console.log("") // console.log("addSegment p2:", p2) // add segment to array for later use @@ -149,7 +147,6 @@ export function addSegment (state, args, p1, p2) { } const arcObj = drawArcFrom2PtsAndCenter(vp1, vp2, vpArc, args) - // still push the normal p1/p2 point for debug p2.g2 = true p2.arcObj = arcObj @@ -158,27 +155,27 @@ export function addSegment (state, args, p1, p2) { // so hiding them for now. jlauer 8/15/15 /* geometry = group.geometry - geometry.vertices.push( + geometry.positions.push( [p1.x, p1.y, p1.z]) - geometry.vertices.push( + geometry.positions.push( [p2.x, p2.y, p2.z)) geometry.colors.push(group.color) geometry.colors.push(group.color) */ } else { - geometry.vertices.push([p1.x, p1.y, p1.z]) - geometry.vertices.push([p2.x, p2.y, p2.z]) + geometry.positions.push(p1.x, p1.y, p1.z) + geometry.positions.push(p2.x, p2.y, p2.z) geometry.colors.push(group.color) geometry.colors.push(group.color) } if (p2.extruding) { - bbbox.min.x = Math.min(bbbox.min.x, p2.x) - bbbox.min.y = Math.min(bbbox.min.y, p2.y) - bbbox.min.z = Math.min(bbbox.min.z, p2.z) - bbbox.max.x = Math.max(bbbox.max.x, p2.x) - bbbox.max.y = Math.max(bbbox.max.y, p2.y) - bbbox.max.z = Math.max(bbbox.max.z, p2.z) + bbox.min.x = Math.min(bbox.min.x, p2.x) + bbox.min.y = Math.min(bbox.min.y, p2.y) + bbox.min.z = Math.min(bbox.min.z, p2.z) + bbox.max.x = Math.max(bbox.max.x, p2.x) + bbox.max.y = Math.max(bbox.max.y, p2.y) + bbox.max.z = Math.max(bbox.max.z, p2.z) } if (p2.g0) { // we're in a toolhead move, label moves @@ -196,12 +193,12 @@ export function addSegment (state, args, p1, p2) { */ } // global bounding box calc - bbbox2.min.x = Math.min(bbbox2.min.x, p2.x) - bbbox2.min.y = Math.min(bbbox2.min.y, p2.y) - bbbox2.min.z = Math.min(bbbox2.min.z, p2.z) - bbbox2.max.x = Math.max(bbbox2.max.x, p2.x) - bbbox2.max.y = Math.max(bbbox2.max.y, p2.y) - bbbox2.max.z = Math.max(bbbox2.max.z, p2.z) + bbox2.min.x = Math.min(bbox2.min.x, p2.x) + bbox2.min.y = Math.min(bbox2.min.y, p2.y) + bbox2.min.z = Math.min(bbox2.min.z, p2.z) + bbox2.max.x = Math.max(bbox2.max.x, p2.x) + bbox2.max.y = Math.max(bbox2.max.y, p2.y) + bbox2.max.z = Math.max(bbox2.max.z, p2.z) /* NEW METHOD OF CREATING OBJECTS create new approach for objects which is @@ -238,9 +235,9 @@ export function addSegment (state, args, p1, p2) { } gcodeObj = {geometry, material} } - gcodeObj.userData.p2 = p2 - gcodeObj.userData.args = args - new3dObj.add(gcodeObj) + gcodeObj.p2 = p2 + gcodeObj.args = args + state.container.children.push(gcodeObj) // DISTANCE CALC // add distance so we can calc estimated time to run @@ -255,8 +252,8 @@ export function addSegment (state, args, p1, p2) { // console.log("arcGeo:", arcGeo) let tad2 = 0 - for (let arcLineCtr = 0; arcLineCtr < arcGeo.vertices.length - 1; arcLineCtr++) { - tad2 += arcGeo.vertices[arcLineCtr].distanceTo(arcGeo.vertices[arcLineCtr + 1]) + for (let arcLineCtr = 0; arcLineCtr < arcGeo.positions.length - 1; arcLineCtr++) { + tad2 += arcGeo.positions[arcLineCtr].distanceTo(arcGeo.positions[arcLineCtr + 1]) } // console.log("tad2:", tad2) @@ -311,7 +308,7 @@ export function addSegment (state, args, p1, p2) { p2.timeMinsSum = totalTime // console.log('Total Time'+totalTime) - totaltimemax += (timeMinutes * 60) + state.metrics.totaltimemax += (timeMinutes * 60) // console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) return { dist, @@ -337,41 +334,44 @@ export function addFakeSegment (state, args) { // lineObject, lastLine, lines) { } export function addLineSegment (state, args, p1, p2) { + if(state.debug){ + console.log('addLineSegment') + } let {lineObject, lasermultiply, bufSize} = state let i = lineObject.nLines * 6 - // lineObject.vertexBuf[i+0] = p1.x // Vertices - // lineObject.vertexBuf[i+1] = p1.y - // lineObject.vertexBuf[i+2] = p1.z - // lineObject.vertexBuf[i+3] = p2.x - // lineObject.vertexBuf[i+4] = p2.y - // lineObject.vertexBuf[i+5] = p2.z + // lineObject.positions[i+0] = p1.x // positions + // lineObject.positions[i+1] = p1.y + // lineObject.positions[i+2] = p1.z + // lineObject.positions[i+3] = p2.x + // lineObject.positions[i+4] = p2.y + // lineObject.positions[i+5] = p2.z if (p1.a !== 0 || p2.a !== 0) { // A axis: rotate around X const R1 = Math.sqrt(p1.y * p1.y + p1.z * p1.z) const R2 = Math.sqrt(p2.y * p2.y + p2.z * p2.z) const a1 = p1.y === 0 ? Math.sign(p1.z) * 90 : Math.atan2(p1.z, p1.y) * 180.0 / Math.PI const a2 = p2.y === 0 ? Math.sign(p2.z) * 90 : Math.atan2(p2.z, p2.y) * 180.0 / Math.PI - lineObject.vertexBuf[i + 0] = p1.x - lineObject.vertexBuf[i + 1] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) - lineObject.vertexBuf[i + 2] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) - lineObject.vertexBuf[i + 3] = p2.x - lineObject.vertexBuf[i + 4] = R2 * Math.cos((-p2.a + a2) * Math.PI / 180.0) - lineObject.vertexBuf[i + 5] = R2 * Math.sin((-p2.a + a2) * Math.PI / 180.0) + lineObject.positions[i + 0] = p1.x + lineObject.positions[i + 1] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) + lineObject.positions[i + 2] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) + lineObject.positions[i + 3] = p2.x + lineObject.positions[i + 4] = R2 * Math.cos((-p2.a + a2) * Math.PI / 180.0) + lineObject.positions[i + 5] = R2 * Math.sin((-p2.a + a2) * Math.PI / 180.0) } else { // Vertice code for A Axis as submitted by HakanBasted - commented out by PvdW else normal gcode only renders in a single Y line. - // lineObject.vertexBuf[i+0] = p1.x // Vertices - // lineObject.vertexBuf[i+1] = 0.1*p1.a - // lineObject.vertexBuf[i+2] = p1.z - // lineObject.vertexBuf[i+3] = p2.x - // lineObject.vertexBuf[i+4] = 0.1*p2.a - // lineObject.vertexBuf[i+5] = p2.z - - lineObject.vertexBuf[i + 0] = p1.x // Vertices - lineObject.vertexBuf[i + 1] = p1.y - lineObject.vertexBuf[i + 2] = p1.z - lineObject.vertexBuf[i + 3] = p2.x - lineObject.vertexBuf[i + 4] = p2.y - lineObject.vertexBuf[i + 5] = p2.z + // lineObject.positions[i+0] = p1.x // positions + // lineObject.positions[i+1] = 0.1*p1.a + // lineObject.positions[i+2] = p1.z + // lineObject.positions[i+3] = p2.x + // lineObject.positions[i+4] = 0.1*p2.a + // lineObject.positions[i+5] = p2.z + + lineObject.positions[i + 0] = p1.x // positions + lineObject.positions[i + 1] = p1.y + lineObject.positions[i + 2] = p1.z + lineObject.positions[i + 3] = p2.x + lineObject.positions[i + 4] = p2.y + lineObject.positions[i + 5] = p2.z } // console.log("Segment " + p1) @@ -391,12 +391,12 @@ export function addLineSegment (state, args, p1, p2) { intensity = 1.0 - p2.s / lasermultiply } - lineObject.colorBuf[i + 0] = color.r + (1 - color.r) * intensity // Colors - lineObject.colorBuf[i + 1] = color.g + (1 - color.g) * intensity - lineObject.colorBuf[i + 2] = color.b + (1 - color.b) * intensity - lineObject.colorBuf[i + 3] = color.r + (1 - color.r) * intensity - lineObject.colorBuf[i + 4] = color.g + (1 - color.g) * intensity - lineObject.colorBuf[i + 5] = color.b + (1 - color.b) * intensity + lineObject.colors[i + 0] = color.r + (1 - color.r) * intensity // Colors + lineObject.colors[i + 1] = color.g + (1 - color.g) * intensity + lineObject.colors[i + 2] = color.b + (1 - color.b) * intensity + lineObject.colors[i + 3] = color.r + (1 - color.r) * intensity + lineObject.colors[i + 4] = color.g + (1 - color.g) * intensity + lineObject.colors[i + 5] = color.b + (1 - color.b) * intensity lineObject.nLines++ @@ -412,17 +412,20 @@ export function addLineSegment (state, args, p1, p2) { return {dist} } -export function closeLineSegment ({lineObject, lineObjects}) { +export function closeLineSegment ({debug, lineObject, lineObjects}) { + if(debug){ + console.log('closeLineSegment', lineObject.nLines) + } if (lineObject.nLines === 0) { return } - const vertices = new Float32Array(6 * lineObject.nLines) + const positions = new Float32Array(6 * lineObject.nLines) const colors = new Float32Array(6 * lineObject.nLines) - vertices.set(lineObject.vertexBuf.subarray(0, lineObject.nLines * 6)) - colors.set(lineObject.colorBuf.subarray(0, lineObject.nLines * 6)) + positions.set(lineObject.positions.subarray(0, lineObject.nLines * 6)) + colors.set(lineObject.colors.subarray(0, lineObject.nLines * 6)) - const lines = {vertices, colors} + const lines = {positions, colors} lineObjects.lines.push(lines) // Feed the objects to "object" in doChunk() lineObject.nLines = 0 } From 5aeec89c6a3c5090e087ef5daefe0529498bf500 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 23:29:11 +0100 Subject: [PATCH 16/34] refactor(drawObject): attempt at making sense of draw object: - cleanup - restructure --- src/drawObject.js | 56 ++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/drawObject.js b/src/drawObject.js index 330291d..905aa00 100644 --- a/src/drawObject.js +++ b/src/drawObject.js @@ -5,7 +5,7 @@ export default function drawobject (state) { isUnitsMm = state.isUnitsMm newObject = { - name:'newObject' + name: 'newObject' } // old approach of monolithic line segment @@ -49,49 +49,51 @@ export default function drawobject (state) { // Center var scale = 1; // TODO: Auto size - var center = new THREE.Vector3( - bbbox.min.x + ((bbbox.max.x - bbbox.min.x) / 2), - bbbox.min.y + ((bbbox.max.y - bbbox.min.y) / 2), - bbbox.min.z + ((bbbox.max.z - bbbox.min.z) / 2)) + const center = [ + bbox.min.x + ((bbox.max.x - bbox.min.x) / 2), + bbox.min.y + ((bbox.max.y - bbox.min.y) / 2), + bbox.min.z + ((bbox.max.z - bbox.min.z) / 2)] - var center2 = new THREE.Vector3( - bbbox2.min.x + ((bbbox2.max.x - bbbox2.min.x) / 2), - bbbox2.min.y + ((bbbox2.max.y - bbbox2.min.y) / 2), - bbbox2.min.z + ((bbbox2.max.z - bbbox2.min.z) / 2)) + const center2 = [ + bbox2.min.x + ((bbox2.max.x - bbox2.min.x) / 2), + bbox2.min.y + ((bbox2.max.y - bbox2.min.y) / 2), + bbox2.min.z + ((bbox2.max.z - bbox2.min.z) / 2)] - var dX = bbbox2.max.x - bbbox2.min.x - var dY = bbbox2.max.y - bbbox2.min.y - var dZ = bbbox2.max.z - bbbox2.min.z + const dX = bbox2.max.x - bbox2.min.x + const dY = bbox2.max.y - bbox2.min.y + const dZ = bbox2.max.z - bbox2.min.z function toTimeString (seconds) { // return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0] } - console.log(totaltimemax + ' seconds estimated') - + //console.log(totaltimemax + ' seconds estimated') // printLog('Estimated Job Time: '+totaltimemax, successcolor) + // printLog('Estimated Distance: ' + (totalDist / 1000).toFixed(1) + ' m', msgcolor, 'viewer') - printLog('Estimated Distance: ' + (totalDist / 1000).toFixed(1) + ' m', msgcolor, 'viewer') - $('#lasertimeqty').val((totalDist.toFixed(1)) / 10) + const estimatedJobTime = totaltimemax + const estimatedDistance = (totalDist / 1000).toFixed(1) + const lasertimeqty = (totalDist.toFixed(1)) / 10 if (fileParentGroup) { var bbox2 = new THREE.Box3().setFromObject(fileParentGroup) // console.log('bbox width: ', (bbox2.max.x - bbox2.min.x), 'height Y: ', (bbox2.max.y - bbox2.min.y) ) - width = (bbox2.max.x - bbox2.min.x) - height = (bbox2.max.y - bbox2.min.y) - $('#quoteresult').html('Job moves length: ' + totalDist.toFixed(1) + ' mm
Width: ' + width.toFixed(1) + ' mm
Height: ' + height.toFixed(1) + ' mm
Material: ' + ((width * height) / 1000).toFixed(3) + 'cm2') - $('#materialqty').val(((width * height) / 1000).toFixed(3)) + // 2' } else if (rastermesh) { - var bbox2 = new THREE.Box3().setFromObject(rastermesh) + const bbox2 = new THREE.Box3().setFromObject(rastermesh) // console.log('bbox width: ', (bbox2.max.x - bbox2.min.x), 'height Y: ', (bbox2.max.y - bbox2.min.y) ) - width = (bbox2.max.x - bbox2.min.x) - height = (bbox2.max.y - bbox2.min.y) - $('#quoteresult').html('Job moves length: ' + totalDist.toFixed(1) + ' mm
Width: ' + width.toFixed(1) + ' mm
Height: ' + height.toFixed(1) + ' mm
Material: ' + ((width * height) / 1000).toFixed(3) + 'cm2') - $('#materialqty').val(((width * height) / 1000).toFixed(3)) + } + const width = (bbox2.max.x - bbox2.min.x) + const height = (bbox2.max.y - bbox2.min.y) + const materialqty = ((width * height) / 1000).toFixed(3) + const quoteresult = [ + `Job moves length: ${totalDist.toFixed(1)} mm`, + `Width: ${width.toFixed(1)} mm`, + `Height: ${height.toFixed(1)} mm`, + `Material: ${((width * height) / 1000).toFixed(3)} cm` + ] console.groupEnd() return newObject - // console.groupEnd() - } From 0e89145f389835d0b2591ab71ae2c55a2203a200 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 23:30:04 +0100 Subject: [PATCH 17/34] feat(index): added doneCallback, various cleanups & doc additions --- src/index.js | 60 ++++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/src/index.js b/src/index.js index 882d5fb..acd183e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,46 +1,50 @@ /** * @author kaosat-dev / https://github.com/kaosat-dev * @author kaosat-dev / https://github.com/kaosat-dev - * - * Description: A gcode parser, + * for the initial inspiration and example code. + * Credit goes to https://github.com/joewalnes/gcode-viewer + * GCode descriptions come from: + * http://reprap.org/wiki/G-code + * http://en.wikipedia.org/wiki/G-code + * SprintRun source code + * Description: A gcode parser **/ - import makeHandlers from './gcodeHandlers' import parseAsChunks from './parseAsChunks' -import makeBaseData from './objFromGcode' +import makeBaseState from './makeBaseState' -export default function parse(data, parameters={}){ - //const params = Object.assign({}, machineDefaults, parameters) +export default function parse (data, doneCallback) { + // const params = Object.assign({}, machineDefaults, parameters) + console.log('Generating GCODE Preview') const handlers = makeHandlers() - let state = makeBaseData().state + let state = makeBaseState() - //FIXME: not sure AT ALL where/when lineObject is supposed to be created + // FIXME: not sure AT ALL where/when lineObject is supposed to be created state.lineObject = { active: false, - vertexBuf: new Float32Array(6 * state.bufSize), // Start with bufSize line segments - colorBuf: new Float32Array(6 * state.bufSize), // Start with bufSize line segments + positions: new Float32Array(6 * state.bufSize), // Start with bufSize line segments + colors: new Float32Array(6 * state.bufSize), // Start with bufSize line segments nLines: 0 }, - parseAsChunks(state, handlers, data) + parseAsChunks(state, handlers, data, doneCallback) } - - /*export default function makeGcodeStream (parameters = {}) { - - OLD code structure , for reference ! - //main entry point !! - createObjectFromGCode(gcode, indexMax) - => handlers = { - gcode(G1 etc): function - => drawArc - => drawArcFrom2PtsAndCenter - => addSegment - } - =>GCodeParser(handlers) - =>parse - =>doChunk - =>parseLine - convertLineGeometryToBufferGeometry +/*export default function makeGcodeStream (parameters = {}) { + +OLD code structure , for reference ! +//main entry point !! +createObjectFromGCode(gcode, indexMax) + => handlers = { + gcode(G1 etc): function + => drawArc + => drawArcFrom2PtsAndCenter + => addSegment + } + =>GCodeParser(handlers) + =>parse + =>doChunk + =>parseLine + convertLineGeometryToBufferGeometry }*/ From ca65924bde4ec214520c6ce2fad604b74cd96d20 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 23:32:15 +0100 Subject: [PATCH 18/34] refactor(): minor tweaks --- src/gcodeHandlers.js | 8 +++++--- src/lineGroup.js | 13 +++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js index ae27c95..187b99f 100644 --- a/src/gcodeHandlers.js +++ b/src/gcodeHandlers.js @@ -16,8 +16,8 @@ export default function makeHandlers (params) { let lines = undefined var lineObject = {active: false, - vertexBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments - colorBuf: new Float32Array(6 * bufSize), // Start with bufSize line segments + positions: new Float32Array(6 * bufSize), // Start with bufSize line segments + colors: new Float32Array(6 * bufSize), // Start with bufSize line segments nLines: 0, } */ @@ -67,7 +67,9 @@ export default function makeHandlers (params) { watching when we extrude at a new Z position */ if (delta(lastLine.e, newLine.e) > 0) { newLine.extruding = delta(lastLine.e, newLine.e) > 0 - if (layer === undefined || newLine.z !== layer.z) cofg.newLayer(newLine) + if (layer === undefined || newLine.z !== layer.z) { + newLayer(newLine, state.layers.layers3d) + } } addLineSegment(state, args, lastLine, newLine) state.lastLine = newLine diff --git a/src/lineGroup.js b/src/lineGroup.js index 82b9131..ae28be8 100644 --- a/src/lineGroup.js +++ b/src/lineGroup.js @@ -1,6 +1,6 @@ export function getLineGroup (state, line, args) { console.log('getLineGroup:', line) - if (state.layer === undefined) newLayer(line) + if (state.layer === undefined) newLayer(line, state.layers.layers3d) const speed = Math.round(line.e / 1000) let opacity = line.s let tool = parseInt(line.t, 10) @@ -56,15 +56,12 @@ export function getLineGroup (state, line, args) { extruding: line.extruding, color: color, segmentCount: 0, - //FIXME: how to deal with the things below ? - /*material: new THREE.LineBasicMaterial({ + material: { opacity: opacity, - // opacity: line.extruding ? 0.5: line.g2 ? 0.2 : 0.3, transparent: true, - linewidth: 1, - vertexColors: THREE.FaceColors - }), - geometry: new THREE.Geometry(),*/ + linewidth: 1 + }, + geometry: {positions: []} } } return state.layer.type[grouptype] From 33e0f45684d969b7e711c32f64ae8cb62b214102 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Sun, 13 Nov 2016 23:32:40 +0100 Subject: [PATCH 19/34] feat(doneCallback): added (back?) call to doneCallback --- src/parseAsChunks.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/parseAsChunks.js b/src/parseAsChunks.js index c6cece1..03ca441 100644 --- a/src/parseAsChunks.js +++ b/src/parseAsChunks.js @@ -4,7 +4,7 @@ function now () { return new Date().getTime() } -export default function parseAsChunks (state, handlers, gcode) { +export default function parseAsChunks (state, handlers, gcode, doneCallback) { const {lineObjects, laserxmax, laserymax} = state const lines = gcode.split(/\r{0,1}\n/) @@ -28,7 +28,8 @@ export default function parseAsChunks (state, handlers, gcode) { setTimeout(doChunk, 1) // set Timeout for async iteration // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") } else { - console.log('done parsing')//, state.lineObjects.lines) + //console.log('done parsing')//, state.lineObjects.lines) + doneCallback(state) } } From 9a9d101f703cb048a6ba1a3ce933186efa329ce3 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Wed, 16 Nov 2016 13:18:13 +0100 Subject: [PATCH 20/34] refactor(): migrating towards new data structures - also removed obsolete code - switched g0: true , g1:true etc to g:1, g:2 etc - various cleanups --- src/drawObject.js | 2 +- src/gcodeHandlers.js | 46 +++++++---------------- src/geometries/geometryUtils.js | 30 --------------- src/geometries/segments.js | 65 +++++++++++++++++---------------- src/makeBaseState.js | 3 +- src/parseLine.js | 5 +-- 6 files changed, 51 insertions(+), 100 deletions(-) delete mode 100644 src/geometries/geometryUtils.js diff --git a/src/drawObject.js b/src/drawObject.js index 905aa00..f6e1087 100644 --- a/src/drawObject.js +++ b/src/drawObject.js @@ -2,7 +2,7 @@ export default function drawobject (state) { var newObject = false // console.log("INSIDE DRAWOBJECT") // set what units we're using in the gcode - isUnitsMm = state.isUnitsMm + unitsMm = state.unitsMm newObject = { name: 'newObject' diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js index 187b99f..e5e1dd4 100644 --- a/src/gcodeHandlers.js +++ b/src/gcodeHandlers.js @@ -3,25 +3,6 @@ import { addSegment, addLineSegment, addFakeSegment } from './geometries/segment import { newLayer } from './layers' export default function makeHandlers (params) { - /*let state = { - isUnitsMm: true, - plane: undefined, - relative: true, - offsetG92: {x: 0, y: 0, z: 0, a: 0, e: 0}, - spotSizeG7: undefined, - dirG7: 0 - } - const lineObject = {} - let lastLine = undefined - let lines = undefined - - var lineObject = {active: false, - positions: new Float32Array(6 * bufSize), // Start with bufSize line segments - colors: new Float32Array(6 * bufSize), // Start with bufSize line segments - nLines: 0, - } - */ - const handlers = { // set the g92 offsets for the parser - defaults to no offset // When doing CNC, generally G0 just moves to a new location @@ -30,6 +11,7 @@ export default function makeHandlers (params) { G0: function (state, args, index) { const {lastLine} = state const newLine = { + g: 0, x: args.x !== undefined ? absolute(state.relative, lastLine.x, args.x) + state.specifics.G92.offset.x : lastLine.x, y: args.y !== undefined ? absolute(state.relative, lastLine.y, args.y) + state.specifics.G92.offset.y : lastLine.y, z: args.z !== undefined ? absolute(state.relative, lastLine.z, args.z) + state.specifics.G92.offset.z : lastLine.z, @@ -37,7 +19,7 @@ export default function makeHandlers (params) { e: args.e !== undefined ? absolute(state.relative, lastLine.e, args.e) + state.specifics.G92.offset.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: 100, - g0: true + t: undefined } addLineSegment(state, args, lastLine, newLine) state.lastLine = newLine @@ -53,6 +35,7 @@ export default function makeHandlers (params) { // 22.4 mm. const newLine = { + g: 1, x: args.x !== undefined ? absolute(state.relative, lastLine.x, args.x) + state.specifics.G92.offset.x : lastLine.x, y: args.y !== undefined ? absolute(state.relative, lastLine.y, args.y) + state.specifics.G92.offset.y : lastLine.y, z: args.z !== undefined ? absolute(state.relative, lastLine.z, args.z) + state.specifics.G92.offset.z : lastLine.z, @@ -60,13 +43,12 @@ export default function makeHandlers (params) { e: args.e !== undefined ? absolute(state.relative, lastLine.e, args.e) + state.specifics.G92.offset.e : lastLine.e, f: args.f !== undefined ? args.f : lastLine.f, s: args.s !== undefined ? args.s : lastLine.s, - t: args.t !== undefined ? args.t : lastLine.t, - g1: true + t: args.t !== undefined ? args.t : lastLine.t } /* layer change detection is or made by watching Z, it's made by watching when we extrude at a new Z position */ - if (delta(lastLine.e, newLine.e) > 0) { - newLine.extruding = delta(lastLine.e, newLine.e) > 0 + if (delta(state.relative, lastLine.e, newLine.e) > 0) { + newLine.extruding = delta(state.relative, lastLine.e, newLine.e) > 0 if (layer === undefined || newLine.z !== layer.z) { newLayer(newLine, state.layers.layers3d) } @@ -135,7 +117,7 @@ export default function makeHandlers (params) { }, G7: function (state, args, index) { - const {lasermultiply, lastLine, lineObject, layer} = state + const {lastLine} = state // Example: G7 L68 D//////sljasflsfagdxsd,.df9078rhfnxm (68 of em) // G7 $1 L4 DAAA= // G7 $0 L4 D2312 @@ -157,6 +139,7 @@ export default function makeHandlers (params) { state.specifics.G7.dir = args.dollar const newLine = { + g: 0, x: lastLine.x, y: lastLine.y + state.specifics.G7.spotSize, z: lastLine.z, @@ -164,8 +147,7 @@ export default function makeHandlers (params) { e: lastLine.e, f: lastLine.f, s: 100, - t: lastLine.t, - g0: true + t: lastLine.t } addLineSegment(state, args, lastLine, newLine) state.lastLine = newLine @@ -173,6 +155,7 @@ export default function makeHandlers (params) { for (var i = 0; i < buf.length; i++) { // Process a base64-encoded chunk const intensity = 255 - buf.charCodeAt(i) // 255 - 0 const newLine = { + g: 7, x: lastLine.x + state.specifics.G7.spotSize * (state.specifics.G7.dir === 1 ? 1 : -1), y: lastLine.y, z: lastLine.z, @@ -180,8 +163,7 @@ export default function makeHandlers (params) { e: lastLine.e, f: lastLine.f, s: intensity, - t: lastLine.t, - g7: true + t: lastLine.t } addLineSegment(state, args, lastLine, newLine) state.lastLine = newLine @@ -213,7 +195,7 @@ export default function makeHandlers (params) { // like toolhead, axes, grid, and extent labels are scaled correctly // later on when they are drawn after the gcode is rendered // console.log("SETTING UNITS TO INCHES!!!") - state.isUnitsMm = false // false means inches cuz default is mm + state.unitsMm = false // false means inches cuz default is mm addFakeSegment(state, args) }, @@ -222,7 +204,7 @@ export default function makeHandlers (params) { // Example: G21 // Units from now on are in millimeters. (This is the RepRap default.) // console.log("SETTING UNITS TO MM!!!") - state.isUnitsMm = true // true means mm + state.unitsMm = true addFakeSegment(state, args) }, @@ -323,8 +305,6 @@ export default function makeHandlers (params) { }, 'default': function (state, args, index) { - // if (!args.isComment) - // console.log('Unknown command:', args.cmd, args, info) addFakeSegment(state, args) } } diff --git a/src/geometries/geometryUtils.js b/src/geometries/geometryUtils.js deleted file mode 100644 index 1dd01c3..0000000 --- a/src/geometries/geometryUtils.js +++ /dev/null @@ -1,30 +0,0 @@ - -function convertLineGeometryToBufferGeometry (lineGeometry, color) { - var positions = new Float32Array(lineGeometry.vertices.length * 3) - var colors = new Float32Array(lineGeometry.vertices.length * 3) - - var geometry = new THREE.BufferGeometry() - - for (var i = 0; i < lineGeometry.vertices.length; i++) { - var x = lineGeometry.vertices[i].x - var y = lineGeometry.vertices[i].y - var z = lineGeometry.vertices[i].z - - // positions - positions[ i * 3 ] = x - positions[ i * 3 + 1 ] = y - positions[ i * 3 + 2 ] = z - - // colors - colors[ i * 3 ] = color.r - colors[ i * 3 + 1 ] = color.g - colors[ i * 3 + 2 ] = color.b - } - - geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3)) - geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3)) - - geometry.computeBoundingSphere() - - return geometry -} diff --git a/src/geometries/segments.js b/src/geometries/segments.js index 288a29b..20b07e9 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -16,9 +16,7 @@ export function addSegment (state, args, p1, p2) { group.segmentCount++ // see if we need to draw an arc if (p2.arc) { - // console.log("") // console.log("drawing arc. p1:", p1, ", p2:", p2) - // let segmentCount = 12 // figure out the 3 pts we are dealing with // the start, the end, and the center of the arc circle @@ -177,7 +175,7 @@ export function addSegment (state, args, p1, p2) { bbox.max.y = Math.max(bbox.max.y, p2.y) bbox.max.z = Math.max(bbox.max.z, p2.z) } - if (p2.g0) { + if (p2.g === 0) { // we're in a toolhead move, label moves /* if (group.segmentCount < 2) { @@ -221,9 +219,9 @@ export function addSegment (state, args, p1, p2) { if (p2.extruding) { color = 0xff00ff - } else if (p2.g0) { + } else if (p2.g === 0) { color = 0x00ff00 - } else if (p2.g2) { + } else if (p2.g === 2) { // color = 0x999900 } else if (p2.arc) { color = 0x0033ff @@ -299,20 +297,17 @@ export function addSegment (state, args, p1, p2) { timeMinutes = timeMinutes * 1.32 } - totalTime += timeMinutes + state.metrics.totalTime += timeMinutes p2.feedrate = args.feedrate p2.dist = dist - p2.distSum = totalDist + p2.distSum = state.metrics.totalDist p2.timeMins = timeMinutes - p2.timeMinsSum = totalTime + p2.timeMinsSum = state.metrics.totalTime // console.log('Total Time'+totalTime) state.metrics.totaltimemax += (timeMinutes * 60) // console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) - return { - dist, - timeMinutes} } export function addFakeSegment (state, args) { // lineObject, lastLine, lines) { @@ -339,12 +334,6 @@ export function addLineSegment (state, args, p1, p2) { } let {lineObject, lasermultiply, bufSize} = state let i = lineObject.nLines * 6 - // lineObject.positions[i+0] = p1.x // positions - // lineObject.positions[i+1] = p1.y - // lineObject.positions[i+2] = p1.z - // lineObject.positions[i+3] = p2.x - // lineObject.positions[i+4] = p2.y - // lineObject.positions[i+5] = p2.z if (p1.a !== 0 || p2.a !== 0) { // A axis: rotate around X const R1 = Math.sqrt(p1.y * p1.y + p1.z * p1.z) @@ -357,14 +346,28 @@ export function addLineSegment (state, args, p1, p2) { lineObject.positions[i + 3] = p2.x lineObject.positions[i + 4] = R2 * Math.cos((-p2.a + a2) * Math.PI / 180.0) lineObject.positions[i + 5] = R2 * Math.sin((-p2.a + a2) * Math.PI / 180.0) + + //FIXME: new structure should be G,X,Y,Z,E,F,S,T + /*lineObject.positions[i + 0] = p1.g + lineObject.positions[i + 1] = p1.x + lineObject.positions[i + 2] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) + lineObject.positions[i + 3] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) + lineObject.positions[i + 4] = p1.a + lineObject.positions[i + 5] = p1.e + lineObject.positions[i + 6] = p1.f + lineObject.positions[i + 7] = p1.s + lineObject.positions[i + 8] = p1.t*/ } else { - // Vertice code for A Axis as submitted by HakanBasted - commented out by PvdW else normal gcode only renders in a single Y line. - // lineObject.positions[i+0] = p1.x // positions - // lineObject.positions[i+1] = 0.1*p1.a - // lineObject.positions[i+2] = p1.z - // lineObject.positions[i+3] = p2.x - // lineObject.positions[i+4] = 0.1*p2.a - // lineObject.positions[i+5] = p2.z + /*lineObject.positions[i + 0] = p1.g + lineObject.positions[i + 1] = p1.x // positions + lineObject.positions[i + 2] = p1.y + lineObject.positions[i + 3] = p1.z + lineObject.positions[i + 4] = p1.a + lineObject.positions[i + 5] = p1.e + lineObject.positions[i + 6] = p1.f + lineObject.positions[i + 7] = p1.s + lineObject.positions[i + 8] = p1.t*/ + lineObject.positions[i + 0] = p1.x // positions lineObject.positions[i + 1] = p1.y @@ -377,13 +380,13 @@ export function addLineSegment (state, args, p1, p2) { let color let intensity - if (p2.g0) { // g0 + if (p2.g === 0) { // g0 color = {r: 0, g: 1, b: 0} intensity = 1.0 - p2.s / lasermultiply - } else if (p2.g1) { // g1 + } else if (p2.g === 1) { // g1 color = {r: 0.7, g: 0, b: 0} intensity = 1.0 - p2.s / lasermultiply - } else if (p2.g7) { // g7 + } else if (p2.g === 7) { // g7 color = {r: 0, g: 0, b: 1} intensity = 1.0 - p2.s / lasermultiply } else { @@ -405,11 +408,9 @@ export function addLineSegment (state, args, p1, p2) { } const dist = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)) - // totalDist += dist - // timeMinutes = dist / p2.f - // totalTime += timeMinutes - // totaltimemax = totalTime * 60 - return {dist} + state.metrics.totalDist += dist + state.metrics.totalTime += dist / p2.f // time minutes + state.metrics.totaltimemax = state.metrics.totalTime * 60 } export function closeLineSegment ({debug, lineObject, lineObjects}) { diff --git a/src/makeBaseState.js b/src/makeBaseState.js index ed0044d..0d5c18e 100644 --- a/src/makeBaseState.js +++ b/src/makeBaseState.js @@ -4,13 +4,14 @@ export default function makeBaseState (gcode, indexMax) { tool: null, relative: false, - isUnitsMm: true, + unitsMm: true, lineObjects: { lines: [], nLines: 0, name: 'LineObjects' }, + linesData: [], extraObjects: {// these are extra Object3D elements added during // the gcode rendering to attach to scene diff --git a/src/parseLine.js b/src/parseLine.js index 3048712..bd5d1c1 100644 --- a/src/parseLine.js +++ b/src/parseLine.js @@ -5,7 +5,6 @@ export default function parseLine (state, handlers, text, index) { if (text.match(/^N/i)) { // remove line numbers if exist text = text.replace(/^N\d+\s*/ig, '') // yes, there's a line num } - const isG7 = text.match(/^G7/) // Is is G7 raster command? const baseParse = isG7 ? parseRaster(text, origtext) : parseDefault(text, origtext) const isComment = baseParse.isComment @@ -137,10 +136,10 @@ function adaptUnitsAndFeedrateForHandler (args, state) { // of the line. if (args.text.match(/\bG20\b/i)) { console.log('SETTING UNITS TO INCHES from pre-parser!!!') - state.isUnitsMm = false // false means inches cuz default is mm + state.unitsMm = false // false means inches cuz default is mm } else if (args.text.match(/\bG21\b/i)) { console.log('SETTING UNITS TO MM!!! from pre-parser') - state.isUnitsMm = true // true means mm + state.unitsMm = true // true means mm } if (args.text.match(/F([\d.]+)/i)) { // scan for feedrate From 189c6311150fb09528386ffbdc146bdf82748b19 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Fri, 18 Nov 2016 21:05:45 +0100 Subject: [PATCH 21/34] refactor(): further changes for up to date output etc - removed more clutter - modified some of the outputs to match the needed 'fields' --- src/geometries/segments.js | 130 ++++++++++--------------------------- src/makeBaseState.js | 4 ++ src/parseAsChunks.js | 2 - src/timeAndDistance.js | 74 +++++++++++++++++++++ test/tmptest.js | 7 -- 5 files changed, 111 insertions(+), 106 deletions(-) delete mode 100644 test/tmptest.js diff --git a/src/geometries/segments.js b/src/geometries/segments.js index 20b07e9..5bd2778 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -10,10 +10,12 @@ export function addSegment (state, args, p1, p2) { // console.log("") // console.log("addSegment p2:", p2) // add segment to array for later use + /*MM_removed let group = getLineGroup(p2, args) let geometry = group.geometry - group.segmentCount++ + */ + // see if we need to draw an arc if (p2.arc) { // console.log("drawing arc. p1:", p1, ", p2:", p2) @@ -57,9 +59,10 @@ export function addSegment (state, args, p1, p2) { // The other will be: // x = x3 - sqrt(r^2-(q/2)^2)*(y1-y2)/q // y = y3 - sqrt(r^2-(q/2)^2)*(x2-x1)/q + + let calc = Math.sqrt((radius * radius) - Math.pow(q / 2, 2)) let pArc_1 let pArc_2 - let calc = Math.sqrt((radius * radius) - Math.pow(q / 2, 2)) let angle_point let cw let ccw @@ -148,7 +151,9 @@ export function addSegment (state, args, p1, p2) { // still push the normal p1/p2 point for debug p2.g2 = true p2.arcObj = arcObj - group = getLineGroup(p2, args) + //MM_removed + //group = getLineGroup(p2, args) + // these golden lines showing start/end of a g2 or g3 arc were confusing people // so hiding them for now. jlauer 8/15/15 /* @@ -163,8 +168,10 @@ export function addSegment (state, args, p1, p2) { } else { geometry.positions.push(p1.x, p1.y, p1.z) geometry.positions.push(p2.x, p2.y, p2.z) + + /*MM_removed geometry.colors.push(group.color) - geometry.colors.push(group.color) + geometry.colors.push(group.color)*/ } if (p2.extruding) { @@ -203,6 +210,7 @@ export function addSegment (state, args, p1, p2) { a unique object for each line of gcode, including g2/g3's make sure userData is good too */ + /*MM_removed let gcodeObj if (p2.arc) { @@ -211,12 +219,6 @@ export function addSegment (state, args, p1, p2) { } else { // make a line let color = 0X0000ff - /*const {extruding, g0, g2, arc} = p2 - const colorMap = { - extruding: 0xff00ff, - g0: 0x00ff00 - }*/ - if (p2.extruding) { color = 0xff00ff } else if (p2.g === 0) { @@ -235,79 +237,10 @@ export function addSegment (state, args, p1, p2) { } gcodeObj.p2 = p2 gcodeObj.args = args - state.container.children.push(gcodeObj) - - // DISTANCE CALC - // add distance so we can calc estimated time to run - // see if arc - let dist = 0 - let a - let b - if (p2.arc) { - // calc dist of all lines - // console.log("this is an arc to calc dist for. p2.arcObj:", p2.arcObj, "p2:", p2) - let arcGeo = p2.arcObj.geometry - // console.log("arcGeo:", arcGeo) - - let tad2 = 0 - for (let arcLineCtr = 0; arcLineCtr < arcGeo.positions.length - 1; arcLineCtr++) { - tad2 += arcGeo.positions[arcLineCtr].distanceTo(arcGeo.positions[arcLineCtr + 1]) - } - // console.log("tad2:", tad2) - - // just do straight line calc - a = [p1.x, p1.y, p1.z] - b = [p2.x, p2.y, p2.z] - // const straightDist = a.distanceTo(b) - // console.log("diff of straight line calc vs arc sum. straightDist:", straightDist) - dist = tad2 - } else { - // just do straight line calc - a = [p1.x, p1.y, p1.z] - b = [p2.x, p2.y, p2.z] - dist = a.distanceTo(b) - } + state.container.children.push(gcodeObj)*/ - // Handle Laser Sxxx parameter - sv = args.s - // console.log(sv) - - // time distance computation - if (dist > 0) { - totalDist += dist - } - - // time to execute this move - // if this move is 10mm and we are moving at 100mm/min then - // this move will take 10/100 = 0.1 minutes or 6 seconds - let timeMinutes = 0 - if (dist > 0) { - let feedrate - if (args.feedrate > 0) { - feedrate = args.feedrate - } else { - feedrate = 100 - } - timeMinutes = dist / feedrate - - // adjust for acceleration, meaning estimate - // this will run longer than estimated from the math - // above because we don't start moving at full feedrate - // obviously, we have to slowly accelerate in and out - timeMinutes = timeMinutes * 1.32 - } - - state.metrics.totalTime += timeMinutes - - p2.feedrate = args.feedrate - p2.dist = dist - p2.distSum = state.metrics.totalDist - p2.timeMins = timeMinutes - p2.timeMinsSum = state.metrics.totalTime - - // console.log('Total Time'+totalTime) - state.metrics.totaltimemax += (timeMinutes * 60) - // console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) + state.bbox = bbox + state.bbox2 = bbox2 } export function addFakeSegment (state, args) { // lineObject, lastLine, lines) { @@ -329,54 +262,57 @@ export function addFakeSegment (state, args) { // lineObject, lastLine, lines) { } export function addLineSegment (state, args, p1, p2) { - if(state.debug){ + if(state.debug) { console.log('addLineSegment') } let {lineObject, lasermultiply, bufSize} = state let i = lineObject.nLines * 6 + i = state.linesDataOffset if (p1.a !== 0 || p2.a !== 0) { // A axis: rotate around X const R1 = Math.sqrt(p1.y * p1.y + p1.z * p1.z) const R2 = Math.sqrt(p2.y * p2.y + p2.z * p2.z) const a1 = p1.y === 0 ? Math.sign(p1.z) * 90 : Math.atan2(p1.z, p1.y) * 180.0 / Math.PI const a2 = p2.y === 0 ? Math.sign(p2.z) * 90 : Math.atan2(p2.z, p2.y) * 180.0 / Math.PI - lineObject.positions[i + 0] = p1.x + /*lineObject.positions[i + 0] = p1.x lineObject.positions[i + 1] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) lineObject.positions[i + 2] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) lineObject.positions[i + 3] = p2.x lineObject.positions[i + 4] = R2 * Math.cos((-p2.a + a2) * Math.PI / 180.0) - lineObject.positions[i + 5] = R2 * Math.sin((-p2.a + a2) * Math.PI / 180.0) + lineObject.positions[i + 5] = R2 * Math.sin((-p2.a + a2) * Math.PI / 180.0)*/ //FIXME: new structure should be G,X,Y,Z,E,F,S,T - /*lineObject.positions[i + 0] = p1.g + lineObject.positions[i + 0] = p1.g lineObject.positions[i + 1] = p1.x lineObject.positions[i + 2] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) lineObject.positions[i + 3] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) - lineObject.positions[i + 4] = p1.a - lineObject.positions[i + 5] = p1.e - lineObject.positions[i + 6] = p1.f + lineObject.positions[i + 4] = p1.e + lineObject.positions[i + 5] = p1.f + lineObject.positions[i + 6] = p1.a lineObject.positions[i + 7] = p1.s - lineObject.positions[i + 8] = p1.t*/ + lineObject.positions[i + 8] = p1.t + } else { - /*lineObject.positions[i + 0] = p1.g + lineObject.positions[i + 0] = p1.g lineObject.positions[i + 1] = p1.x // positions lineObject.positions[i + 2] = p1.y lineObject.positions[i + 3] = p1.z - lineObject.positions[i + 4] = p1.a - lineObject.positions[i + 5] = p1.e - lineObject.positions[i + 6] = p1.f + lineObject.positions[i + 4] = p1.e + lineObject.positions[i + 5] = p1.f + lineObject.positions[i + 6] = p1.a lineObject.positions[i + 7] = p1.s - lineObject.positions[i + 8] = p1.t*/ - + lineObject.positions[i + 8] = p1.t + /* lineObject.positions[i + 0] = p1.x // positions lineObject.positions[i + 1] = p1.y lineObject.positions[i + 2] = p1.z lineObject.positions[i + 3] = p2.x lineObject.positions[i + 4] = p2.y - lineObject.positions[i + 5] = p2.z + lineObject.positions[i + 5] = p2.z*/ } // console.log("Segment " + p1) + state.linesDataOffset += 9 // stride let color let intensity diff --git a/src/makeBaseState.js b/src/makeBaseState.js index 0d5c18e..2964258 100644 --- a/src/makeBaseState.js +++ b/src/makeBaseState.js @@ -12,6 +12,7 @@ export default function makeBaseState (gcode, indexMax) { name: 'LineObjects' }, linesData: [], + linesDataOffset:0, extraObjects: {// these are extra Object3D elements added during // the gcode rendering to attach to scene @@ -101,6 +102,9 @@ export default function makeBaseState (gcode, indexMax) { children: [] } } + //we prepare the storage for data + //we have 9 components : [g, x, y, z, e, f, s, t] + state.linesData.push(new Float32Array(9 * state.bufSize * 2)) // we have been using an approach where we just append // each gcode move to one monolithic geometry. we diff --git a/src/parseAsChunks.js b/src/parseAsChunks.js index 03ca441..9baa9e6 100644 --- a/src/parseAsChunks.js +++ b/src/parseAsChunks.js @@ -5,8 +5,6 @@ function now () { } export default function parseAsChunks (state, handlers, gcode, doneCallback) { - const {lineObjects, laserxmax, laserymax} = state - const lines = gcode.split(/\r{0,1}\n/) const count = lines.length const maxTimePerChunk = 500 diff --git a/src/timeAndDistance.js b/src/timeAndDistance.js index d17d8dd..69848d4 100644 --- a/src/timeAndDistance.js +++ b/src/timeAndDistance.js @@ -9,3 +9,77 @@ export function updateTimeAndDistance(currentState, input){ totaltimemax } } + + +export function updateTimeAndDistance2(state, args, p1, p2){ + // DISTANCE CALC + // add distance so we can calc estimated time to run + // see if arc + let dist = 0 + let a + let b + if (p2.arc) { + // calc dist of all lines + // console.log("this is an arc to calc dist for. p2.arcObj:", p2.arcObj, "p2:", p2) + let arcGeo = p2.arcObj.geometry + // console.log("arcGeo:", arcGeo) + + let tad2 = 0 + for (let arcLineCtr = 0; arcLineCtr < arcGeo.positions.length - 1; arcLineCtr++) { + tad2 += arcGeo.positions[arcLineCtr].distanceTo(arcGeo.positions[arcLineCtr + 1]) + } + // console.log("tad2:", tad2) + + // just do straight line calc + a = [p1.x, p1.y, p1.z] + b = [p2.x, p2.y, p2.z] + // const straightDist = a.distanceTo(b) + // console.log("diff of straight line calc vs arc sum. straightDist:", straightDist) + dist = tad2 + } else { + // just do straight line calc + a = [p1.x, p1.y, p1.z] + b = [p2.x, p2.y, p2.z] + dist = a.distanceTo(b) + } + + // Handle Laser Sxxx parameter + //sv = args.s + + // time distance computation + if (dist > 0) { + state.metrics.totalDist += dist + } + + // time to execute this move + // if this move is 10mm and we are moving at 100mm/min then + // this move will take 10/100 = 0.1 minutes or 6 seconds + let timeMinutes = 0 + if (dist > 0) { + let feedrate + if (args.feedrate > 0) { + feedrate = args.feedrate + } else { + feedrate = 100 + } + timeMinutes = dist / feedrate + + // adjust for acceleration, meaning estimate + // this will run longer than estimated from the math + // above because we don't start moving at full feedrate + // obviously, we have to slowly accelerate in and out + timeMinutes = timeMinutes * 1.32 + } + + state.metrics.totalTime += timeMinutes + + p2.feedrate = args.feedrate + p2.dist = dist + p2.distSum = state.metrics.totalDist + p2.timeMins = timeMinutes + p2.timeMinsSum = state.metrics.totalTime + + // console.log('Total Time'+totalTime) + state.metrics.totaltimemax += (timeMinutes * 60) + // console.log("calculating distance. dist:", dist, "totalDist:", totalDist, "feedrate:", args.feedrate, "timeMinsToExecute:", timeMinutes, "totalTime:", totalTime, "p1:", p1, "p2:", p2, "args:", args) +} diff --git a/test/tmptest.js b/test/tmptest.js deleted file mode 100644 index 29ee6f3..0000000 --- a/test/tmptest.js +++ /dev/null @@ -1,7 +0,0 @@ -import test from 'ava' -// import fs from 'fs' //does not work with babel + brfs -const fs = require('fs') -import parse from '../src/parse' - -const gcode = fs.readFileSync('./data/Rotary Axis GCode.gcode') -parse(gcode) From 3b5334c208b714ff2871a309ba4445e153aace83 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Mon, 21 Nov 2016 22:46:36 +0100 Subject: [PATCH 22/34] tests(travis): slight node version tweak for travis CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cf787f3..6ea24dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: node_js node_js: - - "4.2" + - "4.4" - "6.9" sudo: false From 3d5ead3b683e3e39d398c5125e52e4a5100d735b Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Mon, 21 Nov 2016 22:47:13 +0100 Subject: [PATCH 23/34] refactor():phasing out more obsolete code --- src/legacy/gcode-parser-breakapart.js | 27 --------------------------- src/{ => semi-obsolete}/drawObject.js | 0 2 files changed, 27 deletions(-) delete mode 100644 src/legacy/gcode-parser-breakapart.js rename src/{ => semi-obsolete}/drawObject.js (100%) diff --git a/src/legacy/gcode-parser-breakapart.js b/src/legacy/gcode-parser-breakapart.js deleted file mode 100644 index 5a68c16..0000000 --- a/src/legacy/gcode-parser-breakapart.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - - AUTHOR: John Lauer - -- S??? (laser intensity) Parameter Handling added by AUTHOR: Peter van der Walt - v19/6/2016 - -*/ - -// This is a simplified and updated version of http://gcode.joewalnes.com/ that works with the latest version of Three.js (v68). -// Updated with code from http://chilipeppr.com/tinyg's 3D viewer to support more CNC type Gcode - - -var lineObjects = new THREE.Object3D() -lineObjects.name = 'LineObjects' - -function GCodeParser (handlers) { - handlers = handlers || {} - -} - - - - var material = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors, - opacity: 0.8, - transparent: true, - linewidth: 1, - }) diff --git a/src/drawObject.js b/src/semi-obsolete/drawObject.js similarity index 100% rename from src/drawObject.js rename to src/semi-obsolete/drawObject.js From 18ef16865a321d57d03b19794e57dff8d9f53a37 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Mon, 21 Nov 2016 22:59:00 +0100 Subject: [PATCH 24/34] feat(segements): updated segements parsing to new data structure, updated specs --- src/geometries/segments.js | 86 ++++++++++++++++++++------------------ src/makeBaseState.js | 2 +- test/gcodeParser.spec.js | 2 +- 3 files changed, 48 insertions(+), 42 deletions(-) diff --git a/src/geometries/segments.js b/src/geometries/segments.js index 5bd2778..a2e4194 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -265,56 +265,62 @@ export function addLineSegment (state, args, p1, p2) { if(state.debug) { console.log('addLineSegment') } - let {lineObject, lasermultiply, bufSize} = state - let i = lineObject.nLines * 6 - i = state.linesDataOffset + let {linesData, lineObject, lasermultiply, bufSize} = state + //let i = lineObject.nLines * 6 + let i = state.linesDataOffset if (p1.a !== 0 || p2.a !== 0) { // A axis: rotate around X const R1 = Math.sqrt(p1.y * p1.y + p1.z * p1.z) const R2 = Math.sqrt(p2.y * p2.y + p2.z * p2.z) const a1 = p1.y === 0 ? Math.sign(p1.z) * 90 : Math.atan2(p1.z, p1.y) * 180.0 / Math.PI const a2 = p2.y === 0 ? Math.sign(p2.z) * 90 : Math.atan2(p2.z, p2.y) * 180.0 / Math.PI - /*lineObject.positions[i + 0] = p1.x - lineObject.positions[i + 1] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) - lineObject.positions[i + 2] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) - lineObject.positions[i + 3] = p2.x - lineObject.positions[i + 4] = R2 * Math.cos((-p2.a + a2) * Math.PI / 180.0) - lineObject.positions[i + 5] = R2 * Math.sin((-p2.a + a2) * Math.PI / 180.0)*/ - - //FIXME: new structure should be G,X,Y,Z,E,F,S,T - lineObject.positions[i + 0] = p1.g - lineObject.positions[i + 1] = p1.x - lineObject.positions[i + 2] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) - lineObject.positions[i + 3] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) - lineObject.positions[i + 4] = p1.e - lineObject.positions[i + 5] = p1.f - lineObject.positions[i + 6] = p1.a - lineObject.positions[i + 7] = p1.s - lineObject.positions[i + 8] = p1.t - } else { - lineObject.positions[i + 0] = p1.g - lineObject.positions[i + 1] = p1.x // positions - lineObject.positions[i + 2] = p1.y - lineObject.positions[i + 3] = p1.z - lineObject.positions[i + 4] = p1.e - lineObject.positions[i + 5] = p1.f - lineObject.positions[i + 6] = p1.a - lineObject.positions[i + 7] = p1.s - lineObject.positions[i + 8] = p1.t + linesData[i + 0] = p1.g + linesData[i + 1] = p1.x + linesData[i + 2] = R1 * Math.cos((-p1.a + a1) * Math.PI / 180.0) + linesData[i + 3] = R1 * Math.sin((-p1.a + a1) * Math.PI / 180.0) + linesData[i + 4] = p1.e + linesData[i + 5] = p1.f + linesData[i + 6] = p1.a + linesData[i + 7] = p1.s + linesData[i + 8] = p1.t + + linesData[i + 9] = p2.g + linesData[i + 10] = p2.x + linesData[i + 11] = R2 * Math.cos((-p2.a + a2) * Math.PI / 180.0) + linesData[i + 12] = R2 * Math.sin((-p2.a + a2) * Math.PI / 180.0) + linesData[i + 13] = p2.e + linesData[i + 14] = p2.f + linesData[i + 15] = p2.a + linesData[i + 16] = p2.s + linesData[i + 17] = p2.t - /* - lineObject.positions[i + 0] = p1.x // positions - lineObject.positions[i + 1] = p1.y - lineObject.positions[i + 2] = p1.z - lineObject.positions[i + 3] = p2.x - lineObject.positions[i + 4] = p2.y - lineObject.positions[i + 5] = p2.z*/ + } else { + linesData[i + 0] = p1.g + linesData[i + 1] = p1.x // positions + linesData[i + 2] = p1.y + linesData[i + 3] = p1.z + linesData[i + 4] = p1.e + linesData[i + 5] = p1.f + linesData[i + 6] = p1.a + linesData[i + 7] = p1.s + linesData[i + 8] = p1.t + + linesData[i + 9] = p2.g + linesData[i + 10] = p2.x + linesData[i + 11] = p2.y + linesData[i + 12] = p2.z + linesData[i + 13] = p2.e + linesData[i + 14] = p2.f + linesData[i + 15] = p2.a + linesData[i + 16] = p2.s + linesData[i + 17] = p2.t } // console.log("Segment " + p1) - state.linesDataOffset += 9 // stride + state.linesDataOffset += 18 // stride - let color + //color : not used anymore (for now ?) + /*let color let intensity if (p2.g === 0) { // g0 color = {r: 0, g: 1, b: 0} @@ -341,7 +347,7 @@ export function addLineSegment (state, args, p1, p2) { if (lineObject.nLines === bufSize) { closeLineSegment(state) - } + }*/ const dist = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)) state.metrics.totalDist += dist diff --git a/src/makeBaseState.js b/src/makeBaseState.js index 2964258..e671632 100644 --- a/src/makeBaseState.js +++ b/src/makeBaseState.js @@ -12,7 +12,7 @@ export default function makeBaseState (gcode, indexMax) { name: 'LineObjects' }, linesData: [], - linesDataOffset:0, + linesDataOffset: 0, extraObjects: {// these are extra Object3D elements added during // the gcode rendering to attach to scene diff --git a/test/gcodeParser.spec.js b/test/gcodeParser.spec.js index 0b8bf8d..eed73a7 100644 --- a/test/gcodeParser.spec.js +++ b/test/gcodeParser.spec.js @@ -7,7 +7,7 @@ test.cb('gcode parser tests: can parse gcode files', t => { const gcode = fs.readFileSync('./data/Rotary Axis GCode.gcode','utf8') parse(gcode, function(data){ console.log('done with parsing',data.metrics) - t.deepEqual(data.lineObjects.lines.length, 24) + t.deepEqual(data.linesData.length, 5904) //t.deepEqual(data.positions.length / 3, 864) // we divide by three because each entry is 3 long //t.deepEqual(data.positions[0], -0.025066649541258812) //t.deepEqual(data.positions[data.positions.length - 1], 0.019999999552965164) From 83b91732677b2bdb38cf4b8b36a3bed89dc112ca Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Tue, 22 Nov 2016 10:30:36 +0100 Subject: [PATCH 25/34] test(): moved test data to external repo, added test for multi material 3dp gcode --- test/data/Rotary Axis GCode.gcode | 363 ------------------------------ test/gcodeParser.spec.js | 35 +-- 2 files changed, 22 insertions(+), 376 deletions(-) delete mode 100644 test/data/Rotary Axis GCode.gcode diff --git a/test/data/Rotary Axis GCode.gcode b/test/data/Rotary Axis GCode.gcode deleted file mode 100644 index d5a2a45..0000000 --- a/test/data/Rotary Axis GCode.gcode +++ /dev/null @@ -1,363 +0,0 @@ -(G Code Wrapped by the Chestnut Pens GCodeWrapper Program.) -(Toolpath Creation Program © R.W.Williams, 2013) -(Max Straight segment length = 1.0000mm) -(Max arc angle of segment around centre = 1.0000degrees) -(Note: All dimensions are converted to mm) -(Total Running Time minimum = 2 Minutes, 45.79 Seconds. ) -(Original file Axis height Z = 0.0000) -(Original file Nominal Work height Z = 60.0000) -(This file Axis height Z = 0.0000) -(Y axis is wrapped...) -(...onto the A axis) -G0 F3600 A58.2335 X0.0000 -G1 F1200 Z60.0000 -M3 -G1 F1200 X18.5400 S255 -G1 F1200 A15.0468 S255 -G1 F1200 X47.4760 S255 -G1 F1200 A0.9377 S255 -G1 F1200 X0.0000 S255 -G1 F1200 A58.2335 S255 -M5 -G0 A28.9993 X69.9860 -G1 F1200 -M3 -G1 F1200 A30.6017 X54.0650 S255 -G1 F1200 A34.1636 X55.1650 S255 -G1 F1200 A36.8746 X56.6640 S255 -G1 F1200 A39.0098 X58.7360 S255 -G1 F1200 A40.8414 X61.5550 S255 -G1 F1200 A41.9166 X64.2770 S255 -G1 F1200 A42.7178 X67.8580 S255 -G1 F1200 A43.3825 X76.5350 S255 -G1 F1200 A43.1819 X83.2880 S255 -G1 F1200 A42.5813 X88.5680 S255 -G1 F1200 A41.3446 X92.7320 S255 -G1 F1200 A39.2390 X96.1390 S255 -G1 F1200 A37.1143 X98.0420 S255 -G1 F1200 A34.2562 X99.4950 S255 -G1 F1200 A31.1049 X100.4160 S255 -G1 F1200 A28.1007 X100.7230 S255 -G1 F1200 A9.7708 S255 -G1 F1200 A5.1786 X101.1120 S255 -G1 F1200 A0.9377 X102.8100 S255 -G1 F1200 X87.1760 S255 -G1 F1200 A3.3805 X85.9480 S255 -G1 F1200 A6.0189 X85.3750 S255 -G1 F1200 A3.4397 X82.1110 S255 -G1 F1200 A1.7198 X78.8680 S255 -G1 F1200 A0.4297 X74.0890 S255 -G1 F1200 A0.0000 X68.5950 S255 -G1 F1200 A0.2149 X64.9410 S255 -G1 F1200 A0.8594 X61.7550 S255 -G1 F1200 A1.9347 X59.0370 S255 -G1 F1200 A3.4397 X56.7870 S255 -G1 F1200 A5.2588 X55.0230 S255 -G1 F1200 A7.2794 X53.7640 S255 -G1 F1200 A9.4996 X53.0080 S255 -G1 F1200 A11.9204 X52.7560 S255 -G1 F1200 A16.2290 X53.4820 S255 -G1 F1200 A19.6983 X55.6620 S255 -G1 F1200 A21.1240 X57.4220 S255 -G1 F1200 A22.3559 X59.7950 S255 -G1 F1200 A24.2313 X66.3850 S255 -G1 F1200 A26.7524 X78.5400 S255 -G1 F1200 A28.6479 X84.4340 S255 -G1 F1200 A31.1393 X84.1170 S255 -G1 F1200 A32.7512 X83.1650 S255 -G1 F1200 A33.6307 X81.4150 S255 -G1 F1200 A33.9239 X78.7040 S255 -G1 F1200 A33.6116 X75.1230 S255 -G1 F1200 A32.6739 X72.5650 S255 -G1 F1200 A31.2663 X71.1220 S255 -G1 F1200 A28.9993 X69.9860 S255 -M5 -G0 A20.6360 X84.4340 -G1 F1200 -M3 -G1 F1200 A18.5648 X77.2710 S255 -G1 F1200 A17.2842 X73.1280 S255 -G1 F1200 A16.0237 X70.8460 S255 -G1 F1200 A14.6467 X69.8020 S255 -G1 F1200 A13.0930 X69.4540 S255 -G1 F1200 A11.3875 X69.7970 S255 -G1 F1200 A10.0249 X70.8250 S255 -G1 F1200 A9.1310 X72.5190 S255 -G1 F1200 A8.8331 X74.8570 S255 -G1 F1200 A9.1549 X77.5430 S255 -G1 F1200 A10.1223 X80.0340 S255 -G1 F1200 A11.5537 X82.0800 S255 -G1 F1200 A13.2687 X83.4310 S255 -G1 F1200 A15.4040 X84.1830 S255 -G1 F1200 A18.0959 X84.4340 S255 -G1 F1200 A20.6360 S255 -M5 -G0 A12.4676 X107.7630 -G1 F1200 -M3 -G1 F1200 A13.9525 X124.2970 S255 -G1 F1200 A11.5394 X125.5250 S255 -G1 F1200 A9.9274 X127.1620 S255 -G1 F1200 A9.0184 X129.3110 S255 -G1 F1200 A8.7156 X132.0740 S255 -G1 F1200 A9.0575 X135.0510 S255 -G1 F1200 A10.0821 X137.2710 S255 -G1 F1200 A11.2233 X138.3460 S255 -G1 F1200 A12.6184 X138.7040 S255 -G1 F1200 A14.1406 X138.2330 S255 -G1 F1200 A15.2722 X136.8210 S255 -G1 F1200 A16.9108 X129.6590 S255 -G1 F1200 A18.3022 X122.3070 S255 -G1 F1200 A19.5856 X117.6060 S255 -G1 F1200 A21.2395 X114.4950 S255 -G1 F1200 A23.7434 X111.9170 S255 -G1 F1200 A26.8765 X110.1820 S255 -G1 F1200 A30.4193 X109.6040 S255 -G1 F1200 A34.2361 X110.2290 S255 -G1 F1200 A37.4867 X112.1010 S255 -G1 F1200 A40.0784 X115.0680 S255 -G1 F1200 A41.9185 X118.9770 S255 -G1 F1200 A43.0158 X124.1030 S255 -G1 F1200 A43.3825 X130.7230 S255 -G1 F1200 A43.0988 X137.4810 S255 -G1 F1200 A42.2490 X142.2030 S255 -G1 F1200 A40.8032 X145.6000 S255 -G1 F1200 A38.7310 X148.3830 S255 -G1 F1200 A35.9273 X150.6500 S255 -G1 F1200 A32.2824 X152.4970 S255 -G1 F1200 A30.7974 X136.6980 S255 -G1 F1200 A32.5268 X135.8800 S255 -G1 F1200 A33.7291 X134.6520 S255 -G1 F1200 A34.6668 X132.4830 S255 -G1 F1200 A34.9791 X129.9050 S255 -G1 F1200 A34.7403 X127.4640 S255 -G1 F1200 A34.0232 X125.7910 S255 -G1 F1200 A32.9651 X124.8240 S255 -G1 F1200 A31.7018 X124.5020 S255 -G1 F1200 A30.3649 X124.9110 S255 -G1 F1200 A29.3994 X126.1390 S255 -G1 F1200 A28.6574 X128.7380 S255 -G1 F1200 A27.9938 X133.2610 S255 -G1 F1200 A26.9204 X140.5050 S255 -G1 F1200 A25.4957 X145.6210 S255 -G1 F1200 A23.5533 X149.1970 S255 -G1 F1200 A20.9273 X151.8210 S255 -G1 F1200 A17.8142 X153.4330 S255 -G1 F1200 A14.4070 X153.9700 S255 -G1 F1200 A10.8642 X153.4020 S255 -G1 F1200 A7.4188 X151.6980 S255 -G1 F1200 A4.3678 X148.7720 S255 -G1 F1200 A2.0111 X144.5360 S255 -G1 F1200 A0.5023 X138.7600 S255 -G1 F1200 A0.0000 X131.2140 S255 -G1 F1200 A0.2024 X125.6880 S255 -G1 F1200 A0.8107 X121.0180 S255 -G1 F1200 A1.8249 X117.2050 S255 -G1 F1200 A3.2439 X114.2500 S255 -G1 F1200 A5.0373 X111.9490 S255 -G1 F1200 A7.1715 X110.1010 S255 -G1 F1200 A9.6486 X108.7050 S255 -G1 F1200 A12.4676 X107.7630 S255 -M5 -G0 A17.7435 X210.1640 -G1 F1200 -M3 -G1 F1200 X176.7670 S255 -G1 F1200 A14.4022 X177.5340 S255 -G1 F1200 A12.0378 X178.9360 S255 -G1 F1200 A10.0153 X181.7190 S255 -G1 F1200 A9.3411 X185.2390 S255 -G1 F1200 A9.6343 X187.6330 S255 -G1 F1200 A10.5138 X189.9050 S255 -G1 F1200 A13.1322 X192.8100 S255 -G1 F1200 A11.6855 X209.2220 S255 -G1 F1200 A6.3169 X205.0680 S255 -G1 F1200 A4.2953 X202.7000 S255 -G1 F1200 A2.7158 X200.1360 S255 -G1 F1200 A1.5279 X197.1870 S255 -G1 F1200 A0.6790 X193.6600 S255 -G1 F1200 A0.0000 X184.8700 S255 -G1 F1200 A0.5816 X177.1560 S255 -G1 F1200 A2.3253 X171.2820 S255 -G1 F1200 A5.3352 X166.7550 S255 -G1 F1200 A9.7126 X163.0760 S255 -G1 F1200 A12.3539 X161.6530 S255 -G1 F1200 A15.2178 X160.6360 S255 -G1 F1200 A21.6129 X159.8230 S255 -G1 F1200 A26.2462 X160.2310 S255 -G1 F1200 A30.4164 X161.4550 S255 -G1 F1200 A34.1215 X163.4950 S255 -G1 F1200 A37.3635 X166.3510 S255 -G1 F1200 A39.9963 X169.9250 S255 -G1 F1200 A41.8775 X174.1220 S255 -G1 F1200 A43.0062 X178.9400 S255 -G1 F1200 A43.3825 X184.3790 S255 -G1 F1200 A42.7083 X192.7290 S255 -G1 F1200 A41.8651 X196.1660 S255 -G1 F1200 A40.6857 X199.1130 S255 -G1 F1200 A37.3826 X203.8710 S255 -G1 F1200 A32.8687 X207.3400 S255 -G1 F1200 A30.1156 X208.5750 S255 -G1 F1200 A26.9768 X209.4580 S255 -G1 F1200 A19.5417 X210.1640 S255 -G1 F1200 A17.7435 S255 -M5 -G0 A25.3648 X193.2200 -G1 F1200 -M3 -G1 F1200 A29.3221 X192.3240 S255 -G1 F1200 A31.9701 X190.6210 S255 -G1 F1200 A33.4646 X188.1800 S255 -G1 F1200 A33.9630 X185.0750 S255 -G1 F1200 A33.2105 X181.5040 S255 -G1 F1200 A30.9540 X178.7310 S255 -G1 F1200 A28.6183 X177.4930 S255 -G1 F1200 A25.3648 X176.8080 S255 -G1 F1200 X193.2200 S255 -M5 -G0 A42.4438 X217.9810 -G1 F1200 -M3 -G1 F1200 X233.5740 S255 -G1 F1200 A35.6437 S255 -G1 F1200 A39.3717 X235.8610 S255 -G1 F1200 A41.7209 X238.2200 S255 -G1 F1200 A42.9671 X240.8950 S255 -G1 F1200 A43.3825 X244.1340 S255 -G1 F1200 A42.8353 X247.9910 S255 -G1 F1200 A41.1938 X252.1960 S255 -G1 F1200 A29.8597 X247.0400 S255 -G1 F1200 A31.0323 X242.3740 S255 -G1 F1200 A30.3868 X239.4680 S255 -G1 F1200 A28.4521 X237.2990 S255 -G1 F1200 A26.2396 X236.1710 S255 -G1 F1200 A23.2353 X235.3650 S255 -G1 F1200 A14.8520 X234.7200 S255 -G1 F1200 A0.9377 S255 -G1 F1200 X217.9810 S255 -G1 F1200 A42.4438 S255 -M5 -G0 A58.2335 X249.9450 -G1 F1200 -M3 -G1 F1200 X267.5550 S255 -G1 F1200 A26.2376 X273.9190 S255 -G1 F1200 A58.2335 X283.1750 S255 -G1 F1200 X300.7200 S255 -G1 F1200 A26.2014 X310.0230 S255 -G1 F1200 A58.2335 X316.3700 S255 -G1 F1200 X333.8880 S255 -G1 F1200 A0.9377 X320.6630 S255 -G1 F1200 X302.4820 S255 -G1 F1200 A37.0121 X291.9580 S255 -G1 F1200 A0.9377 X281.4750 S255 -G1 F1200 X263.2940 S255 -G1 F1200 A58.2335 X249.9450 S255 -M5 -G0 A17.7435 X387.0940 -G1 F1200 -M3 -G1 F1200 X353.6970 S255 -G1 F1200 A14.4022 X354.4650 S255 -G1 F1200 A12.0378 X355.8660 S255 -G1 F1200 A10.0153 X358.6490 S255 -G1 F1200 A9.3411 X362.1690 S255 -G1 F1200 A9.6343 X364.5630 S255 -G1 F1200 A10.5138 X366.8350 S255 -G1 F1200 A13.1322 X369.7410 S255 -G1 F1200 A11.6855 X386.1530 S255 -G1 F1200 A6.3169 X381.9990 S255 -G1 F1200 A4.2953 X379.6300 S255 -G1 F1200 A2.7158 X377.0670 S255 -G1 F1200 A1.5279 X374.1170 S255 -G1 F1200 A0.6790 X370.5900 S255 -G1 F1200 A0.0000 X361.8010 S255 -G1 F1200 A0.5816 X354.0860 S255 -G1 F1200 A2.3253 X348.2130 S255 -G1 F1200 A5.3352 X343.6850 S255 -G1 F1200 A9.7126 X340.0070 S255 -G1 F1200 A12.3539 X338.5830 S255 -G1 F1200 A15.2178 X337.5670 S255 -G1 F1200 A21.6129 X336.7530 S255 -G1 F1200 A26.2462 X337.1610 S255 -G1 F1200 A30.4164 X338.3850 S255 -G1 F1200 A34.1215 X340.4250 S255 -G1 F1200 A37.3635 X343.2810 S255 -G1 F1200 A39.9963 X346.8560 S255 -G1 F1200 A41.8775 X351.0520 S255 -G1 F1200 A43.0062 X355.8700 S255 -G1 F1200 A43.3825 X361.3100 S255 -G1 F1200 A42.7083 X369.6590 S255 -G1 F1200 A41.8651 X373.0970 S255 -G1 F1200 A40.6857 X376.0440 S255 -G1 F1200 A37.3826 X380.8020 S255 -G1 F1200 A32.8687 X384.2700 S255 -G1 F1200 A30.1156 X385.5060 S255 -G1 F1200 A26.9768 X386.3880 S255 -G1 F1200 A19.5417 X387.0940 S255 -G1 F1200 A17.7435 S255 -M5 -G0 A25.3648 X370.1500 -G1 F1200 -M3 -G1 F1200 A29.3221 X369.2550 S255 -G1 F1200 A31.9701 X367.5510 S255 -G1 F1200 A33.4646 X365.1110 S255 -G1 F1200 A33.9630 X362.0050 S255 -G1 F1200 A33.2105 X358.4350 S255 -G1 F1200 A30.9540 X355.6620 S255 -G1 F1200 A28.6183 X354.4240 S255 -G1 F1200 A25.3648 X353.7380 S255 -G1 F1200 X370.1500 S255 -M5 -G0 A58.2335 X394.8290 -G1 F1200 -M3 -G1 F1200 X411.6510 S255 -G1 F1200 A38.3796 S255 -G1 F1200 A40.5683 X414.3160 S255 -G1 F1200 A42.1315 X417.3190 S255 -G1 F1200 A43.0692 X420.6600 S255 -G1 F1200 A43.3825 X424.3380 S255 -G1 F1200 A43.0415 X428.1370 S255 -G1 F1200 A42.0188 X431.5930 S255 -G1 F1200 A40.3152 X434.7060 S255 -G1 F1200 A37.9298 X437.4760 S255 -G1 F1200 A34.9075 X439.7500 S255 -G1 F1200 A31.2911 X441.3740 S255 -G1 F1200 A27.0809 X442.3490 S255 -G1 F1200 A22.2776 X442.6740 S255 -G1 F1200 A15.8824 X442.0800 S255 -G1 F1200 A10.2980 X440.3000 S255 -G1 F1200 A5.7745 X437.4710 S255 -G1 F1200 A2.5602 X433.7310 S255 -G1 F1200 A0.6398 X429.3060 S255 -G1 F1200 A0.0000 X424.4200 S255 -G1 F1200 A0.4498 X420.2250 S255 -G1 F1200 A1.7981 X416.3980 S255 -G1 F1200 A3.8207 X413.5330 S255 -G1 F1200 A7.0741 X410.4230 S255 -G1 F1200 A0.9377 S255 -G1 F1200 X394.8290 S255 -G1 F1200 A58.2335 S255 -M5 -G0 A21.8087 X411.5280 -G1 F1200 -M3 -G1 F1200 A17.1916 X412.0550 S255 -G1 F1200 A14.0499 X413.6360 S255 -G1 F1200 A12.2479 X416.0250 S255 -G1 F1200 A11.6463 X418.9770 S255 -G1 F1200 A12.2374 X421.7240 S255 -G1 F1200 A14.0117 X423.9900 S255 -G1 F1200 A17.1820 X425.5100 S255 -G1 F1200 A21.9643 X426.0160 S255 -G1 F1200 A26.2348 X425.5200 S255 -G1 F1200 A29.1951 X424.0310 S255 -G1 F1200 A30.9244 X421.8370 S255 -G1 F1200 A31.5012 X419.2220 S255 -G1 F1200 A30.8996 X416.1370 S255 -G1 F1200 A29.0977 X413.6770 S255 -G1 F1200 A26.0734 X412.0650 S255 -G1 F1200 A21.8087 X411.5280 S255 -M5 diff --git a/test/gcodeParser.spec.js b/test/gcodeParser.spec.js index eed73a7..897b2dc 100644 --- a/test/gcodeParser.spec.js +++ b/test/gcodeParser.spec.js @@ -3,20 +3,29 @@ import test from 'ava' const fs = require('fs') import parse from '../src/index' -test.cb('gcode parser tests: can parse gcode files', t => { - const gcode = fs.readFileSync('./data/Rotary Axis GCode.gcode','utf8') - parse(gcode, function(data){ - console.log('done with parsing',data.metrics) +test.cb('gcode parser: can parse gcode files', t => { + const gcode = fs.readFileSync('../node_modules/lw-sample-files/gcode/Rotary Axis GCode.gcode', 'utf8') + parse(gcode, function (data) { + console.log('done with parsing', data.metrics) t.deepEqual(data.linesData.length, 5904) - //t.deepEqual(data.positions.length / 3, 864) // we divide by three because each entry is 3 long - //t.deepEqual(data.positions[0], -0.025066649541258812) - //t.deepEqual(data.positions[data.positions.length - 1], 0.019999999552965164) + // t.deepEqual(data.positions.length / 3, 864) // we divide by three because each entry is 3 long + // t.deepEqual(data.positions[0], -0.025066649541258812) + // t.deepEqual(data.positions[data.positions.length - 1], 0.019999999552965164) + t.end() + }) +/*fs.createReadStream('./data/test.gcode', { encoding: null, highWaterMark: 512 * 1024 }) // 'binary' + .pipe(makeStlStream()) + .pipe(concatStream(function (parsedgcode) { + t.end() + }))*/ +}) + + +test.cb('gcode parser: can parse multi material 3d printer gcode', t => { + const gcode = fs.readFileSync('../node_modules/lw-sample-files/gcode/3dp_dualExtrusion_UM3.gcode', 'utf8') + parse(gcode, function (data) { + console.log('done with parsing', data.metrics) + t.deepEqual(data.linesData.length, 759060) t.end() }) - // this.timeout(5000) - /*fs.createReadStream('./data/test.gcode', { encoding: null, highWaterMark: 512 * 1024 }) // 'binary' - .pipe(makeStlStream()) - .pipe(concatStream(function (parsedgcode) { - t.end() - }))*/ }) From 6ee3e94d30465168e8c3842ba22536bffad2b9c6 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Tue, 22 Nov 2016 10:31:06 +0100 Subject: [PATCH 26/34] chore(package): added devdepency to lw-sample-files , for testing --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 2d20a29..73317d5 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "dependencies": { }, "devDependencies": { + "lw-sample-files":"LaserWeb/lw-sample-files", "ava": "0.16", "babel-cli": "^6.6.5", "babel-core": "^6.2.1", From 2f37ddb758bceb2b1595251a00445c93f2e89a1d Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Tue, 22 Nov 2016 10:32:20 +0100 Subject: [PATCH 27/34] fix(handlers): minor fix of missing state for some handlers --- src/gcodeHandlers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js index e5e1dd4..f3d80a0 100644 --- a/src/gcodeHandlers.js +++ b/src/gcodeHandlers.js @@ -294,13 +294,13 @@ export default function makeHandlers (params) { // Dual Head 3D Printing Support T0: function (state, args) { // console.log('Found Tool: ', args) - lastLine.t = 0 + state.lastLine.t = 0 addFakeSegment(state, args) }, T1: function (state, args) { // console.log('Found Tool: ', args) - lastLine.t = 1 + state.lastLine.t = 1 addFakeSegment(state, args) }, From f12816ecbafb7f0ce62c985cf70f572f3b5856ed Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Tue, 22 Nov 2016 10:32:51 +0100 Subject: [PATCH 28/34] feat(segments): further changes/tweaks for new data structure --- src/geometries/segments.js | 35 ++++++++++++++++++++++------------- src/makeBaseState.js | 4 +++- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/geometries/segments.js b/src/geometries/segments.js index a2e4194..3586f2a 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -1,8 +1,8 @@ import { getLineGroup } from '../layers' -import {drawArcFrom2PtsAndCenter} from './arcs' +import { drawArcFrom2PtsAndCenter } from './arcs' export function addSegment (state, args, p1, p2) { - if(state.debug){ + if (state.debug) { console.log('addSegment') } closeLineSegment(state) @@ -151,8 +151,8 @@ export function addSegment (state, args, p1, p2) { // still push the normal p1/p2 point for debug p2.g2 = true p2.arcObj = arcObj - //MM_removed - //group = getLineGroup(p2, args) + // MM_removed + // group = getLineGroup(p2, args) // these golden lines showing start/end of a g2 or g3 arc were confusing people // so hiding them for now. jlauer 8/15/15 @@ -169,9 +169,9 @@ export function addSegment (state, args, p1, p2) { geometry.positions.push(p1.x, p1.y, p1.z) geometry.positions.push(p2.x, p2.y, p2.z) - /*MM_removed - geometry.colors.push(group.color) - geometry.colors.push(group.color)*/ + /*MM_removed + geometry.colors.push(group.color) + geometry.colors.push(group.color)*/ } if (p2.extruding) { @@ -262,11 +262,20 @@ export function addFakeSegment (state, args) { // lineObject, lastLine, lines) { } export function addLineSegment (state, args, p1, p2) { - if(state.debug) { + if (state.debug) { console.log('addLineSegment') } - let {linesData, lineObject, lasermultiply, bufSize} = state - //let i = lineObject.nLines * 6 + let {linesData, linesDataOffset, linesDataStride, bufSize} = state + /*if(linesDataOffset%linesDataStride>linesData){ + linesData.push(new Float32Array(9 * bufSize * 2)) + }*/ + const chunkIndex = Math.ceil((linesDataOffset + linesDataStride) / bufSize) - 1 + const curIndex = linesData.length / bufSize + //console.log('chunkIndex', chunkIndex, foo) + /*if (linesDataOffset + linesDataStride > bufSize) { + let tmp = linesDataStride new Float32Array(bufSize * linesDataStride) + }*/ + // let i = lineObject.nLines * 6 let i = state.linesDataOffset if (p1.a !== 0 || p2.a !== 0) { // A axis: rotate around X @@ -294,7 +303,6 @@ export function addLineSegment (state, args, p1, p2) { linesData[i + 15] = p2.a linesData[i + 16] = p2.s linesData[i + 17] = p2.t - } else { linesData[i + 0] = p1.g linesData[i + 1] = p1.x // positions @@ -319,8 +327,9 @@ export function addLineSegment (state, args, p1, p2) { // console.log("Segment " + p1) state.linesDataOffset += 18 // stride + /*MM_removed //color : not used anymore (for now ?) - /*let color + let color let intensity if (p2.g === 0) { // g0 color = {r: 0, g: 1, b: 0} @@ -356,7 +365,7 @@ export function addLineSegment (state, args, p1, p2) { } export function closeLineSegment ({debug, lineObject, lineObjects}) { - if(debug){ + if (debug) { console.log('closeLineSegment', lineObject.nLines) } if (lineObject.nLines === 0) { diff --git a/src/makeBaseState.js b/src/makeBaseState.js index e671632..41a08b6 100644 --- a/src/makeBaseState.js +++ b/src/makeBaseState.js @@ -11,8 +11,10 @@ export default function makeBaseState (gcode, indexMax) { nLines: 0, name: 'LineObjects' }, + linesData: [], linesDataOffset: 0, + linesDataStride: 18,// each chunk of data is 18 (9x2) long extraObjects: {// these are extra Object3D elements added during // the gcode rendering to attach to scene @@ -103,7 +105,7 @@ export default function makeBaseState (gcode, indexMax) { } } //we prepare the storage for data - //we have 9 components : [g, x, y, z, e, f, s, t] + //we have 9 components : [g, x, y, z, e, f, s, t], times 2 state.linesData.push(new Float32Array(9 * state.bufSize * 2)) // we have been using an approach where we just append From 13025f384afb6beaa4c9d00a368bb749b42d600e Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Wed, 23 Nov 2016 22:33:23 +0100 Subject: [PATCH 29/34] feat(data storage): added automatic resizing of typedArrays used for storage --- src/geometries/segments.js | 19 ++++++++++--------- src/parseAsChunks.js | 4 +++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/geometries/segments.js b/src/geometries/segments.js index 3586f2a..6840d2f 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -266,15 +266,16 @@ export function addLineSegment (state, args, p1, p2) { console.log('addLineSegment') } let {linesData, linesDataOffset, linesDataStride, bufSize} = state - /*if(linesDataOffset%linesDataStride>linesData){ - linesData.push(new Float32Array(9 * bufSize * 2)) - }*/ - const chunkIndex = Math.ceil((linesDataOffset + linesDataStride) / bufSize) - 1 - const curIndex = linesData.length / bufSize - //console.log('chunkIndex', chunkIndex, foo) - /*if (linesDataOffset + linesDataStride > bufSize) { - let tmp = linesDataStride new Float32Array(bufSize * linesDataStride) - }*/ + + //to store the next batch of data we need this many chunks + const chunkIndex = Math.ceil((linesDataOffset + linesDataStride) / bufSize) + const chunksNb = linesData.length / bufSize + if (chunkIndex > chunksNb) { // resize data to fit new entries + //console.log('resizing') + let resizedLinesData = new Float32Array(state.bufSize * chunkIndex) + resizedLinesData.set(linesData, 0) + linesData = state.linesData = resizedLinesData + } // let i = lineObject.nLines * 6 let i = state.linesDataOffset diff --git a/src/parseAsChunks.js b/src/parseAsChunks.js index 9baa9e6..8de61c9 100644 --- a/src/parseAsChunks.js +++ b/src/parseAsChunks.js @@ -26,7 +26,9 @@ export default function parseAsChunks (state, handlers, gcode, doneCallback) { setTimeout(doChunk, 1) // set Timeout for async iteration // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") } else { - //console.log('done parsing')//, state.lineObjects.lines) + // console.log('done parsing')//, state.lineObjects.lines) + // cleanup , resize data typedArray to match actual data size + state.linesData = state.linesData.subarray(0, state.linesDataOffset) doneCallback(state) } } From 4de3dd88ad092119adbf465cf8114055ef2838f0 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Wed, 23 Nov 2016 22:50:14 +0100 Subject: [PATCH 30/34] refactor(): more 'binning' of obsolete code --- src/{ => semi-obsolete}/lineGroup.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{ => semi-obsolete}/lineGroup.js (100%) diff --git a/src/lineGroup.js b/src/semi-obsolete/lineGroup.js similarity index 100% rename from src/lineGroup.js rename to src/semi-obsolete/lineGroup.js From b63fa975a8c0736108e3f1a47ffc83f5c888e1cf Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Thu, 24 Nov 2016 08:43:16 +0100 Subject: [PATCH 31/34] feat(state): modified/simplified base state --- src/makeBaseState.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/makeBaseState.js b/src/makeBaseState.js index 41a08b6..dff91b8 100644 --- a/src/makeBaseState.js +++ b/src/makeBaseState.js @@ -1,6 +1,6 @@ export default function makeBaseState (gcode, indexMax) { let state = { - debug: true, + debug: false, tool: null, relative: false, @@ -15,6 +15,8 @@ export default function makeBaseState (gcode, indexMax) { linesData: [], linesDataOffset: 0, linesDataStride: 18,// each chunk of data is 18 (9x2) long + //we prepare the storage for data + //we have 9 components : [g, x, y, z, e, f, s, t], times 2 extraObjects: {// these are extra Object3D elements added during // the gcode rendering to attach to scene @@ -104,9 +106,6 @@ export default function makeBaseState (gcode, indexMax) { children: [] } } - //we prepare the storage for data - //we have 9 components : [g, x, y, z, e, f, s, t], times 2 - state.linesData.push(new Float32Array(9 * state.bufSize * 2)) // we have been using an approach where we just append // each gcode move to one monolithic geometry. we From 241bbe94637c79b00e00d976bc39cfbea9086d43 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Thu, 24 Nov 2016 08:44:18 +0100 Subject: [PATCH 32/34] refactor(): minor tweaks --- src/gcodeHandlers.js | 3 +-- src/index.js | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/gcodeHandlers.js b/src/gcodeHandlers.js index f3d80a0..744d94e 100644 --- a/src/gcodeHandlers.js +++ b/src/gcodeHandlers.js @@ -242,8 +242,7 @@ export default function makeHandlers (params) { // No physical motion will occur. // TODO: Only support E0 - var newLine = state.lastLine - + let newLine = state.lastLine state.specifics.G92.offset.x = (args.x !== undefined ? (args.x === 0 ? newLine.x : newLine.x - args.x) : 0) state.specifics.G92.offset.y = (args.y !== undefined ? (args.y === 0 ? newLine.y : newLine.y - args.y) : 0) state.specifics.G92.offset.z = (args.z !== undefined ? (args.z === 0 ? newLine.z : newLine.z - args.z) : 0) diff --git a/src/index.js b/src/index.js index acd183e..e1ea48b 100644 --- a/src/index.js +++ b/src/index.js @@ -15,8 +15,6 @@ import makeBaseState from './makeBaseState' export default function parse (data, doneCallback) { // const params = Object.assign({}, machineDefaults, parameters) - console.log('Generating GCODE Preview') - const handlers = makeHandlers() let state = makeBaseState() From d080c77563255ff807211a5becedb3240d73249c Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Wed, 30 Nov 2016 16:42:37 +0100 Subject: [PATCH 33/34] refacto(): more cleanup, clutter removal --- src/geometries/segments.js | 3 +-- src/parseAsChunks.js | 42 +++----------------------------------- src/parseLine.js | 2 +- 3 files changed, 5 insertions(+), 42 deletions(-) diff --git a/src/geometries/segments.js b/src/geometries/segments.js index 6840d2f..2a9adc8 100644 --- a/src/geometries/segments.js +++ b/src/geometries/segments.js @@ -5,7 +5,7 @@ export function addSegment (state, args, p1, p2) { if (state.debug) { console.log('addSegment') } - closeLineSegment(state) + throw new Error('SEGMENT !!') let {bbox, bbox2} = state // console.log("") // console.log("addSegment p2:", p2) @@ -247,7 +247,6 @@ export function addFakeSegment (state, args) { // lineObject, lastLine, lines) { if (state.debug) { console.log('addFakeSegment') } - closeLineSegment(state) // line.args = args const arg2 = { isFake: true, diff --git a/src/parseAsChunks.js b/src/parseAsChunks.js index 8de61c9..2f1ffb7 100644 --- a/src/parseAsChunks.js +++ b/src/parseAsChunks.js @@ -19,8 +19,6 @@ export default function parseAsChunks (state, handlers, gcode, doneCallback) { parseLine(state, handlers, lines[index], index) ++index } - // closeLineSegment() //FIXME : add this back .??? or not - // console.log('done parsing ') if (index < count) { setTimeout(doChunk, 1) // set Timeout for async iteration @@ -30,45 +28,11 @@ export default function parseAsChunks (state, handlers, gcode, doneCallback) { // cleanup , resize data typedArray to match actual data size state.linesData = state.linesData.subarray(0, state.linesDataOffset) doneCallback(state) - } - } - - doChunk() -} -// "old" for reference -export function __parser (gcode, params, progressCallback, doneCallback) { - console.log('inside this.parse') - object = null - function doChunk () { - const progress = (index / count) - progressCallback(progress) - - let startTime = now() - while (index < count && (now() - startTime) <= maxTimePerChunk) { - // console.log('parsing ' + lines[index]) - parseLine(lines[index], index) - ++index - } - // closeLineSegment() //FIXME : add this back !! - - // console.log('done parsing ') - if (index < count) { - setTimeout(doChunk, 1) // set Timeout for async iteration - // console.log('[GCODE PARSE] ' + (index / count ) * 100 + "%") - } else { - doneCallback() - object = drawobject() - object.add(lineObjects) - // console.log('Line Objects', lineObjects) - object.translateX(laserxmax / 2 * -1) - object.translateY(laserymax / 2 * -1) - object.name = 'object' - console.log('adding to scene') - scene.add(object) + //TODO: deal with this ? + //object.translateX(laserxmax / 2 * -1) + //object.translateY(laserymax / 2 * -1) } } - - // start it doChunk() } diff --git a/src/parseLine.js b/src/parseLine.js index bd5d1c1..f4cf9ba 100644 --- a/src/parseLine.js +++ b/src/parseLine.js @@ -1,5 +1,5 @@ export default function parseLine (state, handlers, text, index) { - console.log('Parsing: ', text) + //console.log('Parsing: ', text) const origtext = text if (text.match(/^N/i)) { // remove line numbers if exist From 51aedf30394ad132a3267782bf071bd687f1e290 Mon Sep 17 00:00:00 2001 From: Mark 'kaosat-dev' Moissette Date: Wed, 30 Nov 2016 16:42:58 +0100 Subject: [PATCH 34/34] test(): added additional specs for different type of gcode --- test/gcodeParser.spec.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/gcodeParser.spec.js b/test/gcodeParser.spec.js index 897b2dc..6238f35 100644 --- a/test/gcodeParser.spec.js +++ b/test/gcodeParser.spec.js @@ -29,3 +29,12 @@ test.cb('gcode parser: can parse multi material 3d printer gcode', t => { t.end() }) }) + +test.cb('gcode parser: can parse multi material 3d printer gcode (variant2)', t => { + const gcode = fs.readFileSync('../node_modules/lw-sample-files/gcode/Slicer Dual Example File loubie_aria_resculpt_base_and_eyes_v1.1.gcode', 'utf8') + parse(gcode, function (data) { + console.log('done with parsing', data.metrics) + t.deepEqual(data.linesData.length, 3537558) + t.end() + }) +})