From 2dfc89512f9d36ab813c77733787ff96a2802569 Mon Sep 17 00:00:00 2001 From: Mattia Bondanza Date: Wed, 4 Jan 2017 18:07:58 +0100 Subject: [PATCH 1/7] Written function generate_optimized_gcode that generate a much shorter path for cutting. Now the function is used by default. --- public/js/threegcode.js | 239 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 236 insertions(+), 3 deletions(-) diff --git a/public/js/threegcode.js b/public/js/threegcode.js index 8942702f..c5f68022 100644 --- a/public/js/threegcode.js +++ b/public/js/threegcode.js @@ -68,7 +68,7 @@ $(document).ready(function() { if (objectsInScene[j].userData.inflated) { // g += generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); printLog('Separate Operation for ' + objectsInScene[j].name, msgcolor, "file") - objectsInScene[j].userData.gcode = generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); + objectsInScene[j].userData.gcode = generate_optimized_Gcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); } else { // g += generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); if (passes > 1) { @@ -77,11 +77,11 @@ $(document).ready(function() { for (m = 0; m < passes; m++) { console.log("Mulipass Layer: " + m); var zoffset = passdepth * m; - gcodewithmultipass += generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset); + gcodewithmultipass += generate_optimized_Gcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset); } objectsInScene[j].userData.gcode = gcodewithmultipass; } else { - objectsInScene[j].userData.gcode = generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset); + objectsInScene[j].userData.gcode = generate_optimized_Gcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset); } } @@ -149,6 +149,238 @@ function prepgcodefile() { return g; } +function get_cut_begin_point( threeGroup, i ){ + var localPt = threeGroup.children[i].geometry.vertices[0]; + var worldPt = threeGroup.localToWorld(localPt.clone()); + var xpos = worldPt.x + (parseFloat(laserxmax) / 2); + var ypos = worldPt.y + (parseFloat(laserymax) / 2); + + var xpos_offset = threeGroup.children[i].position.x; + var ypos_offset = threeGroup.children[i].position.y; + + if (threeGroup.children[i].geometry.type == "CircleGeometry") { + xpos = (xpos + xpos_offset); + ypos = (ypos + ypos_offset); + } + + return new THREE.Vector2( xpos, ypos ); +} + +function get_cut_end_point( threeGroup, i ){ + var localPt = threeGroup.children[i].geometry.vertices[ threeGroup.children[i].geometry.vertices.length - 1 ]; + var worldPt = threeGroup.localToWorld(localPt.clone()); + var xpos = worldPt.x + (parseFloat(laserxmax) / 2); + var ypos = worldPt.y + (parseFloat(laserymax) / 2); + + var xpos_offset = threeGroup.children[i].position.x; + var ypos_offset = threeGroup.children[i].position.y; + + if (threeGroup.children[i].geometry.type == "CircleGeometry") { + xpos = (xpos + xpos_offset); + ypos = (ypos + ypos_offset); + } + + return new THREE.Vector2( xpos, ypos ); +} + +function distance_2p( a, b ){ + return (Math.pow(a.x-b.x, 2)+Math.pow(a.y-b.y,2)); +} + +function generate_optimized_Gcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset) { + + var laserPwrVal = 0.0; + // console.log('inside generateGcode') + // console.log('Group', threeGroup); + // console.log('CutSpeed', cutSpeed); + // console.log('plungeSpeed', plungeSpeed); + // console.log('Laser Power %', laserPwr); + var lasermultiply = $('#lasermultiply').val(); + // console.log('Laser Multiplier', lasermultiply); + + if (lasermultiply <= 1) { + var laserPwrVal = laserPwr / 100; + laserPwrVal = parseFloat(laserPwrVal).toFixed(2); + } else { + var laserPwrVal = laserPwr * (lasermultiply / 100); + laserPwrVal = laserPwrVal.toFixed(0); + } + // console.log('Laser Power Value', laserPwrVal, ' type of ', typeof(laserPwrVal)); + + var g = ""; + // get the THREE.Group() that is the txt3d + + var txtGrp = threeGroup; + var that = this; + var isLaserOn = false; + var isAtClearanceHeight = false; + var isFeedrateSpecifiedAlready = false; + var isSeekrateSpecifiedAlready = false; + + + var cncMode = false; + + if ($('#cncMode').val() == "Enable") { + cncMode = true; + } + + // var subj_path2 = []; + // var subj_paths = []; + // console.log(txtGrp); + // console.log(rapidSpeed) + // console.log(cutSpeed); + + // txtGrp.updateMatrixWorld(); + + var toCut = txtGrp.clone(); //Copia delle linee di cui deve ancora fare il gocde. + var actual_position = new THREE.Vector2( 0, 0 ); //Posizione attuale del LASER + + while( toCut.children.length > 0 ){ + console.log("Element ", toCut.children.length); + var opt_distance = distance_2p( get_cut_begin_point( toCut, 0 ), actual_position ); + var opt_cut = 0; + //g+= "Calcolo "+toCut.children.length+" distanze\n\n"; + for( i = 0; i < toCut.children.length; i++ ){ // Scorre i segmenti da disegnare cercando iil più vicino + var distance = distance_2p( get_cut_begin_point( toCut, i ), actual_position ); + // g+=i+": "+distance+" mm\n"; + if( distance < opt_distance ){ + opt_distance = distance; + opt_cut = i; + } + } + //g+="Distanza ottimale "+opt_cut+": "+opt_distance+" mm\n"; + //opt_cut = 0; //QUESTA LINEA FA SEMPLICEMENTE ESEGUIRE IL TAGLIO IN ORDINE. + actual_position = get_cut_end_point( toCut, opt_cut ); + child = toCut.children[opt_cut].clone(); + + if (child.type == "Line") { + + var xpos_offset = child.position.x; + var ypos_offset = child.position.y; + + + // let's create gcode for all points in line + for (i = 0; i < child.geometry.vertices.length; i++) { + + // Convert to World Coordinates + var localPt = child.geometry.vertices[i]; + var worldPt = txtGrp.localToWorld(localPt.clone()); + var xpos = worldPt.x + (parseFloat(laserxmax) / 2); + var ypos = worldPt.y + (parseFloat(laserymax) / 2); + + + if (child.geometry.type == "CircleGeometry") { + xpos = (xpos + xpos_offset); + ypos = (ypos + ypos_offset); + } + + + var zpos = worldPt.z; + + if (zoffset) { + zpos = zpos - zoffset; + } + + + // First Move To + if (i == 0) { + // first point in line where we start lasering/milling + var seekrate; + if (isSeekrateSpecifiedAlready) { + seekrate = ""; + } else { + // console.log('Rapid Speed: ', rapidSpeed); + if (rapidSpeed) { + seekrate = " F" + rapidSpeed; + isSeekrateSpecifiedAlready = true; + } else { + seekrate = ""; + } + + } + if (cncMode) { + if (!isAtClearanceHeight) { + g += "\nG0 Z" + clearanceHeight + "\n"; // Position Before Plunge! + } + }; + g += "G0" + seekrate; + g += " X" + xpos.toFixed(4) + " Y" + ypos.toFixed(4) + "\n"; + if (cncMode) { + g += "\nG0 Z1\n"; // G0 to Z0 then Plunge! + g += "G1 F"+plungeSpeed+" Z" + zpos.toFixed(4) + "\n"; // Plunge!!!! + } else { + if (isFeedrateSpecifiedAlready) { + } else { + // console.log('Cut Speed: ', cutSpeed); + if (cutSpeed) { + feedrate = " F" + cutSpeed; + isFeedrateSpecifiedAlready = true; + } else { + feedrate = ""; + } + } + g += "G1" + feedrate + " X" + xpos.toFixed(4) + " Y" + ypos.toFixed(4) + " Z" + zpos.toFixed(4) + "\n"; + }; + isAtClearanceHeight = false; + // Else Cut move + } else { + // we are in a non-first line so this is normal moving + // if the laser is not on, we need to turn it on + if (!isLaserOn) { + if (laseron) { + g += laseron + g += '\n' + } else { + // Nothing - most of the firmware used G0 = move, G1 = cut and doesnt need a laseron/laseroff command + }; + isLaserOn = true; + } + + // do normal feedrate move + var feedrate; + if (isFeedrateSpecifiedAlready) { + } else { + console.log('Cut Speed: ', cutSpeed); + if (cutSpeed) { + feedrate = " F" + cutSpeed; + isFeedrateSpecifiedAlready = true; + } else { + feedrate = ""; + } + } + g += "G1" + feedrate; + g += " X" + xpos.toFixed(4); + g += " Y" + ypos.toFixed(4); + g += " Z" + zpos.toFixed(4); + g += " S" + laserPwrVal + "\n"; + } + } + + + + // make feedrate have to get specified again on next line if there is one + isFeedrateSpecifiedAlready = false; + isLaserOn = false; + // if (firmware.indexOf('Grbl') == 0) { + if (laseroff) { + g += laseroff + g += '\n' + } else { + // Nothing - most of the firmware used G0 = move, G1 = cut and doesnt need a laseron/laseroff command + } + } + + toCut.remove( toCut.children[opt_cut] ); + } + + //FAGLI STAMPARE TUTTI I PUNTI E CONTROLLA DOVE SONO DAVVERO + console.log("Generated gcode. length:", g.length); + console.log(" "); + isGcodeInRegeneratingState = false; + return g; +}; + + function generateGcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset) { var laserPwrVal = 0.0; @@ -746,3 +978,4 @@ drawClipperPaths = function(paths, color, opacity, z, isClosed, name) { } return group; }; + From 485dbab4a7d440e49eb20d598b8a78215790e57e Mon Sep 17 00:00:00 2001 From: Mattia Bondanza Date: Wed, 4 Jan 2017 18:39:03 +0100 Subject: [PATCH 2/7] Code cleaning. Use method of vectors for calculating squared distances. Implemented reverse cuts of lines. --- public/js/threegcode.js | 43 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/public/js/threegcode.js b/public/js/threegcode.js index c5f68022..531ebbb4 100644 --- a/public/js/threegcode.js +++ b/public/js/threegcode.js @@ -183,10 +183,6 @@ function get_cut_end_point( threeGroup, i ){ return new THREE.Vector2( xpos, ypos ); } -function distance_2p( a, b ){ - return (Math.pow(a.x-b.x, 2)+Math.pow(a.y-b.y,2)); -} - function generate_optimized_Gcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset) { var laserPwrVal = 0.0; @@ -232,33 +228,44 @@ function generate_optimized_Gcode(threeGroup, objectseq, cutSpeed, plungeSpeed, // txtGrp.updateMatrixWorld(); - var toCut = txtGrp.clone(); //Copia delle linee di cui deve ancora fare il gocde. - var actual_position = new THREE.Vector2( 0, 0 ); //Posizione attuale del LASER + var toCut = txtGrp.clone(); + var current_position = new THREE.Vector2( 0, 0 ); while( toCut.children.length > 0 ){ - console.log("Element ", toCut.children.length); - var opt_distance = distance_2p( get_cut_begin_point( toCut, 0 ), actual_position ); + var opt_distance = current_position.distanceToSquared( get_cut_begin_point( toCut, 0 ) ); var opt_cut = 0; - //g+= "Calcolo "+toCut.children.length+" distanze\n\n"; - for( i = 0; i < toCut.children.length; i++ ){ // Scorre i segmenti da disegnare cercando iil più vicino - var distance = distance_2p( get_cut_begin_point( toCut, i ), actual_position ); - // g+=i+": "+distance+" mm\n"; + var cut_reverse = 0; + for( i = 0; i < toCut.children.length; i++ ){ + var distance = current_position.distanceToSquared( get_cut_begin_point( toCut, i ) ); if( distance < opt_distance ){ opt_distance = distance; opt_cut = i; + cut_reverse = 0; } } - //g+="Distanza ottimale "+opt_cut+": "+opt_distance+" mm\n"; - //opt_cut = 0; //QUESTA LINEA FA SEMPLICEMENTE ESEGUIRE IL TAGLIO IN ORDINE. - actual_position = get_cut_end_point( toCut, opt_cut ); - child = toCut.children[opt_cut].clone(); + for( i = 0; i < toCut.children.length; i++ ){ + var distance = current_position.distanceToSquared( get_cut_end_point( toCut, i ) ); + if( distance < opt_distance ){ + opt_distance = distance; + opt_cut = i; + cut_reverse = 1; + } + } + + if( cut_reverse ) + current_position = get_cut_begin_point( toCut, opt_cut ); + else + current_position = get_cut_end_point( toCut, opt_cut ); + child = toCut.children[opt_cut].clone(); + if (child.type == "Line") { var xpos_offset = child.position.x; var ypos_offset = child.position.y; - + if( cut_reverse ) + child.geometry.vertices = child.geometry.vertices.reverse(); // let's create gcode for all points in line for (i = 0; i < child.geometry.vertices.length; i++) { @@ -372,8 +379,6 @@ function generate_optimized_Gcode(threeGroup, objectseq, cutSpeed, plungeSpeed, toCut.remove( toCut.children[opt_cut] ); } - - //FAGLI STAMPARE TUTTI I PUNTI E CONTROLLA DOVE SONO DAVVERO console.log("Generated gcode. length:", g.length); console.log(" "); isGcodeInRegeneratingState = false; From 494dc26dc8b9e154111165953c21d8aa2a11637d Mon Sep 17 00:00:00 2001 From: Mattia Bondanza Date: Wed, 4 Jan 2017 20:07:29 +0100 Subject: [PATCH 3/7] Removed original generateGcode function, added a parameter to select what kind of optimization perform. --- public/js/threegcode.js | 228 +++++++--------------------------------- 1 file changed, 38 insertions(+), 190 deletions(-) diff --git a/public/js/threegcode.js b/public/js/threegcode.js index 531ebbb4..091c068f 100644 --- a/public/js/threegcode.js +++ b/public/js/threegcode.js @@ -24,6 +24,9 @@ $(document).ready(function() { var lasermultiply = document.getElementById('lasermultiply').value; var homingseq = document.getElementById('homingseq').value; var endgcode = document.getElementById('endgcode').value; + //"none"=doesn't change cutting order, "standard"=optimize using cartesian distance, "manhattan"=optimize using manhattan distance. + var optimization = "standard"; + cncMode = $('#cncMode').val() if (cncMode == "Enable") { var clearanceHeight = document.getElementById('clearanceHeight').value; @@ -68,7 +71,7 @@ $(document).ready(function() { if (objectsInScene[j].userData.inflated) { // g += generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); printLog('Separate Operation for ' + objectsInScene[j].name, msgcolor, "file") - objectsInScene[j].userData.gcode = generate_optimized_Gcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); + objectsInScene[j].userData.gcode = generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, optimization); } else { // g += generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); if (passes > 1) { @@ -77,11 +80,11 @@ $(document).ready(function() { for (m = 0; m < passes; m++) { console.log("Mulipass Layer: " + m); var zoffset = passdepth * m; - gcodewithmultipass += generate_optimized_Gcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset); + gcodewithmultipass += generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset, optimization); } objectsInScene[j].userData.gcode = gcodewithmultipass; } else { - objectsInScene[j].userData.gcode = generate_optimized_Gcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset); + objectsInScene[j].userData.gcode = generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset, optimization); } } @@ -183,7 +186,7 @@ function get_cut_end_point( threeGroup, i ){ return new THREE.Vector2( xpos, ypos ); } -function generate_optimized_Gcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset) { +function generateGcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset, optimization) { var laserPwrVal = 0.0; // console.log('inside generateGcode') @@ -232,26 +235,42 @@ function generate_optimized_Gcode(threeGroup, objectseq, cutSpeed, plungeSpeed, var current_position = new THREE.Vector2( 0, 0 ); while( toCut.children.length > 0 ){ - var opt_distance = current_position.distanceToSquared( get_cut_begin_point( toCut, 0 ) ); var opt_cut = 0; var cut_reverse = 0; - for( i = 0; i < toCut.children.length; i++ ){ - var distance = current_position.distanceToSquared( get_cut_begin_point( toCut, i ) ); - if( distance < opt_distance ){ - opt_distance = distance; - opt_cut = i; - cut_reverse = 0; + + if( optimization != "none" ){ + var opt_distance; + if( optimization == "manhattan" ) + opt_distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, 0 ) ); + else + opt_distance = current_position.distanceToSquared( get_cut_begin_point( toCut, 0 ) ); + for( i = 0; i < toCut.children.length; i++ ){ + var distance; + if( optimization == "manhattan" ) + distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, i ) ); + else + distance = current_position.distanceToSquared( get_cut_begin_point( toCut, i ) ); + if( distance < opt_distance ){ + opt_distance = distance; + opt_cut = i; + cut_reverse = 0; + } } - } - for( i = 0; i < toCut.children.length; i++ ){ - var distance = current_position.distanceToSquared( get_cut_end_point( toCut, i ) ); - if( distance < opt_distance ){ - opt_distance = distance; - opt_cut = i; - cut_reverse = 1; + for( i = 0; i < toCut.children.length; i++ ){ + var distance; + if( optimization == "manhattan" ) + distance = current_position.distanceToManhattan( get_cut_end_point( toCut, i ) ); + else + distance = current_position.distanceToSquared( get_cut_end_point( toCut, i ) ); + + if( distance < opt_distance ){ + opt_distance = distance; + opt_cut = i; + cut_reverse = 1; + } } } - + if( cut_reverse ) current_position = get_cut_begin_point( toCut, opt_cut ); else @@ -385,177 +404,6 @@ function generate_optimized_Gcode(threeGroup, objectseq, cutSpeed, plungeSpeed, return g; }; - -function generateGcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset) { - - var laserPwrVal = 0.0; - // console.log('inside generateGcode') - // console.log('Group', threeGroup); - // console.log('CutSpeed', cutSpeed); - // console.log('plungeSpeed', plungeSpeed); - // console.log('Laser Power %', laserPwr); - var lasermultiply = $('#lasermultiply').val(); - // console.log('Laser Multiplier', lasermultiply); - - if (lasermultiply <= 1) { - var laserPwrVal = laserPwr / 100; - laserPwrVal = parseFloat(laserPwrVal).toFixed(2); - } else { - var laserPwrVal = laserPwr * (lasermultiply / 100); - laserPwrVal = laserPwrVal.toFixed(0); - } - // console.log('Laser Power Value', laserPwrVal, ' type of ', typeof(laserPwrVal)); - - var g = ""; - // get the THREE.Group() that is the txt3d - - var txtGrp = threeGroup; - var that = this; - var isLaserOn = false; - var isAtClearanceHeight = false; - var isFeedrateSpecifiedAlready = false; - var isSeekrateSpecifiedAlready = false; - - - var cncMode = false; - - if ($('#cncMode').val() == "Enable") { - cncMode = true; - } - - // var subj_path2 = []; - // var subj_paths = []; - // console.log(txtGrp); - // console.log(rapidSpeed) - // console.log(cutSpeed); - - // txtGrp.updateMatrixWorld(); - - txtGrp.traverse(function(child) { - // console.log(child); - if (child.type == "Line") { - - var xpos_offset = child.position.x; - var ypos_offset = child.position.y; - - - // let's create gcode for all points in line - for (i = 0; i < child.geometry.vertices.length; i++) { - - // Convert to World Coordinates - var localPt = child.geometry.vertices[i]; - var worldPt = txtGrp.localToWorld(localPt.clone()); - var xpos = worldPt.x + (parseFloat(laserxmax) / 2); - var ypos = worldPt.y + (parseFloat(laserymax) / 2); - - - if (child.geometry.type == "CircleGeometry") { - xpos = (xpos + xpos_offset); - ypos = (ypos + ypos_offset); - } - - - var zpos = worldPt.z; - - if (zoffset) { - zpos = zpos - zoffset; - } - - - // First Move To - if (i == 0) { - // first point in line where we start lasering/milling - var seekrate; - if (isSeekrateSpecifiedAlready) { - seekrate = ""; - } else { - // console.log('Rapid Speed: ', rapidSpeed); - if (rapidSpeed) { - seekrate = " F" + rapidSpeed; - isSeekrateSpecifiedAlready = true; - } else { - seekrate = ""; - } - - } - if (cncMode) { - if (!isAtClearanceHeight) { - g += "\nG0 Z" + clearanceHeight + "\n"; // Position Before Plunge! - } - }; - g += "G0" + seekrate; - g += " X" + xpos.toFixed(4) + " Y" + ypos.toFixed(4) + "\n"; - if (cncMode) { - g += "\nG0 Z1\n"; // G0 to Z0 then Plunge! - g += "G1 F"+plungeSpeed+" Z" + zpos.toFixed(4) + "\n"; // Plunge!!!! - } else { - if (isFeedrateSpecifiedAlready) { - } else { - // console.log('Cut Speed: ', cutSpeed); - if (cutSpeed) { - feedrate = " F" + cutSpeed; - isFeedrateSpecifiedAlready = true; - } else { - feedrate = ""; - } - } - g += "G1" + feedrate + " X" + xpos.toFixed(4) + " Y" + ypos.toFixed(4) + " Z" + zpos.toFixed(4) + "\n"; - }; - isAtClearanceHeight = false; - // Else Cut move - } else { - // we are in a non-first line so this is normal moving - // if the laser is not on, we need to turn it on - if (!isLaserOn) { - if (laseron) { - g += laseron - g += '\n' - } else { - // Nothing - most of the firmware used G0 = move, G1 = cut and doesnt need a laseron/laseroff command - }; - isLaserOn = true; - } - - // do normal feedrate move - var feedrate; - if (isFeedrateSpecifiedAlready) { - } else { - console.log('Cut Speed: ', cutSpeed); - if (cutSpeed) { - feedrate = " F" + cutSpeed; - isFeedrateSpecifiedAlready = true; - } else { - feedrate = ""; - } - } - g += "G1" + feedrate; - g += " X" + xpos.toFixed(4); - g += " Y" + ypos.toFixed(4); - g += " Z" + zpos.toFixed(4); - g += " S" + laserPwrVal + "\n"; - } - } - - - - // make feedrate have to get specified again on next line if there is one - isFeedrateSpecifiedAlready = false; - isLaserOn = false; - // if (firmware.indexOf('Grbl') == 0) { - if (laseroff) { - g += laseroff - g += '\n' - } else { - // Nothing - most of the firmware used G0 = move, G1 = cut and doesnt need a laseron/laseroff command - } - } - }); - console.log("Generated gcode. length:", g.length); - console.log(" "); - isGcodeInRegeneratingState = false; - return g; -}; - addOperation = function(index, operation, zstep, zdepth) { // This assumes that operation is one of a fixed set of values. From a9dafcf1c605179fe1d34fbd6303701b198f8553 Mon Sep 17 00:00:00 2001 From: Mattia Bondanza Date: Wed, 4 Jan 2017 22:07:54 +0100 Subject: [PATCH 4/7] Added the select for the optimization kind in the web interface. --- public/js/simple-cam.js | 10 ++++++++++ public/js/threegcode.js | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/public/js/simple-cam.js b/public/js/simple-cam.js index 7c941556..e1670574 100644 --- a/public/js/simple-cam.js +++ b/public/js/simple-cam.js @@ -172,6 +172,16 @@ function fillEasyCam() { mm/s +
+ +
+ +
+
diff --git a/public/js/threegcode.js b/public/js/threegcode.js index 091c068f..95a0fb86 100644 --- a/public/js/threegcode.js +++ b/public/js/threegcode.js @@ -24,8 +24,6 @@ $(document).ready(function() { var lasermultiply = document.getElementById('lasermultiply').value; var homingseq = document.getElementById('homingseq').value; var endgcode = document.getElementById('endgcode').value; - //"none"=doesn't change cutting order, "standard"=optimize using cartesian distance, "manhattan"=optimize using manhattan distance. - var optimization = "standard"; cncMode = $('#cncMode').val() if (cncMode == "Enable") { @@ -68,6 +66,8 @@ $(document).ready(function() { var passes = parseInt( $("#passes"+(j)).val() ); var passdepth = parseFloat( $("#depth"+(j)).val() ); var rapidSpeed = parseFloat($("#rapidspeed").val() ) * 60; + //"none"=doesn't change cutting order, "standard"=optimize using cartesian distance, "manhattan"=optimize using manhattan distance. + var optimization = $("#optimization_mode"+(j)).val(); if (objectsInScene[j].userData.inflated) { // g += generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); printLog('Separate Operation for ' + objectsInScene[j].name, msgcolor, "file") From f1c0006928ea2fbe98680a6f21db4a3c92433f11 Mon Sep 17 00:00:00 2001 From: Mattia Bondanza Date: Thu, 5 Jan 2017 10:17:21 +0100 Subject: [PATCH 5/7] Added a condition on generation of G0 codes: if the next cut is at a distance 0 from the previous, does not execute the G0 move. --- public/js/threegcode.js | 44 +++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/public/js/threegcode.js b/public/js/threegcode.js index 95a0fb86..a9c8c32d 100644 --- a/public/js/threegcode.js +++ b/public/js/threegcode.js @@ -24,7 +24,7 @@ $(document).ready(function() { var lasermultiply = document.getElementById('lasermultiply').value; var homingseq = document.getElementById('homingseq').value; var endgcode = document.getElementById('endgcode').value; - + cncMode = $('#cncMode').val() if (cncMode == "Enable") { var clearanceHeight = document.getElementById('clearanceHeight').value; @@ -66,8 +66,8 @@ $(document).ready(function() { var passes = parseInt( $("#passes"+(j)).val() ); var passdepth = parseFloat( $("#depth"+(j)).val() ); var rapidSpeed = parseFloat($("#rapidspeed").val() ) * 60; - //"none"=doesn't change cutting order, "standard"=optimize using cartesian distance, "manhattan"=optimize using manhattan distance. - var optimization = $("#optimization_mode"+(j)).val(); + //"none"=doesn't change cutting order, "standard"=optimize using cartesian distance, "manhattan"=optimize using manhattan distance. + var optimization = $("#optimization_mode"+(j)).val(); if (objectsInScene[j].userData.inflated) { // g += generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); printLog('Separate Operation for ' + objectsInScene[j].name, msgcolor, "file") @@ -160,12 +160,12 @@ function get_cut_begin_point( threeGroup, i ){ var xpos_offset = threeGroup.children[i].position.x; var ypos_offset = threeGroup.children[i].position.y; - + if (threeGroup.children[i].geometry.type == "CircleGeometry") { xpos = (xpos + xpos_offset); ypos = (ypos + ypos_offset); } - + return new THREE.Vector2( xpos, ypos ); } @@ -177,12 +177,12 @@ function get_cut_end_point( threeGroup, i ){ var xpos_offset = threeGroup.children[i].position.x; var ypos_offset = threeGroup.children[i].position.y; - + if (threeGroup.children[i].geometry.type == "CircleGeometry") { xpos = (xpos + xpos_offset); ypos = (ypos + ypos_offset); } - + return new THREE.Vector2( xpos, ypos ); } @@ -237,18 +237,23 @@ function generateGcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, r while( toCut.children.length > 0 ){ var opt_cut = 0; var cut_reverse = 0; + //If is found a cut at a distance 0 from the current_position, there is no need + //to add a G0 move that turns off the laser. + var need_move_to = 1; + if( optimization != "none" ){ var opt_distance; if( optimization == "manhattan" ) opt_distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, 0 ) ); - else + else opt_distance = current_position.distanceToSquared( get_cut_begin_point( toCut, 0 ) ); + for( i = 0; i < toCut.children.length; i++ ){ - var distance; + var distance; if( optimization == "manhattan" ) distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, i ) ); - else + else distance = current_position.distanceToSquared( get_cut_begin_point( toCut, i ) ); if( distance < opt_distance ){ opt_distance = distance; @@ -256,35 +261,37 @@ function generateGcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, r cut_reverse = 0; } } + for( i = 0; i < toCut.children.length; i++ ){ - var distance; + var distance; if( optimization == "manhattan" ) distance = current_position.distanceToManhattan( get_cut_end_point( toCut, i ) ); - else + else distance = current_position.distanceToSquared( get_cut_end_point( toCut, i ) ); - + if( distance < opt_distance ){ opt_distance = distance; opt_cut = i; cut_reverse = 1; } } + + if( opt_distance == 0 ) need_move_to = 0; } - + if( cut_reverse ) current_position = get_cut_begin_point( toCut, opt_cut ); else current_position = get_cut_end_point( toCut, opt_cut ); child = toCut.children[opt_cut].clone(); - - if (child.type == "Line") { + if (child.type == "Line") { var xpos_offset = child.position.x; var ypos_offset = child.position.y; if( cut_reverse ) - child.geometry.vertices = child.geometry.vertices.reverse(); + child.geometry.vertices = child.geometry.vertices.reverse(); // let's create gcode for all points in line for (i = 0; i < child.geometry.vertices.length; i++) { @@ -309,7 +316,7 @@ function generateGcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, r // First Move To - if (i == 0) { + if (i == 0 && need_move_to == 1 ){ // first point in line where we start lasering/milling var seekrate; if (isSeekrateSpecifiedAlready) { @@ -831,4 +838,3 @@ drawClipperPaths = function(paths, color, opacity, z, isClosed, name) { } return group; }; - From 5c810eb513d6ffd5563f76148c60f503f24b858e Mon Sep 17 00:00:00 2001 From: Mattia Bondanza Date: Sun, 8 Jan 2017 14:41:41 +0100 Subject: [PATCH 6/7] Indentation. --- public/js/simple-cam.js | 8 +- public/js/threegcode.js | 1340 +++++++++++++++++++-------------------- 2 files changed, 674 insertions(+), 674 deletions(-) diff --git a/public/js/simple-cam.js b/public/js/simple-cam.js index e1670574..749960de 100644 --- a/public/js/simple-cam.js +++ b/public/js/simple-cam.js @@ -177,8 +177,8 @@ function fillEasyCam() {
@@ -214,7 +214,7 @@ function fillEasyCam() { layerprep += template; } } else if (objectsInScene[i].type == 'Mesh') { - + if (typeof(object) != 'undefined') { scene.remove(object); }; @@ -226,7 +226,7 @@ function fillEasyCam() { var xpos = objectsInScene[i].position.x var ypos = objectsInScene[i].position.y // var seq = objectsInScene[i].userData.seq; - + var scale = objectsInScene[i].scale.y; // scale was already initialized during bitmap load, and may have been changed // We want to set the UI to the actual scale value instead of a default value here diff --git a/public/js/threegcode.js b/public/js/threegcode.js index a9c8c32d..a166d039 100644 --- a/public/js/threegcode.js +++ b/public/js/threegcode.js @@ -1,6 +1,6 @@ /* - AUTHOR: Peter van der Walt - Based on code from: John Lauer, Todd Fleming, Nicholas Raynaud and others +AUTHOR: Peter van der Walt +Based on code from: John Lauer, Todd Fleming, Nicholas Raynaud and others */ var inflateGrp, fileParentGroup, svgPath, y, shape, lines, line; var options = {}; @@ -8,115 +8,115 @@ var options = {}; $(document).ready(function() { - $('#generategcode').on('click', function() { - console.group("Generating GCODE"); - for (j = 0; j < objectsInScene.length; j++) { - // Cleanup Existing GCODE - objectsInScene[j].userData.gcode = ""; - } - if (typeof(fileObject) == 'undefined') { - printLog('No file loaded. do, File -> Open, first!', errorcolor, "file") - }; - // Lets get the machine specific Gcode from the settings Modal (: - var startgcode = document.getElementById('startgcode').value; - var laseron = document.getElementById('laseron').value; - var laseroff = document.getElementById('laseroff').value; - var lasermultiply = document.getElementById('lasermultiply').value; - var homingseq = document.getElementById('homingseq').value; - var endgcode = document.getElementById('endgcode').value; - - cncMode = $('#cncMode').val() - if (cncMode == "Enable") { - var clearanceHeight = document.getElementById('clearanceHeight').value; - } else { - var clearanceHeight = 0 - } - - // Remove old Gcode - // document.getElementById('gcodepreview').value = ""; - $('#gcodejobs').empty(); - lineObjects = null; - lineObjects = new THREE.Object3D(); - var total = scene.children.length - for (var j = 6; j < total; j++) { - scene.remove(scene.children[j]); - } - for (var j = 0; j < objectsInScene.length; j++) { - // console.log('added object ' + j) - scene.add(objectsInScene[j]); - } + $('#generategcode').on('click', function() { + console.group("Generating GCODE"); + for (j = 0; j < objectsInScene.length; j++) { + // Cleanup Existing GCODE + objectsInScene[j].userData.gcode = ""; + } + if (typeof(fileObject) == 'undefined') { + printLog('No file loaded. do, File -> Open, first!', errorcolor, "file") + }; + // Lets get the machine specific Gcode from the settings Modal (: + var startgcode = document.getElementById('startgcode').value; + var laseron = document.getElementById('laseron').value; + var laseroff = document.getElementById('laseroff').value; + var lasermultiply = document.getElementById('lasermultiply').value; + var homingseq = document.getElementById('homingseq').value; + var endgcode = document.getElementById('endgcode').value; + + cncMode = $('#cncMode').val() + if (cncMode == "Enable") { + var clearanceHeight = document.getElementById('clearanceHeight').value; + } else { + var clearanceHeight = 0 + } - scene.updateMatrixWorld(); - pwr = []; - cutSpeed = []; - - for (j = 0; j < objectsInScene.length; j++) { - printLog('Processing ' + objectsInScene[j].name, msgcolor, "file"); - // This step converts each object in objectsInScene, to gcode and puts that gcode into objectsInScene[j].userData.gcode - to be later assembled into a gcode file with proper sequence - objectsInScene[j].updateMatrix(); - if (objectsInScene[j].name != 'object') { - if (objectsInScene[j].type == "Mesh") { - console.log('Object: '+objectsInScene[j].name+' is a Raster') - runRaster(j) - } else { - console.log('Object: '+objectsInScene[j].name+' is a Vector'); - var cutSpeed0 = parseFloat( $("#speed"+(j)).val() ) * 60; - var pwr0 = parseFloat( $("#power"+(j)).val() ); - var plungeSpeed0 = parseFloat( $("#plungespeed"+(j)).val() ) * 60; - var passes = parseInt( $("#passes"+(j)).val() ); - var passdepth = parseFloat( $("#depth"+(j)).val() ); - var rapidSpeed = parseFloat($("#rapidspeed").val() ) * 60; - //"none"=doesn't change cutting order, "standard"=optimize using cartesian distance, "manhattan"=optimize using manhattan distance. - var optimization = $("#optimization_mode"+(j)).val(); - if (objectsInScene[j].userData.inflated) { - // g += generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); - printLog('Separate Operation for ' + objectsInScene[j].name, msgcolor, "file") - objectsInScene[j].userData.gcode = generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, optimization); - } else { - // g += generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); - if (passes > 1) { - console.log("Mulipass Layers to generate: " + passes); - var gcodewithmultipass = ""; - for (m = 0; m < passes; m++) { - console.log("Mulipass Layer: " + m); - var zoffset = passdepth * m; - gcodewithmultipass += generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset, optimization); - } - objectsInScene[j].userData.gcode = gcodewithmultipass; - } else { - objectsInScene[j].userData.gcode = generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset, optimization); - } - - } - var template = ` -
- - -
` - - $('#gcodejobs').append(template); - - $('#gcode'+i).val(objectsInScene[j].userData.gcode); - - var startgcode = document.getElementById('startgcode').value; - var endgcode = document.getElementById('endgcode').value; - - $('#startgcodefinal').val(startgcode) - $('#endgcodefinal').val(endgcode); - - printLog('Gcode Data Generated for ' +objectsInScene[j].name , successcolor, "file"); - // prepgcodefile(); + // Remove old Gcode + // document.getElementById('gcodepreview').value = ""; + $('#gcodejobs').empty(); + lineObjects = null; + lineObjects = new THREE.Object3D(); + var total = scene.children.length + for (var j = 6; j < total; j++) { + scene.remove(scene.children[j]); + } + for (var j = 0; j < objectsInScene.length; j++) { + // console.log('added object ' + j) + scene.add(objectsInScene[j]); + } + scene.updateMatrixWorld(); + pwr = []; + cutSpeed = []; + + for (j = 0; j < objectsInScene.length; j++) { + printLog('Processing ' + objectsInScene[j].name, msgcolor, "file"); + // This step converts each object in objectsInScene, to gcode and puts that gcode into objectsInScene[j].userData.gcode - to be later assembled into a gcode file with proper sequence + objectsInScene[j].updateMatrix(); + if (objectsInScene[j].name != 'object') { + if (objectsInScene[j].type == "Mesh") { + console.log('Object: '+objectsInScene[j].name+' is a Raster') + runRaster(j) + } else { + console.log('Object: '+objectsInScene[j].name+' is a Vector'); + var cutSpeed0 = parseFloat( $("#speed"+(j)).val() ) * 60; + var pwr0 = parseFloat( $("#power"+(j)).val() ); + var plungeSpeed0 = parseFloat( $("#plungespeed"+(j)).val() ) * 60; + var passes = parseInt( $("#passes"+(j)).val() ); + var passdepth = parseFloat( $("#depth"+(j)).val() ); + var rapidSpeed = parseFloat($("#rapidspeed").val() ) * 60; + //"none"=doesn't change cutting order, "standard"=optimize using cartesian distance, "manhattan"=optimize using manhattan distance. + var optimization = $("#optimization_mode"+(j)).val(); + if (objectsInScene[j].userData.inflated) { + // g += generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); + printLog('Separate Operation for ' + objectsInScene[j].name, msgcolor, "file") + objectsInScene[j].userData.gcode = generateGcode(objectsInScene[j].userData.inflated, j, cutSpeed0, plungeSpeed0, pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, optimization); + } else { + // g += generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight); + if (passes > 1) { + console.log("Mulipass Layers to generate: " + passes); + var gcodewithmultipass = ""; + for (m = 0; m < passes; m++) { + console.log("Mulipass Layer: " + m); + var zoffset = passdepth * m; + gcodewithmultipass += generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset, optimization); } + objectsInScene[j].userData.gcode = gcodewithmultipass; + } else { + objectsInScene[j].userData.gcode = generateGcode(objectsInScene[j], j, cutSpeed0, plungeSpeed0 ,pwr0, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset, optimization); } + + } + var template = ` +
+ + +
` + + $('#gcodejobs').append(template); + + $('#gcode'+i).val(objectsInScene[j].userData.gcode); + + var startgcode = document.getElementById('startgcode').value; + var endgcode = document.getElementById('endgcode').value; + + $('#startgcodefinal').val(startgcode) + $('#endgcodefinal').val(endgcode); + + printLog('Gcode Data Generated for ' +objectsInScene[j].name , successcolor, "file"); + // prepgcodefile(); + } - scene.remove(inflateGrp); + } + } + scene.remove(inflateGrp); - $('#gcode-menu').click(); - console.groupEnd(); - console.log('running openGCodeFromText') - openGCodeFromText(); - }); + $('#gcode-menu').click(); + console.groupEnd(); + console.log('running openGCodeFromText') + openGCodeFromText(); + }); }); function prepgcodefile() { @@ -135,14 +135,14 @@ function prepgcodefile() { } for (j = 0; j < objectsInScene.length; j++) { - printLog('Preparing Gcode File: ' + objectsInScene[j].name, msgcolor, "file"); - console.log('Preparing Gcode File: ' + objectsInScene[j].name); - // document.getElementById('gcodepreview').value = ""; - if (typeof(objectsInScene[j].userData.gcode) != "undefined") { - g += objectsInScene[j].userData.gcode; - } else { - console.log(objectsInScene[j].name + ' does not have valid gcode yet'); - } + printLog('Preparing Gcode File: ' + objectsInScene[j].name, msgcolor, "file"); + console.log('Preparing Gcode File: ' + objectsInScene[j].name); + // document.getElementById('gcodepreview').value = ""; + if (typeof(objectsInScene[j].userData.gcode) != "undefined") { + g += objectsInScene[j].userData.gcode; + } else { + console.log(objectsInScene[j].name + ' does not have valid gcode yet'); + } } g += "\n"; if (endgcode) { @@ -153,262 +153,262 @@ function prepgcodefile() { } function get_cut_begin_point( threeGroup, i ){ - var localPt = threeGroup.children[i].geometry.vertices[0]; - var worldPt = threeGroup.localToWorld(localPt.clone()); - var xpos = worldPt.x + (parseFloat(laserxmax) / 2); - var ypos = worldPt.y + (parseFloat(laserymax) / 2); + var localPt = threeGroup.children[i].geometry.vertices[0]; + var worldPt = threeGroup.localToWorld(localPt.clone()); + var xpos = worldPt.x + (parseFloat(laserxmax) / 2); + var ypos = worldPt.y + (parseFloat(laserymax) / 2); - var xpos_offset = threeGroup.children[i].position.x; - var ypos_offset = threeGroup.children[i].position.y; + var xpos_offset = threeGroup.children[i].position.x; + var ypos_offset = threeGroup.children[i].position.y; - if (threeGroup.children[i].geometry.type == "CircleGeometry") { - xpos = (xpos + xpos_offset); - ypos = (ypos + ypos_offset); - } + if (threeGroup.children[i].geometry.type == "CircleGeometry") { + xpos = (xpos + xpos_offset); + ypos = (ypos + ypos_offset); + } - return new THREE.Vector2( xpos, ypos ); + return new THREE.Vector2( xpos, ypos ); } function get_cut_end_point( threeGroup, i ){ - var localPt = threeGroup.children[i].geometry.vertices[ threeGroup.children[i].geometry.vertices.length - 1 ]; - var worldPt = threeGroup.localToWorld(localPt.clone()); - var xpos = worldPt.x + (parseFloat(laserxmax) / 2); - var ypos = worldPt.y + (parseFloat(laserymax) / 2); + var localPt = threeGroup.children[i].geometry.vertices[ threeGroup.children[i].geometry.vertices.length - 1 ]; + var worldPt = threeGroup.localToWorld(localPt.clone()); + var xpos = worldPt.x + (parseFloat(laserxmax) / 2); + var ypos = worldPt.y + (parseFloat(laserymax) / 2); - var xpos_offset = threeGroup.children[i].position.x; - var ypos_offset = threeGroup.children[i].position.y; + var xpos_offset = threeGroup.children[i].position.x; + var ypos_offset = threeGroup.children[i].position.y; - if (threeGroup.children[i].geometry.type == "CircleGeometry") { - xpos = (xpos + xpos_offset); - ypos = (ypos + ypos_offset); - } + if (threeGroup.children[i].geometry.type == "CircleGeometry") { + xpos = (xpos + xpos_offset); + ypos = (ypos + ypos_offset); + } - return new THREE.Vector2( xpos, ypos ); + return new THREE.Vector2( xpos, ypos ); } function generateGcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, rapidSpeed, laseron, laseroff, clearanceHeight, zoffset, optimization) { - var laserPwrVal = 0.0; - // console.log('inside generateGcode') - // console.log('Group', threeGroup); - // console.log('CutSpeed', cutSpeed); - // console.log('plungeSpeed', plungeSpeed); - // console.log('Laser Power %', laserPwr); - var lasermultiply = $('#lasermultiply').val(); - // console.log('Laser Multiplier', lasermultiply); - - if (lasermultiply <= 1) { - var laserPwrVal = laserPwr / 100; - laserPwrVal = parseFloat(laserPwrVal).toFixed(2); - } else { - var laserPwrVal = laserPwr * (lasermultiply / 100); - laserPwrVal = laserPwrVal.toFixed(0); - } - // console.log('Laser Power Value', laserPwrVal, ' type of ', typeof(laserPwrVal)); + var laserPwrVal = 0.0; + // console.log('inside generateGcode') + // console.log('Group', threeGroup); + // console.log('CutSpeed', cutSpeed); + // console.log('plungeSpeed', plungeSpeed); + // console.log('Laser Power %', laserPwr); + var lasermultiply = $('#lasermultiply').val(); + // console.log('Laser Multiplier', lasermultiply); + + if (lasermultiply <= 1) { + var laserPwrVal = laserPwr / 100; + laserPwrVal = parseFloat(laserPwrVal).toFixed(2); + } else { + var laserPwrVal = laserPwr * (lasermultiply / 100); + laserPwrVal = laserPwrVal.toFixed(0); + } + // console.log('Laser Power Value', laserPwrVal, ' type of ', typeof(laserPwrVal)); - var g = ""; - // get the THREE.Group() that is the txt3d + var g = ""; + // get the THREE.Group() that is the txt3d - var txtGrp = threeGroup; - var that = this; - var isLaserOn = false; - var isAtClearanceHeight = false; - var isFeedrateSpecifiedAlready = false; - var isSeekrateSpecifiedAlready = false; + var txtGrp = threeGroup; + var that = this; + var isLaserOn = false; + var isAtClearanceHeight = false; + var isFeedrateSpecifiedAlready = false; + var isSeekrateSpecifiedAlready = false; - var cncMode = false; + var cncMode = false; + + if ($('#cncMode').val() == "Enable") { + cncMode = true; + } - if ($('#cncMode').val() == "Enable") { - cncMode = true; + // var subj_path2 = []; + // var subj_paths = []; + // console.log(txtGrp); + // console.log(rapidSpeed) + // console.log(cutSpeed); + + // txtGrp.updateMatrixWorld(); + + var toCut = txtGrp.clone(); + var current_position = new THREE.Vector2( 0, 0 ); + + while( toCut.children.length > 0 ){ + var opt_cut = 0; + var cut_reverse = 0; + //If is found a cut at a distance 0 from the current_position, there is no need + //to add a G0 move that turns off the laser. + var need_move_to = 1; + + + if( optimization != "none" ){ + var opt_distance; + if( optimization == "manhattan" ) + opt_distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, 0 ) ); + else + opt_distance = current_position.distanceToSquared( get_cut_begin_point( toCut, 0 ) ); + + for( i = 0; i < toCut.children.length; i++ ){ + var distance; + if( optimization == "manhattan" ) + distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, i ) ); + else + distance = current_position.distanceToSquared( get_cut_begin_point( toCut, i ) ); + if( distance < opt_distance ){ + opt_distance = distance; + opt_cut = i; + cut_reverse = 0; + } + } + + for( i = 0; i < toCut.children.length; i++ ){ + var distance; + if( optimization == "manhattan" ) + distance = current_position.distanceToManhattan( get_cut_end_point( toCut, i ) ); + else + distance = current_position.distanceToSquared( get_cut_end_point( toCut, i ) ); + + if( distance < opt_distance ){ + opt_distance = distance; + opt_cut = i; + cut_reverse = 1; + } + } + + if( opt_distance == 0 ) need_move_to = 0; } - // var subj_path2 = []; - // var subj_paths = []; - // console.log(txtGrp); - // console.log(rapidSpeed) - // console.log(cutSpeed); - - // txtGrp.updateMatrixWorld(); - - var toCut = txtGrp.clone(); - var current_position = new THREE.Vector2( 0, 0 ); - - while( toCut.children.length > 0 ){ - var opt_cut = 0; - var cut_reverse = 0; - //If is found a cut at a distance 0 from the current_position, there is no need - //to add a G0 move that turns off the laser. - var need_move_to = 1; - - - if( optimization != "none" ){ - var opt_distance; - if( optimization == "manhattan" ) - opt_distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, 0 ) ); - else - opt_distance = current_position.distanceToSquared( get_cut_begin_point( toCut, 0 ) ); - - for( i = 0; i < toCut.children.length; i++ ){ - var distance; - if( optimization == "manhattan" ) - distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, i ) ); - else - distance = current_position.distanceToSquared( get_cut_begin_point( toCut, i ) ); - if( distance < opt_distance ){ - opt_distance = distance; - opt_cut = i; - cut_reverse = 0; - } - } - - for( i = 0; i < toCut.children.length; i++ ){ - var distance; - if( optimization == "manhattan" ) - distance = current_position.distanceToManhattan( get_cut_end_point( toCut, i ) ); - else - distance = current_position.distanceToSquared( get_cut_end_point( toCut, i ) ); - - if( distance < opt_distance ){ - opt_distance = distance; - opt_cut = i; - cut_reverse = 1; - } - } - - if( opt_distance == 0 ) need_move_to = 0; - } - - if( cut_reverse ) - current_position = get_cut_begin_point( toCut, opt_cut ); - else - current_position = get_cut_end_point( toCut, opt_cut ); - - child = toCut.children[opt_cut].clone(); - - if (child.type == "Line") { - var xpos_offset = child.position.x; - var ypos_offset = child.position.y; - - if( cut_reverse ) - child.geometry.vertices = child.geometry.vertices.reverse(); - // let's create gcode for all points in line - for (i = 0; i < child.geometry.vertices.length; i++) { - - // Convert to World Coordinates - var localPt = child.geometry.vertices[i]; - var worldPt = txtGrp.localToWorld(localPt.clone()); - var xpos = worldPt.x + (parseFloat(laserxmax) / 2); - var ypos = worldPt.y + (parseFloat(laserymax) / 2); - - - if (child.geometry.type == "CircleGeometry") { - xpos = (xpos + xpos_offset); - ypos = (ypos + ypos_offset); - } - - - var zpos = worldPt.z; - - if (zoffset) { - zpos = zpos - zoffset; - } - - - // First Move To - if (i == 0 && need_move_to == 1 ){ - // first point in line where we start lasering/milling - var seekrate; - if (isSeekrateSpecifiedAlready) { - seekrate = ""; - } else { - // console.log('Rapid Speed: ', rapidSpeed); - if (rapidSpeed) { - seekrate = " F" + rapidSpeed; - isSeekrateSpecifiedAlready = true; - } else { - seekrate = ""; - } - - } - if (cncMode) { - if (!isAtClearanceHeight) { - g += "\nG0 Z" + clearanceHeight + "\n"; // Position Before Plunge! - } - }; - g += "G0" + seekrate; - g += " X" + xpos.toFixed(4) + " Y" + ypos.toFixed(4) + "\n"; - if (cncMode) { - g += "\nG0 Z1\n"; // G0 to Z0 then Plunge! - g += "G1 F"+plungeSpeed+" Z" + zpos.toFixed(4) + "\n"; // Plunge!!!! - } else { - if (isFeedrateSpecifiedAlready) { - } else { - // console.log('Cut Speed: ', cutSpeed); - if (cutSpeed) { - feedrate = " F" + cutSpeed; - isFeedrateSpecifiedAlready = true; - } else { - feedrate = ""; - } - } - g += "G1" + feedrate + " X" + xpos.toFixed(4) + " Y" + ypos.toFixed(4) + " Z" + zpos.toFixed(4) + "\n"; - }; - isAtClearanceHeight = false; - // Else Cut move - } else { - // we are in a non-first line so this is normal moving - // if the laser is not on, we need to turn it on - if (!isLaserOn) { - if (laseron) { - g += laseron - g += '\n' - } else { - // Nothing - most of the firmware used G0 = move, G1 = cut and doesnt need a laseron/laseroff command - }; - isLaserOn = true; - } - - // do normal feedrate move - var feedrate; - if (isFeedrateSpecifiedAlready) { - } else { - console.log('Cut Speed: ', cutSpeed); - if (cutSpeed) { - feedrate = " F" + cutSpeed; - isFeedrateSpecifiedAlready = true; - } else { - feedrate = ""; - } - } - g += "G1" + feedrate; - g += " X" + xpos.toFixed(4); - g += " Y" + ypos.toFixed(4); - g += " Z" + zpos.toFixed(4); - g += " S" + laserPwrVal + "\n"; - } - } + if( cut_reverse ) + current_position = get_cut_begin_point( toCut, opt_cut ); + else + current_position = get_cut_end_point( toCut, opt_cut ); + + child = toCut.children[opt_cut].clone(); + + if (child.type == "Line") { + var xpos_offset = child.position.x; + var ypos_offset = child.position.y; + + if( cut_reverse ) + child.geometry.vertices = child.geometry.vertices.reverse(); + // let's create gcode for all points in line + for (i = 0; i < child.geometry.vertices.length; i++) { + + // Convert to World Coordinates + var localPt = child.geometry.vertices[i]; + var worldPt = txtGrp.localToWorld(localPt.clone()); + var xpos = worldPt.x + (parseFloat(laserxmax) / 2); + var ypos = worldPt.y + (parseFloat(laserymax) / 2); + + + if (child.geometry.type == "CircleGeometry") { + xpos = (xpos + xpos_offset); + ypos = (ypos + ypos_offset); + } + + + var zpos = worldPt.z; + + if (zoffset) { + zpos = zpos - zoffset; + } + // First Move To + if (i == 0 && need_move_to == 1 ){ + // first point in line where we start lasering/milling + var seekrate; + if (isSeekrateSpecifiedAlready) { + seekrate = ""; + } else { + // console.log('Rapid Speed: ', rapidSpeed); + if (rapidSpeed) { + seekrate = " F" + rapidSpeed; + isSeekrateSpecifiedAlready = true; + } else { + seekrate = ""; + } + + } + if (cncMode) { + if (!isAtClearanceHeight) { + g += "\nG0 Z" + clearanceHeight + "\n"; // Position Before Plunge! + } + }; + g += "G0" + seekrate; + g += " X" + xpos.toFixed(4) + " Y" + ypos.toFixed(4) + "\n"; + if (cncMode) { + g += "\nG0 Z1\n"; // G0 to Z0 then Plunge! + g += "G1 F"+plungeSpeed+" Z" + zpos.toFixed(4) + "\n"; // Plunge!!!! + } else { + if (isFeedrateSpecifiedAlready) { + } else { + // console.log('Cut Speed: ', cutSpeed); + if (cutSpeed) { + feedrate = " F" + cutSpeed; + isFeedrateSpecifiedAlready = true; + } else { + feedrate = ""; + } + } + g += "G1" + feedrate + " X" + xpos.toFixed(4) + " Y" + ypos.toFixed(4) + " Z" + zpos.toFixed(4) + "\n"; + }; + isAtClearanceHeight = false; + // Else Cut move + } else { + // we are in a non-first line so this is normal moving + // if the laser is not on, we need to turn it on + if (!isLaserOn) { + if (laseron) { + g += laseron + g += '\n' + } else { + // Nothing - most of the firmware used G0 = move, G1 = cut and doesnt need a laseron/laseroff command + }; + isLaserOn = true; + } - // make feedrate have to get specified again on next line if there is one - isFeedrateSpecifiedAlready = false; - isLaserOn = false; - // if (firmware.indexOf('Grbl') == 0) { - if (laseroff) { - g += laseroff - g += '\n' + // do normal feedrate move + var feedrate; + if (isFeedrateSpecifiedAlready) { + } else { + console.log('Cut Speed: ', cutSpeed); + if (cutSpeed) { + feedrate = " F" + cutSpeed; + isFeedrateSpecifiedAlready = true; } else { - // Nothing - most of the firmware used G0 = move, G1 = cut and doesnt need a laseron/laseroff command + feedrate = ""; } + } + g += "G1" + feedrate; + g += " X" + xpos.toFixed(4); + g += " Y" + ypos.toFixed(4); + g += " Z" + zpos.toFixed(4); + g += " S" + laserPwrVal + "\n"; } + } + + + + // make feedrate have to get specified again on next line if there is one + isFeedrateSpecifiedAlready = false; + isLaserOn = false; + // if (firmware.indexOf('Grbl') == 0) { + if (laseroff) { + g += laseroff + g += '\n' + } else { + // Nothing - most of the firmware used G0 = move, G1 = cut and doesnt need a laseron/laseroff command + } + } - toCut.remove( toCut.children[opt_cut] ); - } - console.log("Generated gcode. length:", g.length); - console.log(" "); - isGcodeInRegeneratingState = false; - return g; + toCut.remove( toCut.children[opt_cut] ); + } + console.log("Generated gcode. length:", g.length); + console.log(" "); + isGcodeInRegeneratingState = false; + return g; }; addOperation = function(index, operation, zstep, zdepth) { @@ -438,334 +438,334 @@ addOperation = function(index, operation, zstep, zdepth) { }; inflatePath = function(infobject, inflateVal, zstep, zdepth) { - var zstep = parseFloat(zstep, 2); - var zdepth = parseFloat(zdepth, 2); - var inflateGrpZ = new THREE.Group(); - if (typeof(inflateGrp) != 'undefined') { - scene.remove(inflateGrp); - inflateGrp = null; - } - // if (inflateVal != 0) { - console.log("user wants to inflate. val:", inflateVal); - infobject.updateMatrix(); - var grp = infobject; - 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 = grp.localToWorld(localPt.clone()); - var xpos = worldPt.x; - var ypos = worldPt.y; - - 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"); - } + var zstep = parseFloat(zstep, 2); + var zdepth = parseFloat(zdepth, 2); + var inflateGrpZ = new THREE.Group(); + if (typeof(inflateGrp) != 'undefined') { + scene.remove(inflateGrp); + inflateGrp = null; + } + // if (inflateVal != 0) { + console.log("user wants to inflate. val:", inflateVal); + infobject.updateMatrix(); + var grp = infobject; + 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 = grp.localToWorld(localPt.clone()); + var xpos = worldPt.x; + var ypos = worldPt.y; + + 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"); + } + }); - console.log("clipperPaths:", clipperPaths); + 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); + // 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!:"); - printLog('Clipper Simplification Failed!', errorcolor, "viewer"); - } + if (newClipperPaths.length < 1) { + console.error("Clipper Simplification Failed!:"); + printLog('Clipper Simplification Failed!', errorcolor, "viewer"); + } - // get the inflated/deflated path - var inflatedPaths = getInflatePath(newClipperPaths, inflateVal); + // get the inflated/deflated path + var inflatedPaths = getInflatePath(newClipperPaths, inflateVal); - for (i = 0; i < zdepth; i += zstep) { - inflateGrp = drawClipperPaths(inflatedPaths, 0xff00ff, 0.8, -i, true, "inflatedGroup"); // (paths, color, opacity, z, zstep, isClosed, isAddDirHelper, name, inflateVal) - inflateGrp.name = 'inflateGrp'; - if (inflateGrp.userData.color) { - inflateGrp.userData.color = inflateGrp.material.color.getHex(); - } - inflateGrp.position = infobject.position; - console.log(i); - inflateGrpZ.add(inflateGrp); - } - return inflateGrpZ; - // } + for (i = 0; i < zdepth; i += zstep) { + inflateGrp = drawClipperPaths(inflatedPaths, 0xff00ff, 0.8, -i, true, "inflatedGroup"); // (paths, color, opacity, z, zstep, isClosed, isAddDirHelper, name, inflateVal) + inflateGrp.name = 'inflateGrp'; + if (inflateGrp.userData.color) { + inflateGrp.userData.color = inflateGrp.material.color.getHex(); + } + inflateGrp.position = infobject.position; + console.log(i); + inflateGrpZ.add(inflateGrp); + } + return inflateGrpZ; + // } }; pocketPath = function(infobject, inflateVal, zstep, zdepth) { - var zstep = parseFloat(zstep, 2); - var zdepth = parseFloat(zdepth, 2); - var pocketGrp = new THREE.Group(); - if (typeof(inflateGrp) != 'undefined') { - scene.remove(inflateGrp); - inflateGrp = null; - } - if (inflateVal != 0) { - console.log("user wants to inflate. val:", inflateVal); - infobject.updateMatrix(); - var grp = infobject; - 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 = grp.localToWorld(localPt.clone()); - var xpos = (parseFloat(worldPt.x.toFixed(3))); - var ypos = (parseFloat(worldPt.y.toFixed(3))); - - 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"); - } - }); + var zstep = parseFloat(zstep, 2); + var zdepth = parseFloat(zdepth, 2); + var pocketGrp = new THREE.Group(); + if (typeof(inflateGrp) != 'undefined') { + scene.remove(inflateGrp); + inflateGrp = null; + } + if (inflateVal != 0) { + console.log("user wants to inflate. val:", inflateVal); + infobject.updateMatrix(); + var grp = infobject; + 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 = grp.localToWorld(localPt.clone()); + var xpos = (parseFloat(worldPt.x.toFixed(3))); + var ypos = (parseFloat(worldPt.y.toFixed(3))); + + 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); + } - 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!:"); - printLog('Clipper Simplification Failed!', errorcolor, "viewer"); + 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"); + } + }); - for (j = 0; j < zdepth; j += zstep) { - // get the inflated/deflated path - - for (i = 1; i < 100; i++) { // Rather 100 than a while loop, just in case - inflateValUsed = inflateVal * i; - var inflatedPaths = getInflatePath(newClipperPaths, -inflateValUsed); - inflateGrp = drawClipperPaths(inflatedPaths, 0xff00ff, 0.8, -j, true, "inflatedGroup"); // (paths, color, opacity, z, zstep, isClosed, isAddDirHelper, name, inflateVal) - if (inflateGrp.children.length) { - inflateGrp.name = 'inflateGrp'; - inflateGrp.position = infobject.position; - // pocketGrp.userData.color = pocketGrp.material.color.getHex(); - pocketGrp.add(inflateGrp); - } else { - console.log('Pocket already done after ' + i + ' iterations'); - break; - } - } + 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!:"); + printLog('Clipper Simplification Failed!', errorcolor, "viewer"); + } + + for (j = 0; j < zdepth; j += zstep) { + // get the inflated/deflated path + + for (i = 1; i < 100; i++) { // Rather 100 than a while loop, just in case + inflateValUsed = inflateVal * i; + var inflatedPaths = getInflatePath(newClipperPaths, -inflateValUsed); + inflateGrp = drawClipperPaths(inflatedPaths, 0xff00ff, 0.8, -j, true, "inflatedGroup"); // (paths, color, opacity, z, zstep, isClosed, isAddDirHelper, name, inflateVal) + if (inflateGrp.children.length) { + inflateGrp.name = 'inflateGrp'; + inflateGrp.position = infobject.position; + // pocketGrp.userData.color = pocketGrp.material.color.getHex(); + pocketGrp.add(inflateGrp); + } else { + console.log('Pocket already done after ' + i + ' iterations'); + break; } - return pocketGrp; + } } + return pocketGrp; + } }; dragknifePath = function(infobject, inflateVal, zstep, zdepth) { - var zstep = parseFloat(zstep, 2); - var zdepth = parseFloat(zdepth, 2); - var dragknifeGrp = new THREE.Group(); - if (typeof(inflateGrp) != 'undefined') { - scene.remove(inflateGrp); - inflateGrp = null; - } + var zstep = parseFloat(zstep, 2); + var zdepth = parseFloat(zdepth, 2); + var dragknifeGrp = new THREE.Group(); + if (typeof(inflateGrp) != 'undefined') { + scene.remove(inflateGrp); + inflateGrp = null; + } - // if (inflateVal != 0) { - console.log("user wants to create Drag Knife Path. val:", inflateVal); - infobject.updateMatrix(); - var grp = infobject; - 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 = grp.localToWorld(localPt.clone()); - var xpos = worldPt.x; - var ypos = worldPt.y; - - var xpos_offset = child.position.x; - var ypos_offset = child.position.y; - - 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"); - } + // if (inflateVal != 0) { + console.log("user wants to create Drag Knife Path. val:", inflateVal); + infobject.updateMatrix(); + var grp = infobject; + 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 = grp.localToWorld(localPt.clone()); + var xpos = worldPt.x; + var ypos = worldPt.y; + + var xpos_offset = child.position.x; + var ypos_offset = child.position.y; + + 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"); + } + }); - console.log("clipperPaths:", clipperPaths); + 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); + // 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!:"); - printLog('Clipper Simplification Failed!', errorcolor, "viewer") - } + if (newClipperPaths.length < 1) { + console.error("Clipper Simplification Failed!:"); + printLog('Clipper Simplification Failed!', errorcolor, "viewer") + } - for (j = 0; j < zdepth; j += zstep) { - var polygons = newClipperPaths; - polygons = polygons.map(function (poly) { - // return addCornerActions(poly, Math.pow(2, 20) * 5, 20 / 180 * Math.PI); - return addCornerActions(poly, inflateVal, 20 / 180 * Math.PI); - }); - inflateGrp = drawClipperPaths(polygons, 0xff00ff, 0.8, -j, true, "inflatedGroup"); // (paths, color, opacity, z, zstep, isClosed, isAddDirHelper, name, inflateVal) - if (inflateGrp.children.length) { - inflateGrp.name = 'dragknifeGrp'; - inflateGrp.position = infobject.position; - dragknifeGrp.userData.color = dragknifeGrp.material.color.getHex(); - dragknifeGrp.add(inflateGrp) - } else { - console.log('Dragknife Operation Failed') - break; - } - } - return dragknifeGrp + for (j = 0; j < zdepth; j += zstep) { + var polygons = newClipperPaths; + polygons = polygons.map(function (poly) { + // return addCornerActions(poly, Math.pow(2, 20) * 5, 20 / 180 * Math.PI); + return addCornerActions(poly, inflateVal, 20 / 180 * Math.PI); + }); + inflateGrp = drawClipperPaths(polygons, 0xff00ff, 0.8, -j, true, "inflatedGroup"); // (paths, color, opacity, z, zstep, isClosed, isAddDirHelper, name, inflateVal) + if (inflateGrp.children.length) { + inflateGrp.name = 'dragknifeGrp'; + inflateGrp.position = infobject.position; + dragknifeGrp.userData.color = dragknifeGrp.material.color.getHex(); + dragknifeGrp.add(inflateGrp) + } else { + console.log('Dragknife Operation Failed') + break; + } + } + return dragknifeGrp }; addCornerActions = function (clipperPolyline, clipperRadius, toleranceAngleRadians) { // var previousPoint = null; // var point = []; - 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; + 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); + } } - 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) { + 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); + // 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; + 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())) + // 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); + return new Point(this.X * val, this.Y * val, this.Z * val); }, distance: function (p) { - return Math.sqrt(this.sqDistance(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); + return new Point(this.X + p.X, this.Y + p.Y, this.Z + p.Z); }, atan2: function () { - return Math.atan2(this.Y, this.Y); + return Math.atan2(this.Y, this.Y); }, }; @@ -775,66 +775,66 @@ polarPoint = function (r, 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; + 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) { - var scale = 10000; - ClipperLib.JS.ScaleUpPaths(paths, scale); - var miterLimit = 2; - 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; + var scale = 10000; + ClipperLib.JS.ScaleUpPaths(paths, scale); + var miterLimit = 2; + 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(paths, color, opacity, z, isClosed, name) { - console.log("drawClipperPaths", paths); + console.log("drawClipperPaths", paths); - var lineUnionMat = new THREE.LineBasicMaterial({ - color: color, - transparent: true, - opacity: opacity, - }); + var lineUnionMat = new THREE.LineBasicMaterial({ + color: color, + transparent: true, + opacity: opacity, + }); - if (z === undefined || z == null) - z = 0; + if (z === undefined || z == null) + z = 0; - if (isClosed === undefined || isClosed == null) - isClosed = true; + if (isClosed === undefined || isClosed == null) + isClosed = true; - var group = new THREE.Object3D(); - if (name) group.name = name; + var group = new THREE.Object3D(); + if (name) group.name = name; - for (var i = 0; i < paths.length; i++) { - var lineUnionGeo = new THREE.Geometry(); - for (var j = 0; j < paths[i].length; j++) { - lineUnionGeo.vertices.push(new THREE.Vector3(paths[i][j].X, paths[i][j].Y, z)); - } - // close it by connecting last point to 1st point - if (isClosed) { - lineUnionGeo.vertices.push(new THREE.Vector3(paths[i][0].X, paths[i][0].Y, z)); - } - var lineUnion = new THREE.Line(lineUnionGeo, lineUnionMat); - if (name) { - lineUnion.name = name; - } - group.add(lineUnion); + for (var i = 0; i < paths.length; i++) { + var lineUnionGeo = new THREE.Geometry(); + for (var j = 0; j < paths[i].length; j++) { + lineUnionGeo.vertices.push(new THREE.Vector3(paths[i][j].X, paths[i][j].Y, z)); + } + // close it by connecting last point to 1st point + if (isClosed) { + lineUnionGeo.vertices.push(new THREE.Vector3(paths[i][0].X, paths[i][0].Y, z)); } - return group; + var lineUnion = new THREE.Line(lineUnionGeo, lineUnionMat); + if (name) { + lineUnion.name = name; + } + group.add(lineUnion); + } + return group; }; From c100245e3a726bcb744e357190347238871169cb Mon Sep 17 00:00:00 2001 From: Mattia Bondanza Date: Sun, 8 Jan 2017 15:04:35 +0100 Subject: [PATCH 7/7] Added a condition to stop the search for the closest point when a point with distance equal to 0 is found. --- public/js/threegcode.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/public/js/threegcode.js b/public/js/threegcode.js index a166d039..d39d23ee 100644 --- a/public/js/threegcode.js +++ b/public/js/threegcode.js @@ -245,34 +245,42 @@ function generateGcode(threeGroup, objectseq, cutSpeed, plungeSpeed, laserPwr, r if( optimization != "none" ){ var opt_distance; if( optimization == "manhattan" ) - opt_distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, 0 ) ); + opt_distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, 0 ) ); else - opt_distance = current_position.distanceToSquared( get_cut_begin_point( toCut, 0 ) ); + opt_distance = current_position.distanceToSquared( get_cut_begin_point( toCut, 0 ) ); for( i = 0; i < toCut.children.length; i++ ){ var distance; if( optimization == "manhattan" ) - distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, i ) ); + distance = current_position.distanceToManhattan( get_cut_begin_point( toCut, i ) ); else - distance = current_position.distanceToSquared( get_cut_begin_point( toCut, i ) ); + distance = current_position.distanceToSquared( get_cut_begin_point( toCut, i ) ); if( distance < opt_distance ){ opt_distance = distance; opt_cut = i; cut_reverse = 0; + + if( opt_distance == 0 ){ //If opt_distance == 0 no more optimization can be performed, time saving instruction. + break; //Exit from for cycle. + } } } for( i = 0; i < toCut.children.length; i++ ){ var distance; if( optimization == "manhattan" ) - distance = current_position.distanceToManhattan( get_cut_end_point( toCut, i ) ); + distance = current_position.distanceToManhattan( get_cut_end_point( toCut, i ) ); else - distance = current_position.distanceToSquared( get_cut_end_point( toCut, i ) ); + distance = current_position.distanceToSquared( get_cut_end_point( toCut, i ) ); if( distance < opt_distance ){ opt_distance = distance; opt_cut = i; cut_reverse = 1; + + if( opt_distance == 0 ){ //If opt_distance == 0 no more optimization can be performed, time saving instruction. + break; //Exit form for cycle. + } } }