From 9b73fc55263ecbc233427ab1e9dd96f0fbd36e3a Mon Sep 17 00:00:00 2001 From: openbuilds-engineer Date: Mon, 1 Jul 2019 21:52:29 +0200 Subject: [PATCH] Toolpath Webworkers --- CHANGELOG.txt | 1 + index.html | 12 +- js/advanced-cam-gcode.js | 33 +- js/advanced-cam-geometryutils.js | 22 +- js/advanced-cam-modal.js | 2 +- js/advanced-cam-preview.js | 194 --- js/advanced-cam-threegcode.js | 985 ------------- js/advanced-cam-tree.js | 4 +- js/advanced-cam-viewer-mouse.js | 4 +- js/advanced-cam-viewer-select.js | 19 +- js/advanced-cam-workspace-export.js | 13 +- js/basic-cad-helloworld.js | 30 +- js/viewer-pause.js | 2 +- js/viewer.js | 4 +- lib/3dview/workers/litegcodeviewer.js | 2 +- lib/svgreader/SVGReader.js | 1286 ----------------- lib/svgreader/svg2three.js | 216 --- lib/svgreader/vec2.js | 294 ---- workers/toolpath/toolpath.js | 160 +- workers/toolpath/worker/toolpathworker.js | 812 +++++++++-- workspace/helloworld.json-old | 1 - workspace/{helloworld.json => helloworld.obc} | 0 workspace/helloworlddragknife.obc | 1 + ...lloworldlaser.json => helloworldlaser.obc} | 0 workspace/helloworldplasma.obc | 1 + 25 files changed, 901 insertions(+), 3197 deletions(-) delete mode 100644 js/advanced-cam-preview.js delete mode 100644 js/advanced-cam-threegcode.js delete mode 100644 lib/svgreader/SVGReader.js delete mode 100644 lib/svgreader/svg2three.js delete mode 100644 lib/svgreader/vec2.js delete mode 100644 workspace/helloworld.json-old rename workspace/{helloworld.json => helloworld.obc} (100%) create mode 100644 workspace/helloworlddragknife.obc rename workspace/{helloworldlaser.json => helloworldlaser.obc} (100%) create mode 100644 workspace/helloworldplasma.obc diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8c04109b..cf3d1c12 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,4 @@ +01 Jul 2019: Moved Toolpath Calculation to WebWorkers 24 Jun 2019: Moved Gcode Preview to WebWorker 14 Jun 2019: Added Beta of Servo based Pen Plotter CAM 29 Apr 2019: Added Delete Selection button #49, Added Workspace and Gcode naming #51, Added .OBC file support via CONTROL diff --git a/index.html b/index.html index 2cfa54f9..15445154 100644 --- a/index.html +++ b/index.html @@ -73,7 +73,8 @@
  • Import from Parts Library
  • @@ -638,7 +639,6 @@
    Calculating Toolpaths...
    - @@ -646,7 +646,6 @@
    Calculating Toolpaths...
    - @@ -657,9 +656,6 @@
    Calculating Toolpaths...
    - - - @@ -669,10 +665,6 @@
    Calculating Toolpaths...
    - - diff --git a/js/advanced-cam-gcode.js b/js/advanced-cam-gcode.js index e439670f..ee1ebf70 100644 --- a/js/advanced-cam-gcode.js +++ b/js/advanced-cam-gcode.js @@ -13,8 +13,17 @@ function trashGcode() { $('#trashicon').removeClass('fg-red').addClass('fg-gray'); } - function makeGcode() { + if (toolpathWorkersBusy()) { + // console.log('not yet... rescheduling') + setTimeout(function(){makeGcode()}, 500); + } else { + makeGcodeExec() + } +} + + +function makeGcodeExec() { if (toolpathsInScene.length > 0) { @@ -90,7 +99,7 @@ function makeGcode() { // openGCodeFromText() parseGcodeInWebWorker() - + }, 100); } else { @@ -149,13 +158,19 @@ function generateGcode(index, toolpathGrp, cutSpeed, plungeSpeed, laserPwr, rapi // Find longest segment // console.log("Vertices before optimise: ", child.geometry.vertices) if (child.geometry.vertices.length > 2) { - var bestSegment = indexOfMax(child.geometry.vertices) - // console.log('longest section' + bestSegment) - var clone = child.geometry.vertices.slice(0); - clone.splice(-1, 1) // remove the last point (as its the "go back to first point"-point which will just be a duplicate point after rotation) - var optimisedVertices = clone.rotateRight(bestSegment) - optimisedVertices.push(optimisedVertices[0]) // add back the "go back to first point"-point - from the new first point - // console.log("Vertices after optimise: ", optimisedVertices) + if (toolpathsInScene[j].userData.camOperation.indexOf('Plasma') != 0) { + var bestSegment = indexOfMax(child.geometry.vertices) + // console.log('longest section' + bestSegment) + var clone = child.geometry.vertices.slice(0); + clone.splice(-1, 1) // remove the last point (as its the "go back to first point"-point which will just be a duplicate point after rotation) + var optimisedVertices = clone.rotateRight(bestSegment) + optimisedVertices.push(optimisedVertices[0]) // add back the "go back to first point"-point - from the new first point + // console.log("Vertices after optimise: ", optimisedVertices) + } else { + var optimisedVertices = child.geometry.vertices.slice(0) + } + + } else { var optimisedVertices = child.geometry.vertices.slice(0) } diff --git a/js/advanced-cam-geometryutils.js b/js/advanced-cam-geometryutils.js index 98ef83c4..0e9e929e 100644 --- a/js/advanced-cam-geometryutils.js +++ b/js/advanced-cam-geometryutils.js @@ -117,4 +117,24 @@ Array.prototype.rotateRight = function(n) { // example rotation // var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; // months.rotateRight( 6 ) -// console.log(months) \ No newline at end of file +// console.log(months) + +// borrowed tab generator code from https://github.com/andrewhodel/millcrum/blob/master/inc/mc.js +distanceFormula = function(x1, x2, y1, y2) { + // get the distance between p1 and p2 + var a = (x2 - x1) * (x2 - x1); + var b = (y2 - y1) * (y2 - y1); + return Math.sqrt(a + b); +}; + +newPointFromDistanceAndAngle = function(pt, ang, distance) { + // use cos and sin to get a new point with an angle + // and distance from an existing point + // pt = [x,y] + // ang = in degrees + // distance = N + var r = []; + r.push(pt[0] + (distance * Math.cos(ang * Math.PI / 180))); + r.push(pt[1] + (distance * Math.sin(ang * Math.PI / 180))); + return r; +}; diff --git a/js/advanced-cam-modal.js b/js/advanced-cam-modal.js index c98e3a1c..0d22b798 100644 --- a/js/advanced-cam-modal.js +++ b/js/advanced-cam-modal.js @@ -325,7 +325,7 @@ function setupJob(i) {
    - + mm
    diff --git a/js/advanced-cam-preview.js b/js/advanced-cam-preview.js deleted file mode 100644 index 508ea5af..00000000 --- a/js/advanced-cam-preview.js +++ /dev/null @@ -1,194 +0,0 @@ -var runningPreviews = 0; - -function toolpathPreview(i) { - $('#toolpathtree').hide(); - $('#toolpathactivity').show() - trashGcode(); - $('#gcodesavebtn2').addClass('disabled'); - $('#gcodetrashbtn2').addClass('disabled'); - $('#gcodeexporticon').removeClass('fg-grayBlue').addClass('fg-gray'); - $('#trashicon').removeClass('fg-red').addClass('fg-gray'); - - - $('#validGcode').html(" No GCODE yet") - $("#savetpgcode").addClass("disabled"); - $("#exportGcodeMenu").addClass("disabled"); - $("#previewToolpathBtn").html(" Calculating, please wait"); - $("#previewToolpathBtn").prop('disabled', true); - setTimeout(function() { - runningPreviews++ - toolpathPreviewExec(i); - }, 200); -} - -function toolpathPreviewExec(i) { - var operation = toolpathsInScene[i].userData.camOperation - var ToolDia = toolpathsInScene[i].userData.camToolDia - var ZClearance = toolpathsInScene[i].userData.camZClearance - var ZStart = toolpathsInScene[i].userData.camZStart - var DragOffset = toolpathsInScene[i].userData.camDragOffset - var LaserPower = toolpathsInScene[i].userData.camLaserPower - var DragOffset = toolpathsInScene[i].userData.camDragOffset - var Feedrate = toolpathsInScene[i].userData.camFeedrate - var LaserPower = toolpathsInScene[i].userData.camLaserPower - var Operation = toolpathsInScene[i].userData.camOperation - var PlasmaIHS = toolpathsInScene[i].userData.camPlasmaIHS - var PlasmaKerf = toolpathsInScene[i].userData.camPlasmaKerf - var PlasmaZHeight = toolpathsInScene[i].userData.camPlasmaZHeight - var Plungerate = toolpathsInScene[i].userData.camPlungerate - var ToolDia = toolpathsInScene[i].userData.camToolDia - var VAngle = toolpathsInScene[i].userData.camVAngle - var VHeight = toolpathsInScene[i].userData.camVHeight - var ZClearance = toolpathsInScene[i].userData.camZClearance - var ZDepth = toolpathsInScene[i].userData.camZDepth - var ZStep = toolpathsInScene[i].userData.camZStep - var SpotSize = toolpathsInScene[i].userData.camSpotSize - var union = toolpathsInScene[i].userData.camUnion - var direction = toolpathsInScene[i].userData.camDirection - var StepOver = toolpathsInScene[i].userData.camStepover - var tabdepth = -(parseFloat(toolpathsInScene[i].userData.camZDepth) - parseFloat(toolpathsInScene[i].userData.camTabDepth)); - var tabspace = parseFloat(toolpathsInScene[i].userData.camTabSpace); - var tabwidth = parseFloat(toolpathsInScene[i].userData.camTabWidth); - var penupval = parseFloat(toolpathsInScene[i].userData.camPenUp); - var pendownval = parseFloat(toolpathsInScene[i].userData.camPenDown); - if (tabwidth < 1) { // set a sane minimum, tab can't be smaller than tooldia - tabwidth = 1 - } - - if (!operation) { - $('#toolpathtree').show(); - $('#toolpathactivity').hide() - runningPreviews-- - } else if (operation == "... Select Operation ...") { - // Do Nothing - console.log("NO OPERATION") - $('#toolpathtree').show(); - $('#toolpathactivity').hide() - toolpathErrorToast(`Toolpath Error: You did not select a valid "Type of Cut" for toolpath "` + toolpathsInScene[i].name + `" - Please Edit the toolpath and configure it"`, 'bg-red'); - runningPreviews-- - } else if (operation == "Laser: Vector (no path offset)") { // operation, index, offset, StepOver, zstep, zdepth, zstart, leadinval, tabdepth, tabspace, tabwidth, union - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, 0, StepOver, 1, 1, 0, false, false, false, false, union, direction); - } else if (operation == "Laser: Vector (path inside)") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, -(SpotSize / 2), 0, 1, 1, 0, false, false, false, false, union, direction); - } else if (operation == "Laser: Vector (path outside)") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, (SpotSize / 2), 0, 1, 1, 0, false, false, false, false, union, direction); - } else if (operation == "Laser: Vector (raster fill) (Beta)") { - toolpathsInScene[i].userData.inflated = getToolpath("fill", i, (SpotSize / 2), 0, 1, 1, 0, false, false, false, false, union, direction); - } else if (operation == "CNC: Vector (no offset)") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, 0, 0, ZStep, ZDepth, ZStart, false, tabdepth, tabspace, tabwidth, union, direction); - } else if (operation == "CNC: Vector (path inside)") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, -(ToolDia / 2), 0, ZStep, ZDepth, ZStart, false, tabdepth, tabspace, tabwidth, union, direction); - } else if (operation == "CNC: Vector (path outside)") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, (ToolDia / 2), 0, ZStep, ZDepth, ZStart, false, tabdepth, tabspace, tabwidth, union, direction); - } else if (operation == "CNC: Pocket") { - toolpathsInScene[i].userData.inflated = getToolpath("pocket", i, (ToolDia / 2), StepOver, ZStep, ZDepth, ZStart, false, false, false, false, union, direction); - } else if (operation == "CNC: V-Engrave") { - // no op yet - } else if (operation == "Plasma: Vector (path outside)") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, (PlasmaKerf / 2), 0, 1, 1, 0, (PlasmaKerf / 2), false, false, false, union, direction); - } else if (operation == "Plasma: Vector (path inside)") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, -(PlasmaKerf / 2), 0, 1, 1, 0, (PlasmaKerf / 2), false, false, false, union, direction); - } else if (operation == "Plasma: Mark") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, 0, 0, 1, 1, 0, false, false, false, false, union, direction); - } else if (operation == "Plasma: Vector (no path offset)") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, 0, 0, 1, 1, 0, false, false, false, false, union, direction); - } else if (operation == "Drag Knife: Cutout") { - toolpathsInScene[i].userData.inflated = getToolpath("dragknife", i, DragOffset, 0, 1, 1, 0, false, false, false, false, union, direction); - } else if (operation == "Drill: Peck (Centered)") { - toolpathsInScene[i].userData.inflated = getToolpath("peckdrill", i, (ToolDia / 2), 0, ZStep, ZDepth, 0, false, false, false, false, union, direction); - } else if (operation == "Drill: Continuous (Centered)") { - toolpathsInScene[i].userData.inflated = getToolpath("drill", i, (ToolDia / 2), 0, 0, ZDepth, 0, false, false, false, false, union, direction); - } else if (operation == "Pen Plotter") { - toolpathsInScene[i].userData.inflated = getToolpath("inflate", i, 0, 0, 1, 1, 0, false, false, false, false, union, direction); - } - - Metro.dialog.close('#statusmodal') - fillTree() - clearSceneFlag = true; -} - -function getToolpath(operation, index, offset, StepOver, zstep, zdepth, zstart, leadinval, tabdepth, tabspace, tabwidth, union, direction) { - var depth = zdepth - zstart; - if (zstep > depth) { - console.log("Could not generate " + operation + " toolpath for " + toolpathsInScene[index].name + ": You cannot have Cut Depth: Per Pass, larger than Cut Depth: Final") - printLog("Could not generate toolpath for " + toolpathsInScene[index].name + ": You cannot have Cut Depth: Per Pass, larger than Cut Depth: Final", errorcolor, "viewer") - } - var config = { - toolpath: toolpathsInScene[index], - offset: parseFloat(offset, 3), - zstep: parseFloat(zstep, 2), - zdepth: parseFloat(zdepth, 2), - zstart: parseFloat(zstart, 2), - leadinval: parseFloat(leadinval, 2), - tabdepth: parseFloat(tabdepth, 2), - tabspace: parseFloat(tabspace, 2), - tabwidth: parseFloat(tabwidth, 2), - union: union, - direction: direction, - stepover: parseFloat(StepOver, 2) - } - if (operation == "inflate") { - var toolpath = inflatePath(config, toolpathsInScene[index], offset, zstep, zdepth, zstart, leadinval, tabdepth, union); - // console.log(toolpath) - } - if (operation == "pocket") { - var toolpath = pocketPath(config, toolpathsInScene[index], offset, StepOver, zstep, zdepth, zstart, union); - } - if (operation == "fill") { - var toolpath = fillPath(config); - } - if (operation == "dragknife") { - var toolpath = dragknifePath(config, toolpathsInScene[index], offset, zstep, zdepth); - } - - if (operation == "peckdrill") { - var toolpath = drill(config); - } - - if (operation == "drill") { - var toolpath = drill(config); - } - - if (operation == "plotter") { - // var toolpath = - console.log("MAKE PLOTTER PATH", index) - } - - if (toolpath) { - toolpath.userData.type = "toolpath"; - // lets check if we has success, if not, raise an error message - var errorcount = 0; - for (i = 0; i < toolpath.children.length; i++) { - var checkpath = toolpath.children[i] - if (checkpath.children.length < 1) { - errorcount++ - } - } - if (errorcount > 0) { - toolpathErrorToast('Toolpath Warning: Please check the Toolpath result, we encountered some processing errors with either your file, or the parameters you entered', 'bg-amber'); - } - if (toolpath.children.length < 1) { - toolpathErrorToast('Toolpath Warning: Please check the Toolpath result, we encountered some processing errors with either your file, or the parameters you entered', 'bg-amber'); - } - runningPreviews-- - - if (runningPreviews == 0) { - $('#toolpathactivity').hide() - $('#toolpathtree').fadeIn(); - } - return toolpath - } - if (runningPreviews == 0) { - $('#toolpathactivity').hide() - $('#toolpathtree').fadeIn(); - } -} - -function toolpathErrorToast(data, background) { - if (data) { - var message = data; - } else { - var message = `Toolpath Warning: ` + data + ` We encountered some errors while processing the toolpath: Some elements may have been skipped. Either the file you are using has some issues, or the Toolpath settings you provided is wrong / won't work with the particular file / operation.` - } - Metro.toast.create(message, null, 10000, background); -} \ No newline at end of file diff --git a/js/advanced-cam-threegcode.js b/js/advanced-cam-threegcode.js deleted file mode 100644 index 9d84b50f..00000000 --- a/js/advanced-cam-threegcode.js +++ /dev/null @@ -1,985 +0,0 @@ -/* - AUTHOR: Peter van der Walt - Based on code from: John Lauer, Todd Fleming, Nicholas Raynaud and others -*/ - -//todo: tabs: constrain tabwidth > tooldia+saneminimum -// constrain tab tooldia > 0 (0= will loop forever) - -var repair = false; // needs a lot more math thinking - just playing - -var inflateGrp, fileParentGroup, svgPath, y, shape, lines, line; -var options = {}; - -var insideCutsColor = 0x660000; -var outsideCutsColor = 0x000066; -var pocketColor = 0x006600; -var toolpathColor = 0x666600; - -var minimumToolDiaForPreview = 0.04; - -inflatePath = function(config) { //}, infobject, inflateVal, zstep, zdepth, zstart, leadinval, tabdepth, union) { - // console.log(config) - var inflateGrpZ = new THREE.Group(); - var prettyGrp = new THREE.Group(); - var clipperPaths = getClipperPaths(config.toolpath) - if (repair) { - clipperPaths = repairClipperPath(clipperPaths); - } - // console.log('Original Toolpath: ', JSON.stringify(clipperPaths)) - if (config.union == "Yes") { - // simplify this set of paths which is a very powerful Clipper call that figures out holes and path orientations - var newClipperPaths = simplifyPolygons(clipperPaths); - if (newClipperPaths.length < 1) { - console.error("Clipper Simplification Failed!:"); - toolpathErrorToast(`Toolpath Error: Clipper Simplification Failed! for toolpath "` + config.toolpath.name + `" - this indicates some problem with the geometry coming from the original document"`, 'bg-red'); - } - if (config.offset != 0) { - var inflatedPaths = getInflatePath(newClipperPaths, config.offset); - } else { - var inflatedPaths = newClipperPaths; - } - if (config.direction == "Climb") { - // reverse here - if (config.offset > 0) { - for (i = 0; i < inflatedPaths.length; i++) { - inflatedPaths[i].reverse(); - } - } - } else if (config.direction == "Conventional") { - if (config.offset < 0) { - for (i = 0; i < inflatedPaths.length; i++) { - inflatedPaths[i].reverse(); - } - } - } - // console.log(inflatedPaths); - if (config.leadinval > 0) { // plasma lead-in - var leadInPaths = getInflatePath(newClipperPaths, config.offset * 3); - } - for (i = config.zstart + config.zstep; i < config.zdepth + config.zstep; i += config.zstep) { - if (i > config.zdepth) { - var zval = -config.zdepth; - } else { - var zval = -i - } - // console.log(i * config.zstep > config.zdepth, i * config.zstep, i, zval) - // console.log(i, config.zstart, config.zstep, config.zdepth, zval); - var drawClipperPathsconfig = { - paths: inflatedPaths, - color: toolpathColor, - opacity: 0.8, - z: zval, - isClosed: true, - name: 'inflateGrp', - leadInPaths: leadInPaths, - tabdepth: config.tabdepth, - tabspace: config.tabspace, - tabwidth: config.tabwidth, - toolDia: config.offset * 2, - drawPretty: true, - prettyGrpColor: (config.offset < 0) ? insideCutsColor : outsideCutsColor - } - var drawings = drawClipperPathsWithTool(drawClipperPathsconfig); - inflateGrp = drawings.lines; - inflateGrp.name = 'inflateGrp' + i; - inflateGrp.userData.material = inflateGrp.material; - inflateGrpZ.add(inflateGrp); - if (drawings.pretty) { - prettyGrp.add(drawings.pretty) - } - } - } else { - var newClipperPaths = clipperPaths; - for (j = 0; j < newClipperPaths.length; j++) { - if (config.offset != 0) { - var inflatedPaths = getInflatePath([newClipperPaths[j]], config.offset); - } else { - var inflatedPaths = [newClipperPaths[j]]; - } - if (config.direction == "Climb") { - // reverse here - if (config.offset > 0) { - for (i = 0; i < inflatedPaths.length; i++) { - inflatedPaths[i].reverse(); - } - } - } else if (config.direction == "Conventional") { - if (config.offset < 0) { - for (i = 0; i < inflatedPaths.length; i++) { - inflatedPaths[i].reverse(); - } - } - } - if (inflatedPaths.length < 1) { - console.error("Clipper Inflate Failed!:"); - toolpathErrorToast(`Toolpath Error: Clipper Simplification Failed! for toolpath "` + config.toolpath.name + `" - this indicates some problem with the geometry coming from the original document"`, 'bg-red'); - } - // plasma lead-in - if (config.leadinval > 0) { - var leadInPaths = getInflatePath([newClipperPaths[j]], config.offset * 3); - } - for (i = config.zstart + config.zstep; i < config.zdepth + config.zstep; i += config.zstep) { - if (i > config.zdepth) { - var zval = -config.zdepth; - } else { - var zval = -i - } - // console.log(i, config.zstart, config.zstep, config.zdepth, zval); - var drawClipperPathsconfig = { - paths: inflatedPaths, - color: toolpathColor, - opacity: 0.8, - z: zval, - isClosed: true, - name: 'inflateGrp', - leadInPaths: leadInPaths, - tabdepth: config.tabdepth, - tabspace: config.tabspace, - tabwidth: config.tabwidth, - toolDia: config.offset * 2, - drawPretty: true, - prettyGrpColor: (config.offset < 0) ? insideCutsColor : outsideCutsColor - } - var drawings = drawClipperPathsWithTool(drawClipperPathsconfig); - inflateGrp = drawings.lines; - inflateGrp.name = 'inflateGrp' + i; - inflateGrp.userData.material = inflateGrp.material; - inflateGrpZ.add(inflateGrp); - if (drawings.pretty) { - prettyGrp.add(drawings.pretty) - } - } - } - } - if (config.offset > minimumToolDiaForPreview || config.offset < -minimumToolDiaForPreview) { //Dont show for very small offsets, not worth the processing time - inflateGrpZ.userData.pretty = prettyGrp - }; - inflateGrpZ.userData.toolDia = config.offset * 2 - return inflateGrpZ; -}; - -pocketPath = function(config) { //}, infobject, inflateVal, stepOver, zstep, zdepth, zstart, union) { - var pocketGrp = new THREE.Group(); - var prettyGrp = new THREE.Group(); - if (config.offset != 0) { - var clipperPaths = getClipperPaths(config.toolpath) - // console.log("clipperPaths:", clipperPaths); - if (config.union == "Yes") { - // console.log("Union") - // simplify this set of paths which is a very powerful Clipper call that figures out holes and path orientations - var newClipperPaths = simplifyPolygons(clipperPaths); - // console.log(newClipperPaths) - if (newClipperPaths.length < 1) { - console.error("Clipper Simplification Failed!:"); - } - // calc Stepover - var cutwidth = ((config.offset * 2) * (config.stepover / 100)) //mm per cut - // todo for newClipperPaths.length (Split each clipperpath into own pocket) - // for (k = 1; k < newClipperPaths.length; k++) { - // var pathobj = []; - // pathobj.push(newClipperPaths[k]) - // console.log("processing " + newClipperPaths[k]) - for (i = 0; i < 1000; i++) { // Rather 1000 than a while loop, just in case, break when it no longer has data to work with - if (i == 0) { - inflateValUsed = config.offset; // at outer perimeter we offset just half tool else cut is bigger than sketch - } - if (inflateValUsed < config.offset) { - inflateValUsed = config.offset - } else { - inflateValUsed = cutwidth * i; - } - if (inflateValUsed < config.offset) { - // console.log("Should skip " + i) - } - // console.log(i, inflateValUsed, config.offset) - if (inflateValUsed > 0) { - // console.log(i, inflateValUsed, inflateVal, cutwidth, (cutwidth * i), (inflateVal * 2)) - var inflatedPaths = getInflatePath(newClipperPaths, -inflateValUsed); - if (inflatedPaths.length > 0) { - // Duplicate each loop, down into Z. We go full depth before next loop. - for (j = config.zdepth; j > config.zstart; j -= config.zstep) { // do the layers in reverse, because later, we REVERSE the whole array with pocketGrp.children.reverse() - then its top down. - // console.log(j) - - if (j > config.zdepth) { - var zval = -config.zdepth; - } else { - var zval = -j - } - // get the inflated/deflated path - var drawClipperPathsconfig = { - paths: inflatedPaths, - color: toolpathColor, - opacity: 0.8, - z: zval, - isClosed: true, - name: 'inflatedGroup', - leadInPaths: false, - tabdepth: false, - tabspace: false, - tabwidth: false, - toolDia: config.offset * 2, - drawPretty: true, - prettyGrpColor: pocketColor - } - var drawings = drawClipperPathsWithTool(drawClipperPathsconfig); - inflateGrp = drawings.lines; - inflateGrp.name = 'inflateGrp'; - inflateGrp.position = config.toolpath.position; - pocketGrp.add(inflateGrp); - if (drawings.pretty) { - prettyGrp.add(drawings.pretty) - } - } - } else { - // console.log('Pocket already done after ' + i + ' iterations'); - break; - } - } - } - // } - // get the inflated/deflated path then inside each loop, Duplicate each loop, down into Z. We go full depth before next loop. - if (config.offset > 1 || config.offset < -1) { - pocketGrp.userData.pretty = prettyGrp; - } - pocketGrp.children = pocketGrp.children.reverse(); // Inside Out! Breakthrough! - return pocketGrp; - } else { - console.log("Union") - // simplify this set of paths which is a very powerful Clipper call that figures out holes and path orientations - var newClipperPaths = simplifyPolygons(clipperPaths); - // console.log(newClipperPaths) - if (newClipperPaths.length < 1) { - console.error("Clipper Simplification Failed!:"); - } - // calc Stepover - var cutwidth = ((config.offset * 2) * (config.stepover / 100)) //mm per cut - // todo for newClipperPaths.length (Split each clipperpath into own pocket) - for (k = 0; k < newClipperPaths.length; k++) { - var pathobj = []; - pathobj.push(newClipperPaths[k]) - // console.log("processing " + newClipperPaths[k]) - for (i = 0; i < 1000; i++) { // Rather 1000 than a while loop, just in case, break when it no longer has data to work with - if (i == 0) { - inflateValUsed = config.offset; // at outer perimeter we offset just half tool else cut is bigger than sketch - } - if (inflateValUsed < config.offset) { - inflateValUsed = config.offset - } else { - inflateValUsed = cutwidth * i; - } - if (inflateValUsed < config.offset) { - console.log("Should skip " + i) - } - // console.log(i, inflateValUsed, config.offset) - if (inflateValUsed > 0) { - // console.log(i, inflateValUsed, inflateVal, cutwidth, (cutwidth * i), (inflateVal * 2)) - var inflatedPaths = getInflatePath(pathobj, -inflateValUsed); - if (inflatedPaths.length > 0) { - // Duplicate each loop, down into Z. We go full depth before next loop. - for (j = config.zdepth; j > config.zstart; j -= config.zstep) { // do the layers in reverse, because later, we REVERSE the whole array with pocketGrp.children.reverse() - then its top down. - // console.log(j) - if (j * config.zstep < config.zdepth) { - var zval = -j - } else { - var zval = -config.zdepth; - } - // get the inflated/deflated path - var drawClipperPathsconfig = { - paths: inflatedPaths, - color: toolpathColor, - opacity: 0.8, - z: zval, - isClosed: true, - name: 'inflatedGroup', - leadInPaths: false, - tabdepth: false, - tabspace: false, - tabwidth: false, - toolDia: config.offset * 2, - drawPretty: true, - prettyGrpColor: pocketColor - } - var drawings = drawClipperPathsWithTool(drawClipperPathsconfig); - inflateGrp = drawings.lines; - inflateGrp.name = 'inflateGrp'; - inflateGrp.position = config.toolpath.position; - pocketGrp.add(inflateGrp); - if (drawings.pretty) { - prettyGrp.add(drawings.pretty) - } - } - } else { - // console.log('Pocket already done after ' + i + ' iterations'); - break; - } - } - } - } - // get the inflated/deflated path then inside each loop, Duplicate each loop, down into Z. We go full depth before next loop. - if (config.offset > 1 || config.offset < -1) { - pocketGrp.userData.pretty = prettyGrp; - } - pocketGrp.children = pocketGrp.children.reverse(); // Inside Out! Breakthrough! - pocketGrp.userData.toolDia = config.offset * 2 - return pocketGrp; - } // end no union - } -}; - -dragknifePath = function(config) { //}, infobject, inflateVal, zstep, zdepth) { - var dragknifeGrp = new THREE.Group(); - // console.log("user wants to create Drag Knife Path. val:", inflateVal); - var clipperPaths = getClipperPaths(config.toolpath) - // console.log("clipperPaths:", clipperPaths); - // simplify this set of paths which is a very powerful Clipper call that figures out holes and path orientations - var newClipperPaths = simplifyPolygons(clipperPaths); - - if (newClipperPaths.length < 1) { - console.error("Clipper Simplification Failed!:"); - } - - for (j = 0; j < config.zdepth; j += config.zstep) { - if (j * config.zstep < config.zdepth) { - var zval = -j - } else { - var zval = -config.zdepth; - } - var polygons = newClipperPaths; - polygons = polygons.map(function(poly) { - // return addCornerActions(poly, Math.pow(2, 20) * 5, 20 / 180 * Math.PI); - return addCornerActions(poly, config.offset, 20 / 180 * Math.PI); - }); - var drawClipperPathsconfig = { - paths: polygons, - color: toolpathColor, - opacity: 0.8, - z: zval, - isClosed: true, - name: 'inflatedGroup', - leadInPaths: false, - tabdepth: false, - tabspace: false, - tabwidth: false, - toolDia: config.offset * 2, - } - inflateGrp = drawClipperPaths(drawClipperPathsconfig); - if (inflateGrp.children.length) { - inflateGrp.name = 'dragknifeGrp'; - inflateGrp.position = config.toolpath.position; - // dragknifeGrp.userData.color = dragknifeGrp.material.color.getHex(); - dragknifeGrp.add(inflateGrp) - } else { - console.log('Dragknife Operation Failed') - break; - } - } - dragknifeGrp.userData.toolDia = config.offset * 2 - return dragknifeGrp -}; - -addCornerActions = function(clipperPolyline, clipperRadius, toleranceAngleRadians) { - console.log("clipperPolyline Starting : ", clipperPolyline); - if (clipperRadius == 0 || clipperPolyline.length == 0) - return clipperPolyline; - var result = []; - result.push(clipperPolyline[0]); - //previous point is not always at i-1, because repeated points in the polygon are skipped - // var previousPoint = clipperPolyline[0]; - var previousPoint = new Point(clipperPolyline[0].X, clipperPolyline[0].Y, 0); //clipperPolyline[i - 1]; - for (var i = 1; i < clipperPolyline.length - 1; i++) { - previousPoint = new Point(clipperPolyline[i - 1].X, clipperPolyline[i - 1].Y, 0); //clipperPolyline[i - 1]; - var point = new Point(clipperPolyline[i].X, clipperPolyline[i].Y, 0); //clipperPolyline[i]; - if (previousPoint.sqDistance(point) == 0) - continue; - // you don't want to play with atan2() if a point is repeated - var incomingVector = point.sub(previousPoint); - var nextPoint = new Point(clipperPolyline[i + 1].X, clipperPolyline[i + 1].Y, 0) //clipperPolyline[i + 1]; - var angle = point.angle(previousPoint, nextPoint); - var overshoot = point.add(incomingVector.normalized().scale(clipperRadius)); - result.push(overshoot); - if (Math.abs(angle) > toleranceAngleRadians) { - - var arcPoints = 100 / (2 * Math.PI) * Math.abs(angle); - var incomingAngle = incomingVector.atan2(); - for (var j = 0; j <= arcPoints; j++) { - var a = incomingAngle + angle / arcPoints * j; - var pt = point.add(polarPoint(clipperRadius, a)); - result.push(pt); - } - } - previousPoint = point; - } - if (clipperPolyline.length > 1) - result.push(clipperPolyline[clipperPolyline.length - 1]); - return result; -} - -function Point(X, Y, Z) { - this.X = X; - this.Y = Y; - this.Z = Z === undefined ? 0 : Z; -} - -Point.prototype = { - sqDistance: function(p) { - var d = p == null ? this : this.sub(p); - return d.X * d.X + d.Y * d.Y + d.Z * d.Z; - }, - sub: function(p) { - // console.log("sub.x: ", this.x, " p.x ", p.x) - return new Point(this.X - p.X, this.Y - p.Y, this.Z - p.Z); - }, - angle: function(fromPoint, toPoint) { - var toPoint2 = new Point(toPoint.X, toPoint.Y, toPoint.Z); - var v1 = this.sub(fromPoint); - var v2 = toPoint2.sub(this); - var dot = v1.X * v2.X + v1.Y * v2.Y; - var cross = v1.X * v2.Y - v1.Y * v2.X; - var res = Math.atan2(cross, dot); - var twoPi = 2 * Math.PI; - if (res < -twoPi) - return res + twoPi; - if (res > twoPi) - return res - twoPi; - return res; - }, - normalized: function() { - // console.log("normalized.distance: ", this.distance()) - return this.scale(1 / this.distance()); - console.log("normalized: ", this.scale(1 / this.distance())) - }, - scale: function(val) { - return new Point(this.X * val, this.Y * val, this.Z * val); - }, - distance: function(p) { - return Math.sqrt(this.sqDistance(p)); - }, - add: function(p) { - return new Point(this.X + p.X, this.Y + p.Y, this.Z + p.Z); - }, - atan2: function() { - return Math.atan2(this.Y, this.Y); - }, -}; - -polarPoint = function(r, theta) { - return new Point(r * Math.cos(theta), r * Math.sin(theta)); -}; - -simplifyPolygons = function(paths) { - // console.log('Simplifying: ', paths); - var scale = 10000; - ClipperLib.JS.ScaleUpPaths(paths, scale); - var newClipperPaths = ClipperLib.Clipper.SimplifyPolygons(paths, ClipperLib.PolyFillType.pftEvenOdd); - // console.log('Simplified: ', newClipperPaths); - // scale back down - ClipperLib.JS.ScaleDownPaths(newClipperPaths, scale); - ClipperLib.JS.ScaleDownPaths(paths, scale); - return newClipperPaths; -}; - -getInflatePath = function(paths, delta, joinType) { - // console.log(paths.length) - var scale = 10000; - ClipperLib.JS.Clean(paths, 2); - ClipperLib.JS.ScaleUpPaths(paths, scale); - var miterLimit = 3; - var arcTolerance = 10; - joinType = joinType ? joinType : ClipperLib.JoinType.jtRound; - var co = new ClipperLib.ClipperOffset(miterLimit, arcTolerance); - co.AddPaths(paths, joinType, ClipperLib.EndType.etClosedPolygon); - //var delta = 0.0625; // 1/16 inch endmill - var offsetted_paths = new ClipperLib.Paths(); - co.Execute(offsetted_paths, delta * scale); - // scale back down - ClipperLib.JS.ScaleDownPaths(offsetted_paths, scale); - ClipperLib.JS.ScaleDownPaths(paths, scale); - return offsetted_paths; -}; - -drawClipperPaths = function(config) { - if (config.leadInPaths) { - if (config.leadInPaths.length != config.paths.length) { - console.log("Skipping lead-in: Source vector file is broken, and we could not produce a reliable offset") - printLog('Skipping lead-in: Source vector file is broken, and we could not produce a reliable offset', warncolor, "settings"); - } - } - // console.log("Compare lead-in: " + paths.length + " / " + leadInPaths.length) - - var lineUnionMat = new THREE.LineBasicMaterial({ - color: config.color, - transparent: true, - opacity: config.opacity, - }); - - if (config.z === undefined || config.z == null) - config.z = 0; - - if (config.isClosed === undefined || config.isClosed == null) - config.isClosed = true; - - var group = new THREE.Object3D(); - - - if (config.name) group.name = config.name; - - for (var i = 0; i < config.paths.length; i++) { - var lineUnionGeo = new THREE.Geometry(); - if (config.leadInPaths) { - if (leadInPaths.length == paths.length) { - lineUnionGeo.vertices.push(new THREE.Vector3(config.leadInPaths[i][0].X, config.leadInPaths[i][0].Y, z)); - } - } - var totalDist = 0; - var lastTabPos = -config.tabspace; - var lastvert = { - x: 0, - y: 0, - z: 0 - } - var lastTabPos = -config.tabspace; - for (var j = 0; j < config.paths[i].length; j++) { - // console.log(j) - totalDist += distanceFormula(lastvert.x, config.paths[i][j].X, lastvert.y, config.paths[i][j].Y) - if (totalDist > (lastTabPos + config.tabspace) && config.z < config.tabdepth) { - if (config.z < -config.tabdepth && j < config.paths[i].length - 1) { - // console.log(i, j) - var d = distanceFormula(config.paths[i][j].X, config.paths[i][j + 1].X, config.paths[i][j].Y, config.paths[i][j + 1].Y) - if (d >= (config.toolDia + config.tabwidth)) { - var numTabs = Math.round(d / (config.tabspace + config.tabwidth)); - // if we have a line distance of 100 - // and 3 tabs (width 10) in that line per numTabs - // then we want to evenly space them - // so we divide the line distance by numTabs - var spacePerTab = d / numTabs; - // which in this example would be 33.33~ - // then in each space per tab we need to center the tab - // which means dividing the difference of the spacePerTab and tabWidth by 2 - var tabPaddingPerSpace = (spacePerTab - (config.tabwidth + config.toolDia)) / 2; - - // console.log("Adding tab") - // next point - var deltaX = config.paths[i][j + 1].X - config.paths[i][j].X; - var deltaY = config.paths[i][j + 1].Y - config.paths[i][j].Y; - - // get the line angle - var ang = Math.atan2(deltaY, deltaX); - // console.log(' ANGLE ' + (ang * 180 / Math.PI)); - - // convert it to degrees for later math with addDegree - ang = ang * 180 / Math.PI; - - lastTabPos = totalDist; - var npt = [config.paths[i][j].X, config.paths[i][j].Y] - for (var r = 0; r < numTabs; r++) { - // then for each tab - // add another point at the current point +tabPaddingPerSpace - npt = newPointFromDistanceAndAngle(npt, ang, tabPaddingPerSpace); - // g += 'G1' + feedrate + ' X' + npt[0] + ' Y' + npt[1] + '\n'; - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.z)); - // then we raise the z height by config.tabHeight - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.tabdepth)); - // g += 'G0 Z' + tabsBelowZ + '\n'; - // then add another point at the current point +tabWidth - npt = newPointFromDistanceAndAngle(npt, ang, config.tabwidth + config.toolDia); - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.tabdepth)); - // g += 'G0' + feedrate + ' X' + npt[0] + ' Y' + npt[1] + '\n'; - // then lower the z height back to zPos at plunge speed - // g += 'G0 F' + plungeSpeed + ' Z' + tabsBelowZ + '\n'; - // g += 'G1 F' + plungeSpeed + ' Z' + zpos + '\n'; - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.z)); - // then add another point at the current point +tabPaddingPerSpace - // with the cut speed - npt = newPointFromDistanceAndAngle(npt, ang, tabPaddingPerSpace); - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.z)); - // g += 'G1' + feedrate + ' X' + npt[0] + ' Y' + npt[1] + '\n'; - } - } else { - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][j].X, config.paths[i][j].Y, config.z)); - } - } else { - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][j].X, config.paths[i][j].Y, config.vz)); - } - } else { - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][j].X, config.paths[i][j].Y, config.z)); - } - // lineUnionGeo.vertices.push(new THREE.Vector3(paths[i][j].X, paths[i][j].Y, z)); - lastvert = { - x: config.paths[i][j].X, - y: config.paths[i][j].Y, - z: config.z - } - } - // close it by connecting last point to 1st point - if (config.isClosed) { - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][0].X, config.paths[i][0].Y, config.z)); - } - if (config.leadInPaths) { - if (leadInPaths.length == paths.length) { - lineUnionGeo.vertices.push(new THREE.Vector3(config.leadInPaths[i][0].X, config.leadInPaths[i][0].Y, config.z)); - } - } - - var lineUnion = new THREE.Line(lineUnionGeo, lineUnionMat); - if (config.name) { - lineUnion.name = config.name; - } - group.add(lineUnion); - } - return group; -}; - -drawClipperPathsWithTool = function(config) { - var group = new THREE.Object3D(); - // console.log(config) - if (config.leadInPaths) { - if (config.leadInPaths.length != config.paths.length) { - console.log("Skipping lead-in: Source vector file is broken, and we could not produce a reliable offset") - printLog('Skipping lead-in: Source vector file is broken, and we could not produce a reliable offset', warncolor, "settings"); - } - } - - var lineUnionMat = new THREE.LineBasicMaterial({ - color: config.color, - transparent: true, - opacity: config.opacity, - }); - - if (config.z === undefined || config.z == null || config.z == false) - config.z = 0; - - if (config.isClosed === undefined || config.isClosed == null) - config.isClosed = true; - - if (config.name) group.name = config.name; - - if (config.toolDia < 0) { - config.toolDia = config.toolDia * -1; - } - - var clipperPaths = []; - var clipperTabsPaths = []; - for (var i = 0; i < config.paths.length; i++) { - var clipperArr = []; - var clipperTabsArr = []; - var lineUnionGeo = new THREE.Geometry(); - if (config.leadInPaths) { - if (config.leadInPaths.length == config.paths.length) { - lineUnionGeo.vertices.push(new THREE.Vector3(config.leadInPaths[i][0].X, config.leadInPaths[i][0].Y, config.z)); - clipperArr.push({ - X: config.leadInPaths[i][0].X, - Y: config.leadInPaths[i][0].Y - }); - } - } - var totalDist = 0; - var lastTabPos = -config.tabspace; - var lastvert = { - x: 0, - y: 0, - z: 0 - } - var lastTabPos = -config.tabspace; - for (var j = 0; j < config.paths[i].length; j++) { - // console.log(j) - totalDist += distanceFormula(lastvert.x, config.paths[i][j].X, lastvert.y, config.paths[i][j].Y) - if (config.tabwidth) { - if (totalDist > (lastTabPos + config.tabspace) && config.z < config.tabdepth) { - if (j < config.paths[i].length) { - // console.log(i, j) - if (j < config.paths[i].length - 1) { - var d = distanceFormula(config.paths[i][j].X, config.paths[i][j + 1].X, config.paths[i][j].Y, config.paths[i][j + 1].Y) - } else { - var d = distanceFormula(config.paths[i][j].X, config.paths[i][0].X, config.paths[i][j].Y, config.paths[i][0].Y) - } - if (d >= (config.toolDia + config.tabwidth)) { - var numTabs = Math.round(d / (config.tabspace + config.tabwidth)); - // if we have a line distance of 100 - // and 3 tabs (width 10) in that line per numTabs - // then we want to evenly space them - // so we divide the line distance by numTabs - var spacePerTab = d / numTabs; - // which in this example would be 33.33~ - // then in each space per tab we need to center the tab - // which means dividing the difference of the spacePerTab and tabWidth by 2 - var tabPaddingPerSpace = (spacePerTab - (config.tabwidth + config.toolDia)) / 2; - - // console.log("Adding tab") - // next point - if (j < config.paths[i].length - 1) { - var deltaX = config.paths[i][j + 1].X - config.paths[i][j].X; - var deltaY = config.paths[i][j + 1].Y - config.paths[i][j].Y; - } else { - var deltaX = config.paths[i][0].X - config.paths[i][j].X; - var deltaY = config.paths[i][0].Y - config.paths[i][j].Y; - } - - // get the line angle - var ang = Math.atan2(deltaY, deltaX); - // console.log(' ANGLE ' + (ang * 180 / Math.PI)); - - // convert it to degrees for later math with addDegree - ang = ang * 180 / Math.PI; - - lastTabPos = totalDist; - var npt = [config.paths[i][j].X, config.paths[i][j].Y] - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.z)); - clipperArr.push({ - X: npt[0], - Y: npt[1] - }); - for (var r = 0; r < numTabs; r++) { - var clipperTabsArr = []; - // then for each tab - // add another point at the current point +tabPaddingPerSpace - npt = newPointFromDistanceAndAngle(npt, ang, tabPaddingPerSpace); - // g += 'G1' + feedrate + ' X' + npt[0] + ' Y' + npt[1] + '\n'; - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.z)); - clipperArr.push({ - X: npt[0], - Y: npt[1] - }); - clipperTabsArr.push({ - X: npt[0], - Y: npt[1] - }); - // then we raise the z height by config.tabHeight - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.tabdepth)); - clipperArr.push({ - X: npt[0], - Y: npt[1] - }); - clipperTabsArr.push({ - X: npt[0], - Y: npt[1] - }); - // g += 'G0 Z' + tabsBelowZ + '\n'; - // then add another point at the current point +tabWidth - npt = newPointFromDistanceAndAngle(npt, ang, config.tabwidth + config.toolDia); - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.tabdepth)); - clipperArr.push({ - X: npt[0], - Y: npt[1] - }); - clipperTabsArr.push({ - X: npt[0], - Y: npt[1] - }); - // g += 'G0' + feedrate + ' X' + npt[0] + ' Y' + npt[1] + '\n'; - // then lower the z height back to zPos at plunge speed - // g += 'G0 F' + plungeSpeed + ' Z' + tabsBelowZ + '\n'; - // g += 'G1 F' + plungeSpeed + ' Z' + zpos + '\n'; - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.z)); - clipperArr.push({ - X: npt[0], - Y: npt[1] - }); - clipperTabsArr.push({ - X: npt[0], - Y: npt[1] - }); - // then add another point at the current point +tabPaddingPerSpace - // with the cut speed - npt = newPointFromDistanceAndAngle(npt, ang, tabPaddingPerSpace); - lineUnionGeo.vertices.push(new THREE.Vector3(npt[0], npt[1], config.z)); - clipperArr.push({ - X: npt[0], - Y: npt[1] - }); - clipperTabsPaths.push(clipperTabsArr); - // g += 'G1' + feedrate + ' X' + npt[0] + ' Y' + npt[1] + '\n'; - } - } else { // line isnt long enough - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][j].X, config.paths[i][j].Y, config.z)); - clipperArr.push({ - X: config.paths[i][j].X, - Y: config.paths[i][j].Y - }); - } - } else { // is last point - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][j].X, config.paths[i][j].Y, config.z)); - clipperArr.push({ - X: config.paths[i][j].X, - Y: config.paths[i][j].Y - }); - } - } else { // havent moved far enough yet - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][j].X, config.paths[i][j].Y, config.z)); - clipperArr.push({ - X: config.paths[i][j].X, - Y: config.paths[i][j].Y - }); - } - } else { // no valid config.tabwidth found - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][j].X, config.paths[i][j].Y, config.z)); - clipperArr.push({ - X: config.paths[i][j].X, - Y: config.paths[i][j].Y - }); - } - // lineUnionGeo.vertices.push(new THREE.Vector3(paths[i][j].X, paths[i][j].Y, z)); - lastvert = { - x: config.paths[i][j].X, - y: config.paths[i][j].Y, - z: config.z - } - } // end for loop j < paths[i].length - // close it by connecting last point to 1st point - if (config.isClosed) { - lineUnionGeo.vertices.push(new THREE.Vector3(config.paths[i][0].X, config.paths[i][0].Y, config.z)); - clipperArr.push({ - X: config.paths[i][0].X, - Y: config.paths[i][0].Y - }); - } - if (config.leadInPaths) { - if (config.leadInPaths.length == config.paths.length) { - lineUnionGeo.vertices.push(new THREE.Vector3(config.leadInPaths[i][0].X, config.leadInPaths[i][0].Y, config.z)); - clipperArr.push({ - X: config.leadInPaths[i][0].X, - Y: config.leadInPaths[i][0].Y - }); - } - } - - var lineUnion = new THREE.Line(lineUnionGeo, lineUnionMat); - if (config.name) { - lineUnion.name = config.name; - } - group.add(lineUnion); - clipperPaths.push(clipperArr); - clipperTabsPaths.push(clipperTabsArr); - - } // end for loop i < paths.length - - // console.log(clipperPaths[0].length, clipperTabsPaths.length) - - var prettyGrp = new THREE.Group(); - var prettyGrpColor = config.prettyGrpColor; - - if (config.z < config.tabdepth) { - if (config.toolDia > minimumToolDiaForPreview || config.toolDia < -minimumToolDiaForPreview) { //Dont show for very small offsets, not worth the processing time - // generate once use again - // for each z - if (!$('#performanceLimit').is(":checked")) { - var lineMesh = this.getMeshLineFromClipperPath({ - width: config.toolDia, - clipperPath: clipperPaths, - isSolid: true, - opacity: 0.2, - isShowOutline: true, - color: config.prettyGrpColor, - caps: "round" - }); - lineMesh.position.z = config.z; - prettyGrp.add(lineMesh) - var lineMesh = this.getMeshLineFromClipperPath({ - width: config.toolDia, - clipperPath: clipperTabsPaths, - isSolid: true, - opacity: 0.4, - isShowOutline: true, - color: 0x00ff00, - caps: "negative" - }); - lineMesh.position.z = config.z; - prettyGrp.add(lineMesh) - } - } - } else { - if (config.toolDia > minimumToolDiaForPreview || config.toolDia < -minimumToolDiaForPreview) { //Dont show for very small offsets, not worth the processing time - // generate once use again for each z - if (!$('#performanceLimit').is(":checked")) { - var lineMesh = this.getMeshLineFromClipperPath({ - width: config.toolDia, - clipperPath: config.paths, - isSolid: true, - opacity: 0.2, - isShowOutline: true, - color: config.prettyGrpColor, - caps: "round" - }); - lineMesh.position.z = config.z; - prettyGrp.add(lineMesh) - } - } - } - - - if (!$('#performanceLimit').is(":checked")) { - var grp = { - lines: group, - pretty: prettyGrp - } - } else { - var grp = { - lines: group, - pretty: false - } - } - - return grp; -}; - -function getClipperPaths(object) { - object.updateMatrix(); - var grp = object; - var clipperPaths = []; - grp.traverse(function(child) { - // console.log('Traverse: ', child) - if (child.name == "inflatedGroup") { - console.log("this is the inflated path from a previous run. ignore."); - return; - } else if (child.type == "Line") { - // let's inflate the path for this line. it may not be closed - // so we need to check that. - var clipperArr = []; - // Fix world Coordinates - for (i = 0; i < child.geometry.vertices.length; i++) { - var localPt = child.geometry.vertices[i]; - var worldPt = child.localToWorld(localPt.clone()); - var xpos = worldPt.x; // + (sizexmax /2); - var ypos = worldPt.y; // + (sizeymax /2); - - var xpos_offset = (parseFloat(child.position.x.toFixed(3))); - var ypos_offset = (parseFloat(child.position.y.toFixed(3))); - - if (child.geometry.type == "CircleGeometry") { - xpos = (xpos + xpos_offset); - ypos = (ypos + ypos_offset); - } - clipperArr.push({ - X: xpos, - Y: ypos - }); - } - clipperPaths.push(clipperArr); - } else if (child.type == "Points") { - child.visible = false; - } else { - // console.log("type of ", child.type, " being skipped"); - } - }); - return clipperPaths -} - -// borrowed tab generator code from https://github.com/andrewhodel/millcrum/blob/master/inc/mc.js -distanceFormula = function(x1, x2, y1, y2) { - // get the distance between p1 and p2 - var a = (x2 - x1) * (x2 - x1); - var b = (y2 - y1) * (y2 - y1); - return Math.sqrt(a + b); -}; - -newPointFromDistanceAndAngle = function(pt, ang, distance) { - // use cos and sin to get a new point with an angle - // and distance from an existing point - // pt = [x,y] - // ang = in degrees - // distance = N - var r = []; - r.push(pt[0] + (distance * Math.cos(ang * Math.PI / 180))); - r.push(pt[1] + (distance * Math.sin(ang * Math.PI / 180))); - return r; -}; diff --git a/js/advanced-cam-tree.js b/js/advanced-cam-tree.js index 61ac2c37..36b21266 100644 --- a/js/advanced-cam-tree.js +++ b/js/advanced-cam-tree.js @@ -84,9 +84,11 @@ function fillTree() { toolp += ` + + @@ -121,4 +123,4 @@ function fillTree() { var data = $this.data(); toolpathsInScene[data.id].name = $this.text(); }); -} \ No newline at end of file +} diff --git a/js/advanced-cam-viewer-mouse.js b/js/advanced-cam-viewer-mouse.js index b8dcd7ec..c9dc83b2 100644 --- a/js/advanced-cam-viewer-mouse.js +++ b/js/advanced-cam-viewer-mouse.js @@ -91,7 +91,7 @@ function setOpacity(array, opacity) { pretty.traverse(function(child) { if (child.material && child.type == "Mesh") { // child.material.opacity = opacity / depth; - child.material.opacity = opacity / depth + 0.5; + child.material.opacity = opacity / depth + 0.2; } else if (child.material && child.type == "Line") { // child.material.opacity = (opacity / depth )+0.25; child.material.opacity = (opacity / depth) + 0.5; @@ -137,4 +137,4 @@ function updateCloneMoves() { }); } -} \ No newline at end of file +} diff --git a/js/advanced-cam-viewer-select.js b/js/advanced-cam-viewer-select.js index 764d1e7c..1302f538 100644 --- a/js/advanced-cam-viewer-select.js +++ b/js/advanced-cam-viewer-select.js @@ -378,30 +378,16 @@ function mouseMove(event) { // } } } else { // just hovering - lets color - // console.log(event) - // var isModalOpen = $('#statusmodal').is(':visible'); // dont raycast if modal is over the viewer var isModalOpen = Metro.dialog.isOpen('#statusmodal') // dont raycast if modal is over the viewer if (!isModalOpen) { // the first 390px = sidebar - we dont want to catch the mouse there.. mouseVector.x = (event.offsetX / renderer.domElement.width) * 2 - 1; mouseVector.y = -(event.offsetY / renderer.domElement.height) * 2 + 1; camera.updateProjectionMatrix(); raycaster.setFromCamera(mouseVector, camera); - // focus the scope of the intersecting to ONLY documents. Otherwise if there is existing toolpaths, we intersect - // upwards of 10k objects and slows the filter down immensely - // scene.remove(arrow); - // var dir = new THREE.Vector3(raycaster.ray.direction.x, raycaster.ray.direction.y, raycaster.ray.direction.z); - // //normalize the direction vector (convert to vector of length 1) - // dir.normalize(); - // var origin = new THREE.Vector3(raycaster.ray.origin.x, raycaster.ray.origin.y, raycaster.ray.origin.z); - // arrow = new THREE.ArrowHelper(dir, origin, 1000, 0xff0000, 5, 5); - // scene.add(arrow); var documents = scene.getObjectByName("Documents"); - // console.log(documents) if (documents) { var intersects = raycaster.intersectObjects(documents.children, true) - // console.log(intersects) if (intersects.length > 0) { - // clear all hover colors for (i = 0; i < objectsInScene.length; i++) { var obj = objectsInScene[i]; obj.traverse(function(child) { @@ -421,7 +407,6 @@ function mouseMove(event) { } else if (mouseState = "scale") { $('#renderArea').css('cursor', 'pointer'); } - // console.log(obj) hoverShapesinScene.length = 0; if (mouseState == "scale" || (mouseState == "move" && !event.ctrlKey && !event.altKey) || (mouseState == "delete" && event.ctrlKey) || (mouseState == "delete" && event.altKey)) { obj = obj.parent @@ -456,7 +441,6 @@ function mouseMove(event) { }); clearSceneFlag = true; } - } else { // hovering over nothing $('#renderArea').css('cursor', ''); hoverShapesinScene.length = 0; @@ -470,7 +454,6 @@ function mouseMove(event) { }); } } - // console.log(hoverShapesinScene) } // end raycast hover event } // end !ismodalopen } // end just hovering @@ -535,4 +518,4 @@ function mouseToWorldCoord(e) { var distance = -camera.position.z / dir.z; var coords = camera.position.clone().add(dir.multiplyScalar(distance)); return coords; -} \ No newline at end of file +} diff --git a/js/advanced-cam-workspace-export.js b/js/advanced-cam-workspace-export.js index 80e4835d..08e0ded4 100644 --- a/js/advanced-cam-workspace-export.js +++ b/js/advanced-cam-workspace-export.js @@ -263,17 +263,22 @@ function parseLoadWorkspace(json, resetView) { var object = loader.parse(newWorkspace.objects[key]); objectsInScene.push(object) } - fillTree(); + // fillTree(); $('#documentstree').show(); $('#documentactivity').hide(); for (var key in newWorkspace.toolpaths) { var object = loader.parse(newWorkspace.toolpaths[key]); toolpathsInScene.push(object) } - - for (i = 0; i < toolpathsInScene.length; i++) { - toolpathPreview(i); + fillTree(); + if (resetView) { + resetView(); } + setTimeout(function() { + for (i = 0; i < toolpathsInScene.length; i++) { + toolpathPreview(i); + } + }, 200); if (resetView) { resetView(); } diff --git a/js/basic-cad-helloworld.js b/js/basic-cad-helloworld.js index ef432af2..f83a018f 100644 --- a/js/basic-cad-helloworld.js +++ b/js/basic-cad-helloworld.js @@ -1,20 +1,38 @@ function helloWorld() { - $.get("./workspace/helloworld.json?date=" + new Date().getTime(), function(data) { + $.get("./workspace/helloworld.obc?date=" + new Date().getTime(), function(data) { parseLoadWorkspace(data) resetView(); fillTree(); setTimeout(function() { makeGcode(); - }, 2000) + }, 500) }); } function helloWorldLaser() { - $.get("./workspace/helloworldlaser.json?date=" + new Date().getTime(), function(data) { + $.get("./workspace/helloworldlaser.obc?date=" + new Date().getTime(), function(data) { parseLoadWorkspace(data) resetView(); fillTree(); - setTimeout(function() {}, 2000) - makeGcode(); + setTimeout(function() {makeGcode();}, 500) + + }); +} + +function helloWorldDragKnife() { + $.get("./workspace/helloworlddragknife.obc?date=" + new Date().getTime(), function(data) { + parseLoadWorkspace(data) + resetView(); + fillTree(); + setTimeout(function() {makeGcode();}, 500) }); -} \ No newline at end of file +} + +function helloWorldPlasma() { + $.get("./workspace/helloworldplasma.obc?date=" + new Date().getTime(), function(data) { + parseLoadWorkspace(data) + resetView(); + fillTree(); + setTimeout(function() {makeGcode();}, 500) + }); +} diff --git a/js/viewer-pause.js b/js/viewer-pause.js index a7cd4860..29c30a22 100644 --- a/js/viewer-pause.js +++ b/js/viewer-pause.js @@ -55,4 +55,4 @@ if (notIE && !isChromium) { // console.log("blur"); }); }; -}; \ No newline at end of file +}; diff --git a/js/viewer.js b/js/viewer.js index 049cb707..54bae23e 100644 --- a/js/viewer.js +++ b/js/viewer.js @@ -282,7 +282,7 @@ function init3D() { printLog('WebGL Support found! success: this application will work optimally on this device!'); renderer = new THREE.WebGLRenderer({ autoClearColor: true, - antialias: false, + antialias: true, preserveDrawingBuffer: true, alpha: true }); @@ -603,4 +603,4 @@ function resetView(object) { } else { viewExtents(object); } -} \ No newline at end of file +} diff --git a/lib/3dview/workers/litegcodeviewer.js b/lib/3dview/workers/litegcodeviewer.js index 0d5084bd..5b15673a 100644 --- a/lib/3dview/workers/litegcodeviewer.js +++ b/lib/3dview/workers/litegcodeviewer.js @@ -320,7 +320,7 @@ GCodeParser = function(handlers, modecmdhandlers) { //console.log("ac:", ac); var acmat = new THREE.LineBasicMaterial({ color: colorG2, - opacity: 0.5, + opacity: 1, transparent: true }); var acgeo = new THREE.Geometry(); diff --git a/lib/svgreader/SVGReader.js b/lib/svgreader/SVGReader.js deleted file mode 100644 index af7c20b2..00000000 --- a/lib/svgreader/SVGReader.js +++ /dev/null @@ -1,1286 +0,0 @@ -/** -SVG parser for the Lasersaur. -Converts SVG DOM to a flat collection of paths. - -Copyright (c) 2011 Nortd Labs -Open Source by the terms of the Gnu Public License (GPL3) or higher. - -Code inspired by cake.js, canvg.js, svg2obj.py, and Squirtle. -Thank you for open sourcing your work! - -Usage: -var boundarys = SVGReader.parse(svgstring, config) - -Features: -* width and height, viewBox clipping. -* paths, rectangles, ellipses, circles, lines, polylines and polygons -* nested transforms -* transform lists (transform="rotate(30) translate(2,2) scale(4)") -* non-pixel units (cm, mm, in, pt, pc) -* 'style' attribute and presentation attributes -* curves, arcs, cirles, ellipses tesellated according to tolerance - -Intentinally not Supported: -* markers -* masking -* em, ex, % units -* text (needs to be converted to paths) -* raster images -* style sheets - -ToDo: -* check for out of bounds geometry -*/ - -if(typeof require === 'function') { - var Vec2 = require(__dirname + '/vec2.js').Vec2 -} - -SVGReader = { - - boundarys : {}, - // output path flattened (world coords) - // hash of path by color - // each path is a list of subpaths - // each subpath is a list of verteces - style : {}, - // style at current parsing position - tolerance : 0.05, - // max tollerance when tesselating curvy shapes - - - preview : function(svgstring, config) { - this.tolerance_squared = Math.pow(this.tolerance, 2); - - // parse xml - var svgRootElement; - if (window.DOMParser) { - var parser = new DOMParser(); - svgRootElement = parser.parseFromString(svgstring, 'text/xml').documentElement; - } - else { - xml = xml.replace(/]*>/, ''); - var xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); - xmlDoc.async = 'false'; - xmlDoc.loadXML(svgstring); - svgRootElement = xmlDoc.documentElement; - } - - // let the fun begin - var node = {} - this.boundarys.allcolors = [] // TODO: sort by color - node.stroke = [255,0,0]; - node.xformToWorld = [1,0,0,1,0,0] - this.previewChildren(svgRootElement, node) - return this.boundarys - }, - - - previewChildren : function(domNode, parentNode) { - var childNodes = [] - for (var i=0; i]*>/, ''); - var xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); - xmlDoc.async = 'false'; - xmlDoc.loadXML(svgstring); - svgRootElement = xmlDoc.documentElement; - } - - // let the fun begin - var node = {}; - this.boundarys.allcolors = []; // TODO: sort by color - node.stroke = [255,0,0]; - node.xformToWorld = [1,0,0,1,0,0]; - this.parseChildren(svgRootElement, node); - - // Parse editor vendor/version/etc... - // Editor tag stay on line 2 - var fingerprint = svgstring.split('\n')[1]; - if (fingerprint) { - var inkscape = fingerprint.match(/^