From 595c148565ce6c54f6842a99aa1d6b32eeb4b9fd Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sun, 26 Nov 2017 12:30:23 -0800 Subject: [PATCH 1/6] support for a status callback --- packages/stl-serializer/CSGToStla.js | 7 +++++-- packages/stl-serializer/index.js | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/stl-serializer/CSGToStla.js b/packages/stl-serializer/CSGToStla.js index 6f9da99..6c2552f 100644 --- a/packages/stl-serializer/CSGToStla.js +++ b/packages/stl-serializer/CSGToStla.js @@ -1,10 +1,13 @@ -function serialize (CSG) { +function serialize (CSG, options) { + options.statusCallback({percentage: 0}) var result = 'solid csg.js\n' - CSG.polygons.map(function (p) { + CSG.polygons.map(function (p, i) { result += CSGPolygontoStlString(p) + options.statusCallback({percentage: 100 * i / CSG.polygons.length}) }) result += 'endsolid csg.js\n' + options.statusCallback({percentage: 100}) return [result] } diff --git a/packages/stl-serializer/index.js b/packages/stl-serializer/index.js index b1f060c..2460213 100644 --- a/packages/stl-serializer/index.js +++ b/packages/stl-serializer/index.js @@ -6,7 +6,8 @@ const mimeType = 'application/sla' function serialize (data, options) { const defaults = { - binary: true + binary: true, + statusCallback: function (statusObject) { } } options = Object.assign({}, defaults, options) From 2c58ddb68339ce6fa8dea564963b60f1b3b562e1 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sun, 26 Nov 2017 15:42:04 -0800 Subject: [PATCH 2/6] remove no-op --- packages/stl-serializer/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/stl-serializer/index.js b/packages/stl-serializer/index.js index 2460213..b1f060c 100644 --- a/packages/stl-serializer/index.js +++ b/packages/stl-serializer/index.js @@ -6,8 +6,7 @@ const mimeType = 'application/sla' function serialize (data, options) { const defaults = { - binary: true, - statusCallback: function (statusObject) { } + binary: true } options = Object.assign({}, defaults, options) From 0c21f4f29d54a36152a4963a86356a79390c5ad6 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sun, 26 Nov 2017 15:43:58 -0800 Subject: [PATCH 3/6] rename to progress, check for existence of statusCallback --- packages/stl-serializer/CSGToStla.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/stl-serializer/CSGToStla.js b/packages/stl-serializer/CSGToStla.js index 6c2552f..5709b9c 100644 --- a/packages/stl-serializer/CSGToStla.js +++ b/packages/stl-serializer/CSGToStla.js @@ -1,13 +1,13 @@ function serialize (CSG, options) { - options.statusCallback({percentage: 0}) + options.statusCallback && options.statusCallback({progress: 0}) var result = 'solid csg.js\n' CSG.polygons.map(function (p, i) { result += CSGPolygontoStlString(p) - options.statusCallback({percentage: 100 * i / CSG.polygons.length}) + options.statusCallback && options.statusCallback({progress: 100 * i / CSG.polygons.length}) }) result += 'endsolid csg.js\n' - options.statusCallback({percentage: 100}) + options.statusCallback && options.statusCallback({progress: 100}) return [result] } From b5fb58bc0138c4b057a23bcbd098d68787f7b171 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sun, 26 Nov 2017 16:44:48 -0800 Subject: [PATCH 4/6] added statusCallback to all serializers --- packages/amf-serializer/index.js | 9 +++++++-- packages/dxf-serializer/index.js | 11 +++++++---- packages/json-serializer/index.js | 15 ++++++++++----- packages/stl-serializer/CSGToStla.js | 6 +++--- packages/stl-serializer/CSGToStlb.js | 7 +++++-- packages/svg-serializer/index.js | 10 +++++++--- packages/x3d-serializer/index.js | 7 +++++-- 7 files changed, 44 insertions(+), 21 deletions(-) diff --git a/packages/amf-serializer/index.js b/packages/amf-serializer/index.js index 39da476..50ed867 100644 --- a/packages/amf-serializer/index.js +++ b/packages/amf-serializer/index.js @@ -1,7 +1,8 @@ const { ensureManifoldness } = require('@jscad/io-utils') const mimeType = 'application/amf+xml' -function serialize (CSG, m) { +function serialize (CSG, m, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) CSG = ensureManifoldness(CSG) var result = '\n\n' for (var k in m) { @@ -17,7 +18,7 @@ function serialize (CSG, m) { result += '\n' var n = 0 - CSG.polygons.map(function (p) { // then we dump all polygons + CSG.polygons.map(function (p, i) { // then we dump all polygons result += '\n' if (p.vertices.length < 3) { return @@ -42,9 +43,13 @@ function serialize (CSG, m) { } n += p.vertices.length result += '\n' + options && options.statusCallback && options.statusCallback({progress: 100 * i / CSG.polygons.length}) }) result += '\n\n' result += '\n' + + options && options.statusCallback && options.statusCallback({progress: 100}) + return [result] } diff --git a/packages/dxf-serializer/index.js b/packages/dxf-serializer/index.js index 8b540b0..80da74e 100644 --- a/packages/dxf-serializer/index.js +++ b/packages/dxf-serializer/index.js @@ -1,11 +1,12 @@ const mimeType = 'application/dxf' -function serialize (cagObject) { +function serialize (cagObject, options) { var paths = cagObject.getOutlinePaths() - return PathsToDxf(paths) + return PathsToDxf(paths, options) } -function PathsToDxf (paths) { +function PathsToDxf (paths, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) var str = '999\nDXF generated by OpenJsCad\n' str += ' 0\nSECTION\n 2\nHEADER\n' str += ' 0\nENDSEC\n' @@ -22,7 +23,7 @@ function PathsToDxf (paths) { str += ' 0\nSECTION\n 2\nBLOCKS\n' str += ' 0\nENDSEC\n' str += ' 0\nSECTION\n 2\nENTITIES\n' - paths.map(function (path) { + paths.map(function (path, i) { var numpointsClosed = path.points.length + (path.closed ? 1 : 0) str += ' 0\nLWPOLYLINE\n 8\nOpenJsCad\n 90\n' + numpointsClosed + '\n 70\n' + (path.closed ? 1 : 0) + '\n' for (var pointindex = 0; pointindex < numpointsClosed; pointindex++) { @@ -31,8 +32,10 @@ function PathsToDxf (paths) { var point = path.points[pointindexwrapped] str += ' 10\n' + point.x + '\n 20\n' + point.y + '\n 30\n0.0\n' } + options && options.statusCallback && options.statusCallback({progress: 100 * i / paths.length}) }) str += ' 0\nENDSEC\n 0\nEOF\n' + options && options.statusCallback && options.statusCallback({progress: 100}) return [str] } diff --git a/packages/json-serializer/index.js b/packages/json-serializer/index.js index a298e9f..ec10da5 100644 --- a/packages/json-serializer/index.js +++ b/packages/json-serializer/index.js @@ -2,28 +2,30 @@ const { ensureManifoldness } = require('@jscad/io-utils') const mimeType = 'application/json' -function fromCAG (CAG) { +function fromCAG (CAG, options) { let str = '{ "type": "cag","sides": [' let comma = '' CAG.sides.map( - function (side) { + function (side, i) { str += comma str += JSON.stringify(side) comma = ',' + options && options.statusCallback && options.statusCallback({progress: 100 * i / CAG.sides.length}) } ) str += '] }' return [str] } -function fromCSG (CSG) { +function fromCSG (CSG, options) { let str = '{ "type": "csg","polygons": [' let comma = '' CSG.polygons.map( - function (polygon) { + function (polygon, i) { str += comma str += JSON.stringify(polygon) comma = ',' + options && options.statusCallback && options.statusCallback({progress: 100 * i / CSG.polygons.length}) } ) str += '],' @@ -34,7 +36,10 @@ function fromCSG (CSG) { } function serialize (data, options) { - return 'sides' in data ? fromCAG(data) : fromCSG(ensureManifoldness(data)) + options && options.statusCallback && options.statusCallback({progress: 0}) + const result = 'sides' in data ? fromCAG(data, options) : fromCSG(ensureManifoldness(data), options) + options && options.statusCallback && options.statusCallback({progress: 100}) + return result } module.exports = { diff --git a/packages/stl-serializer/CSGToStla.js b/packages/stl-serializer/CSGToStla.js index 5709b9c..d4fb24e 100644 --- a/packages/stl-serializer/CSGToStla.js +++ b/packages/stl-serializer/CSGToStla.js @@ -1,13 +1,13 @@ function serialize (CSG, options) { - options.statusCallback && options.statusCallback({progress: 0}) + options && options.statusCallback && options.statusCallback({progress: 0}) var result = 'solid csg.js\n' CSG.polygons.map(function (p, i) { result += CSGPolygontoStlString(p) - options.statusCallback && options.statusCallback({progress: 100 * i / CSG.polygons.length}) + options && options.statusCallback && options.statusCallback({progress: 100 * i / CSG.polygons.length}) }) result += 'endsolid csg.js\n' - options.statusCallback && options.statusCallback({progress: 100}) + options && options.statusCallback && options.statusCallback({progress: 100}) return [result] } diff --git a/packages/stl-serializer/CSGToStlb.js b/packages/stl-serializer/CSGToStlb.js index c82146f..470138f 100644 --- a/packages/stl-serializer/CSGToStlb.js +++ b/packages/stl-serializer/CSGToStlb.js @@ -1,6 +1,7 @@ // see http://en.wikipedia.org/wiki/STL_%28file_format%29#Binary_STL -function serialize (CSG) { +function serialize (CSG, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) // first check if the host is little-endian: var buffer = new ArrayBuffer(4) var int32buffer = new Int32Array(buffer, 0, 1) @@ -35,7 +36,7 @@ function serialize (CSG) { // and one uint16: var triangleUint16array = new Uint16Array(triangleBuffer, 48, 1) var byteoffset = 0 - CSG.polygons.map(function (p) { + CSG.polygons.map(function (p, i) { var numvertices = p.vertices.length for (var i = 0; i < numvertices - 2; i++) { var normal = p.plane.normal @@ -55,7 +56,9 @@ function serialize (CSG) { allTrianglesBufferAsInt8.set(triangleBufferAsInt8, byteoffset) byteoffset += 50 } + options && options.statusCallback && options.statusCallback({progress: 100 * i / CSG.polygons.length}) }) + options && options.statusCallback && options.statusCallback({progress: 100}) return [headerarray.buffer, ar1.buffer, allTrianglesBuffer]// 'blobable array' /* return new Blob([headerarray.buffer, ar1.buffer, allTrianglesBuffer], { type: mimeType diff --git a/packages/svg-serializer/index.js b/packages/svg-serializer/index.js index d197169..06bfebf 100644 --- a/packages/svg-serializer/index.js +++ b/packages/svg-serializer/index.js @@ -21,17 +21,19 @@ function dPath (path, xoffset, yoffset) { return str } -function PathsToSvg (paths, bounds) { +function PathsToSvg (paths, bounds, options) { // calculate offsets in order to create paths orientated from the 0,0 axis var xoffset = 0 - bounds[0].x var yoffset = 0 - bounds[0].y - return paths.reduce(function (res, path) { + return paths.reduce(function (res, path, i) { + options && options.statusCallback && options.statusCallback({progress: 100 * i / paths.length}) return res.concat([['path', {d: dPath(path, xoffset, yoffset)}]]) }, ['g']) } -function serialize (cagObject) { +function serialize (cagObject, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) var decimals = 1000 // mirror the CAG about the X axis in order to generate paths into the POSITIVE direction @@ -60,6 +62,8 @@ function serialize (cagObject) { svg += '\n' svg += '\n' svg += stringify(body) + + options && options.statusCallback && options.statusCallback({progress: 100}) return svg } diff --git a/packages/x3d-serializer/index.js b/packages/x3d-serializer/index.js index f118721..f60dcaa 100644 --- a/packages/x3d-serializer/index.js +++ b/packages/x3d-serializer/index.js @@ -7,7 +7,8 @@ const mimeType = 'model/x3d+xml' const XMLSerializer = xmldom.XMLSerializer // NOTE: might be useful :https://github.com/jindw/xmldom/pull/152/commits/be5176ece6fa1591daef96a5f361aaacaa445175 -function serialize (CSG) { +function serialize (CSG, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) CSG = ensureManifoldness(CSG) const DOMImplementation = typeof document !== 'undefined' ? document.implementation : new xmldom.DOMImplementation() // materialPolygonLists @@ -20,7 +21,7 @@ function serialize (CSG) { // map to look up the index in vertexCoords of a given vertex var vertexTagToCoordIndexMap = {} - CSG.polygons.map(function (p) { + CSG.polygons.map(function (p, i) { var red = 0 var green = 0 var blue = 1 // default color is blue @@ -53,6 +54,7 @@ function serialize (CSG) { } // add this polygonString to the list of colorString-colored polygons materialPolygonLists[colorString].push(polygonString) + options && options.statusCallback && options.statusCallback({progress: 100 * i / CSG.polygons.length}) }) // create output document @@ -111,6 +113,7 @@ function serialize (CSG) { } const x3dstring = (new XMLSerializer()).serializeToString(exportDoc) + options && options.statusCallback && options.statusCallback({progress: 100}) return [x3dstring] } From 004471875fe9396ff53fd3937e9f0f123ba33f90 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sun, 26 Nov 2017 19:32:58 -0800 Subject: [PATCH 5/6] add status callbacks to deserializers --- packages/amf-deserializer/translate.js | 6 ++++++ packages/gcode-deserializer/index.js | 4 ++++ packages/json-deserializer/index.js | 3 +++ packages/obj-deserializer/index.js | 10 +++++++--- packages/stl-deserializer/index.js | 10 +++++++++- packages/svg-deserializer/index.js | 12 +++++++++++- 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/packages/amf-deserializer/translate.js b/packages/amf-deserializer/translate.js index 3dee750..dfba227 100644 --- a/packages/amf-deserializer/translate.js +++ b/packages/amf-deserializer/translate.js @@ -2,6 +2,7 @@ const createObject = require('./objectBuilder') const parse = require('./parse') const translate = function (src, filename, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) filename = filename || 'amf' const defaults = {pxPmm: require('./constants').pxPmm, version: '0.0.0', addMetaData: true} options = Object.assign({}, defaults, options) @@ -20,8 +21,13 @@ const translate = function (src, filename, options) { if (!amfObj) { throw new Error('AMF parsing failed, no valid AMF data retrieved') } + + options && options.statusCallback && options.statusCallback({progress: 50}) + const scadCode = codify(amfObj, {amfMaterials, amfTextures, amfConstels}) code += scadCode + + options && options.statusCallback && options.statusCallback({progress: 100}) return code } diff --git a/packages/gcode-deserializer/index.js b/packages/gcode-deserializer/index.js index f2891bd..2d0c5ad 100644 --- a/packages/gcode-deserializer/index.js +++ b/packages/gcode-deserializer/index.js @@ -1,5 +1,6 @@ function deserialize (gcode, filename, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) // http://reprap.org/wiki/G-code const defaults = {version: '0.0.0', addMetaData: true, output: 'jscad'} options = Object.assign({}, defaults, options) @@ -83,6 +84,7 @@ function deserialize (gcode, filename, options) { lpos.E = pos.E } ld = d + options && options.statusCallback && options.statusCallback({progress: 100 * i / l.length}) } let code = addMetaData ? `// @@ -99,6 +101,8 @@ function deserialize (gcode, filename, options) { ` // if(err) src += "// WARNING: import errors: "+err+" (some triangles might be misaligned or missing)\n"; + options && options.statusCallback && options.statusCallback({progress: 100}) + return code } diff --git a/packages/json-deserializer/index.js b/packages/json-deserializer/index.js index df0d604..6ab1176 100644 --- a/packages/json-deserializer/index.js +++ b/packages/json-deserializer/index.js @@ -82,6 +82,7 @@ function toSource (obj) { // fn (optional) original filename of JSON source // function deserialize (src, fn, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) fn = fn || 'amf' const defaults = {version: '0.0.0'} options = Object.assign({}, defaults, options) @@ -89,6 +90,7 @@ function deserialize (src, fn, options) { // convert the JSON into an anonymous object var obj = JSON.parse(src) + options && options.statusCallback && options.statusCallback({progress: 50}) // convert the internal objects to JSCAD code var code = '' code += '//\n' @@ -99,6 +101,7 @@ function deserialize (src, fn, options) { code += 'function main() {\n' code += toSource(obj) code += '};\n' + options && options.statusCallback && options.statusCallback({progress: 100}) return code }; diff --git a/packages/obj-deserializer/index.js b/packages/obj-deserializer/index.js index 505858d..d8d1c59 100644 --- a/packages/obj-deserializer/index.js +++ b/packages/obj-deserializer/index.js @@ -12,15 +12,18 @@ const {CSG} = require('@jscad/csg') * @return {CSG/string} either a CAG/CSG object or a string (jscad script) */ function deserialize (input, filename, options) { // http://en.wikipedia.org/wiki/Wavefront_.obj_file + options && options.statusCallback && options.statusCallback({progress: 0}) const defaults = {version: '0.0.0', addMetaData: true, output: 'jscad'} options = Object.assign({}, defaults, options) const {output} = options - const {positions, faces} = getPositionsAndFaces(input) - return output === 'jscad' ? stringify({positions, faces, options}) : objectify({positions, faces, options}) + const {positions, faces} = getPositionsAndFaces(input, options) + const result = output === 'jscad' ? stringify({positions, faces, options}) : objectify({positions, faces, options}) + options && options.statusCallback && options.statusCallback({progress: 100}) + return result } -const getPositionsAndFaces = data => { +const getPositionsAndFaces = (data, options) => { let lines = data.split(/\n/) let positions = [] let faces = [] @@ -53,6 +56,7 @@ const getPositionsAndFaces = data => { } else { // vn vt and all others disregarded } + options && options.statusCallback && options.statusCallback({progress: 90 * i / lines.length}) //getPositionsAndFaces is 90% of total } return {positions, faces} } diff --git a/packages/stl-deserializer/index.js b/packages/stl-deserializer/index.js index 2bac7a1..5435b68 100644 --- a/packages/stl-deserializer/index.js +++ b/packages/stl-deserializer/index.js @@ -22,6 +22,7 @@ const echo = console.info * @return {CSG/string} either a CAG/CSG object or a string (jscad script) */ function deserialize (stl, filename, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) const defaults = {version: '0.0.0', addMetaData: true, output: 'jscad'} options = Object.assign({}, defaults, options) const {version, output, addMetaData} = options @@ -30,14 +31,21 @@ function deserialize (stl, filename, options) { stl = isBinary && isBuffer(stl) ? bufferToBinaryString(stl) : stl + options && options.statusCallback && options.statusCallback({progress: 33}) + const elementFormatterJscad = ({vertices, triangles, normals, colors, index}) => `// object #${index}: triangles: ${triangles.length}\n${vt2jscad(vertices, triangles, null)}` const elementFormatterCSG = ({vertices, triangles, normals, colors}) => polyhedron({ points: vertices, polygons: triangles }) + options && options.statusCallback && options.statusCallback({progress: 66}) + const deserializer = isBinary ? deserializeBinarySTL : deserializeAsciiSTL const elementFormatter = output === 'jscad' ? elementFormatterJscad : elementFormatterCSG const outputFormatter = output === 'jscad' ? formatAsJscad : formatAsCsg - return outputFormatter(deserializer(stl, filename, version, elementFormatter), addMetaData, version, filename) + const result = outputFormatter(deserializer(stl, filename, version, elementFormatter), addMetaData, version, filename) + + options && options.statusCallback && options.statusCallback({progress: 100}) + return result /* if (err) src += '// WARNING: import errors: ' + err + ' (some triangles might be misaligned or missing)\n' diff --git a/packages/svg-deserializer/index.js b/packages/svg-deserializer/index.js index 41611f6..986c0e4 100644 --- a/packages/svg-deserializer/index.js +++ b/packages/svg-deserializer/index.js @@ -49,6 +49,7 @@ const deserialize = function (input, filename, options) { * @return a CAG (2D CSG) object */ function deserializeToCSG (src, filename, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) filename = filename || 'svg' const defaults = {pxPmm: require('./constants').pxPmm, version: '0.0.0', addMetaData: true} options = Object.assign({}, defaults, options) @@ -60,7 +61,12 @@ function deserializeToCSG (src, filename, options) { throw new Error('SVG parsing failed, no valid svg data retrieved') } - return objectify(svgObj) + options && options.statusCallback && options.statusCallback({progress: 50}) + + const result = objectify(svgObj) + + options && options.statusCallback && options.statusCallback({progress: 100}) + return result } /** @@ -75,6 +81,7 @@ function deserializeToCSG (src, filename, options) { * @return a CAG (2D CSG) object */ function translate (src, filename, options) { + options && options.statusCallback && options.statusCallback({progress: 0}) filename = filename || 'svg' const defaults = {pxPmm: require('./constants').pxPmm, version: '0.0.0', addMetaData: true} options = Object.assign({}, defaults, options) @@ -94,9 +101,12 @@ function translate (src, filename, options) { throw new Error('SVG parsing failed, no valid svg data retrieved') } + options && options.statusCallback && options.statusCallback({progress: 50}) + const scadCode = codify(svgObj) code += scadCode + options && options.statusCallback && options.statusCallback({progress: 100}) return code } From 9d41240d303f3c2a0c7aeccef73e81e740a4a522 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Tue, 28 Nov 2017 22:48:37 -0800 Subject: [PATCH 6/6] added test for progress status callback --- packages/stl-serializer/test.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/stl-serializer/test.js b/packages/stl-serializer/test.js index 035ebe8..1986924 100644 --- a/packages/stl-serializer/test.js +++ b/packages/stl-serializer/test.js @@ -5,7 +5,7 @@ const serializer = require('./index.js') test('serialize csg to stl (binary)', function (t) { const input = new CSG.cube() const observed = serializer.serialize(input, {binary: true}) - + // TODO: VERY shallow testing ... improve t.deepEqual(observed[0].byteLength, 80) t.deepEqual(observed[1].byteLength, 4) @@ -18,3 +18,15 @@ test('serialize csg to stl (ascii)', function (t) { const observed = serializer.serialize(input, {binary: false}) t.deepEqual(observed, expected) }) + +test('progress status callback', function (t) { + const input = new CSG.cube() + const progresses = []; + const statusCallback = function (statusObj) { + progresses.push(statusObj.progress); + }; + const observed = serializer.serialize(input, {statusCallback: statusCallback}) + + t.deepEqual(0, progresses[0]); + t.deepEqual(100, progresses[progresses.length - 1]); +})