From a2e7bf4d85ce41b2a1064adbbe1243ec578bf576 Mon Sep 17 00:00:00 2001 From: casperlamboo Date: Fri, 15 May 2015 17:35:18 +0200 Subject: [PATCH] fixed path optimizing when paths are empty --- build/d3d.js | 67 +++++++++++++++++++++++++++++--------- build/d3d.min.js | 2 +- models/stanford_bunny.stl | Bin 0 -> 15534 bytes slice_test.html | 6 ++-- src/paths.js | 6 ++-- src/slicer.js | 29 ++++++++++------- 6 files changed, 79 insertions(+), 31 deletions(-) create mode 100644 models/stanford_bunny.stl diff --git a/build/d3d.js b/build/d3d.js index 95c9744..404f625 100644 --- a/build/d3d.js +++ b/build/d3d.js @@ -583,7 +583,9 @@ D3D.Paths.prototype.setPaths = function (paths) { for (var i = 0; i < paths.length; i ++) { var path = paths[i]; - this.push(path); + if (path.length > 0) { + this.push(path); + } } return this; @@ -598,7 +600,7 @@ D3D.Paths.prototype.clip = function (path, type) { clipper.AddPaths(path, ClipperLib.PolyType.ptClip, path.closed); clipper.Execute(type, solution); - return new D3D.Paths(solution); + return new D3D.Paths(solution, this.closed); }; D3D.Paths.prototype.union = function (path) { "use strict"; @@ -762,8 +764,8 @@ D3D.Paths.prototype.draw = function (context, color) { for (var i = 0; i < this.length; i ++) { var shape = this[i]; - var point = shape[0]; - context.fillText(i, point.X*2, point.Y*2); + //var point = shape[0]; + //context.fillText(i, point.X*2, point.Y*2); context.beginPath(); var length = this.closed ? (shape.length + 1) : shape.length; @@ -797,17 +799,34 @@ D3D.Slicer = function () { D3D.Slicer.prototype.setMesh = function (mesh) { "use strict"; - mesh.updateMatrix(); - + //convert buffergeometry to geometry; var geometry = mesh.geometry.clone(); if (geometry instanceof THREE.BufferGeometry) { geometry = new THREE.Geometry().fromBufferGeometry(geometry); } + + //remove duplicate vertices; + for (var i = 0; i < geometry.vertices.length; i ++) { + var vertexA = geometry.vertices[i]; + + for (var j = i + 1; j < geometry.vertices.length; j ++) { + var vertexB = geometry.vertices[j]; + + if (vertexA.equals(vertexB)) { + geometry.vertices[j] = vertexA; + } + } + } geometry.mergeVertices(); + + //apply mesh matrix on geometry; + mesh.updateMatrix(); geometry.applyMatrix(mesh.matrix); + geometry.computeFaceNormals(); this.geometry = geometry; + //get unique lines from geometry; this.createLines(); return this; @@ -1060,6 +1079,7 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { } var fillArea = (inset || outerLayer).offset(-wallThickness/2); + //var fillArea = (inset || outerLayer).clone(); var highFillArea = fillArea.difference(surroundingLayer); @@ -1067,18 +1087,35 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { var fill = new D3D.Paths([], false); - fill.join(lowFillTemplate.intersect(lowFillArea)); - - if (highFillArea.length > 0) { - var highFillTemplate = this.getFillTemplate(highFillArea.bounds(), wallThickness, (layer % 2 === 0), (layer % 2 === 1)); - fill.join(highFillTemplate.intersect(highFillArea)); + if (lowFillTemplate.length > 0) { + fill.join(lowFillTemplate.intersect(lowFillArea)); } + if (highFillArea.length > 0) { + var bounds = highFillArea.bounds(); + var even = (layer % 2 === 0); + var highFillTemplate = this.getFillTemplate(bounds, wallThickness, even, !even); + fill.join(highFillTemplate.intersect(highFillArea)); + } + outerLayer = outerLayer.optimizePath(start); - insets = insets.optimizePath(outerLayer.lastPoint()); - fill = fill.optimizePath(insets.lastPoint()); - start = fill.lastPoint(); - + if (insets.length > 0) { + insets = insets.optimizePath(outerLayer.lastPoint()); + fill = fill.optimizePath(insets.lastPoint()); + } + else { + fill = fill.optimizePath(outerLayer.lastPoint()); + } + if (fill.length > 0) { + start = fill.lastPoint(); + } + else if (insets.length > 0) { + start = insets.lastPoint(); + } + else { + start = outerLayer.lastPoint(); + } + layerData.push({ outerLayer: outerLayer.scaleDown(scale), fill: fill.scaleDown(scale), diff --git a/build/d3d.min.js b/build/d3d.min.js index 5a968d5..9c55cb2 100644 --- a/build/d3d.min.js +++ b/build/d3d.min.js @@ -1 +1 @@ -function sendAPI(t,e,i){"use strict";$.ajax({url:t,type:"POST",data:e,dataType:"json",timeout:1e4,success:function(t){"success"===t.status?void 0!==i&&i(t.data):console.warn(t.msg)}}).fail(function(){console.warn("Failed connecting to "+t),sendAPI(t,e,i)})}function getAPI(t,e){"use strict";$.ajax({url:t,dataType:"json",timeout:5e3,success:function(t){"success"===t.status?void 0!==e&&e(t.data):console.warn(t.msg)}}).fail(function(){console.warn("Failed connecting to "+t),getAPI(t,e)})}function downloadFile(t,e){"use strict";$(document.createElement("a")).attr({download:t,href:"data:text/plain,"+e})[0].click()}var D3D={version:"0.1",website:"http://www.doodle3d.com/",contact:"develop@doodle3d.com"};THREE.Vector2.prototype.normal=function(){"use strict";var t=this.y,e=-this.x;return this.set(t,e)},Array.prototype.clone=function(){"use strict";for(var t=[],e=0;e0&&this.printer.status.buffered_lines+this.batchSize<=this.maxBufferedLines?this.printBatch():this.updateState()},D3D.Box.prototype.updateState=function(){"use strict";var t=this;this.getInfoStatus(function(e){t.printer.status=e,void 0!==t.onupdate&&t.onupdate(e),t.update()})},D3D.Box.prototype.print=function(t){"use strict";for(this.currentBatch=0,t=t.clone();t.length>0;){var e=t.splice(0,Math.min(this.batchSize,t.length));this.printBatches.push(e)}return this},D3D.Box.prototype.printBatch=function(){"use strict";var t=this,e=this.printBatches.shift();this.setPrinterPrint({start:0===this.currentBatch?!0:!1,first:0===this.currentBatch?!0:!1,gcode:e.join("\n")},function(e){console.log("batch sent: "+t.currentBatch,e),t.printBatches.length>0&&t.currentBatch++,t.updateState()})},D3D.Box.prototype.stopPrint=function(){"use strict";this.printBatches=[],this.currentBatch=0;var t=["M107 ;fan off","G91 ;relative positioning","G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure","G1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more","G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way","M84 ;disable axes / steppers","G90 ;absolute positioning","M104 S180",";M140 S70","M117 Done ;display message (20 characters to clear whole screen)"];return this.setPrinterStop({gcode:t.join("\n")},function(t){console.log("Printer stop command sent")}),this},D3D.Box.prototype.getConfig=function(t,e){"use strict";return getAPI(this.api+"config/?"+t.join("=&")+"=",e),this},D3D.Box.prototype.getConfigAll=function(t){"use strict";return getAPI(this.api+"config/all",t),this},D3D.Box.prototype.setConfig=function(t,e){"use strict";var i=this;return sendAPI(this.api+"config",t,function(r){for(var n in r.validation)"ok"!==r.validation[n]&&delete t[n];i.updateConfig(t),i.printer.updateConfig(t),void 0!==e&&e(r)}),this},D3D.Box.prototype.getInfo=function(t){"use strict";return getAPI(this.api+"info",t),this},D3D.Box.prototype.getInfoStatus=function(t){"use strict";return getAPI(this.api+"info/status",t),this},D3D.Box.prototype.downloadInfoLogFiles=function(){"use strict";window.location=this.api+"info/logfiles"},D3D.Box.prototype.getInfoAcces=function(t){"use strict";return getAPI(this.api+"info/access",t),this},D3D.Box.prototype.getNetworkScan=function(t){"use strict";return getAPI(this.api+"network/scan",t),this},D3D.Box.prototype.getNetworkKnown=function(t){"use strict";return getAPI(this.api+"network/known",t),this},D3D.Box.prototype.getNetworkStatus=function(t){"use strict";return getAPI(this.api+"network/status",t),this},D3D.Box.prototype.setNetworkAssosiate=function(t,e){"use strict";return sendAPI(this.api+"network/associate",t,e),this},D3D.Box.prototype.setNetworkDisassosiate=function(t){"use strict";return sendAPI(this.api+"network/disassociate",{},t),this},D3D.Box.prototype.setNetworkOpenAP=function(t){"use strict";return sendAPI(this.api+"network/openap",{},t),this},D3D.Box.prototype.setNetworkRemove=function(t,e){"use strict";return sendAPI(this.api+"network/remove",{ssid:t},e),this},D3D.Box.prototype.getNetworkSignin=function(t){"use strict";return getAPI(this.api+"network/signin",t),this},D3D.Box.prototype.getNetworkAlive=function(t){"use strict";return getAPI(this.api+"network/alive",t),this},D3D.Box.prototype.getPrinterTemperature=function(t){"use strict";return getAPI(this.api+"printer/temperature",t),this},D3D.Box.prototype.getPrinterProgress=function(t){"use strict";return getAPI(this.api+"printer/progress",t),this},D3D.Box.prototype.getPrinterState=function(t){"use strict";return getAPI(this.api+"printer/state",t),this},D3D.Box.prototype.getPrinterListAll=function(t){"use strict";return getAPI(this.api+"printer/listall",t),this},D3D.Box.prototype.setPrinterHeatup=function(t){"use strict";return sendAPI(this.api+"printer/heatup",{},t),this},D3D.Box.prototype.setPrinterPrint=function(t,e){"use strict";return sendAPI(this.api+"printer/print",t,e),this},D3D.Box.prototype.setPrinterStop=function(t,e){"use strict";return sendAPI(this.api+"printer/stop",t,e),this},D3D.Box.prototype.getSketch=function(t,e){"use strict";return getAPI(this.api+"sketch/?id="+t,e),this},D3D.Box.prototype.setSketch=function(t,e){"use strict";return sendAPI(this.api+"sketch",{data:t},e),this},D3D.Box.prototype.getSketchStatus=function(t){"use strict";return getAPI(this.api+"sketch/status",t),this},D3D.Box.prototype.setSketchClear=function(t){"use strict";return sendAPI(this.api+"sketch/clear",t),this},D3D.Box.prototype.getSystemVersions=function(t){"use strict";return getAPI(this.api+"system/fwversions",t),this},D3D.Box.prototype.getUpdateStatus=function(t){"use strict";return getAPI(this.api+"update/status",t),this},D3D.Box.prototype.setUpdateDownload=function(t){"use strict";return sendAPI(this.api+"update/download",{},t),this},D3D.Box.prototype.setUpdateInstall=function(t){"use strict";return sendAPI(this.api+"update/install",{},t),this},D3D.Box.prototype.setUpdateClear=function(t){"use strict";return sendAPI(this.api+"update/clear",{},t),this},D3D.Printer=function(t){"use strict";this.status={},this.config={},this.updateConfig(t)},D3D.Printer.prototype.updateConfig=function(t){"use strict";for(var e in t)0===e.indexOf("printer")&&(this.config[e]=t[e]);return this},D3D.Printer.prototype.getStartCode=function(){"use strict";var t=this.config["printer.startcode"];return t=this.subsituteVariables(t),t.split("\n")},D3D.Printer.prototype.getEndCode=function(){"use strict";var t=this.config["printer.endcode"];return t=this.subsituteVariables(t),t.split("\n")},D3D.Printer.prototype.subsituteVariables=function(t){"use strict";var e=this.config["printer.temperature"],i=this.config["printer.bed.temperature"],r=this.config["printer.heatup.temperature"],n=this.config["printer.heatup.bed.temperature"],s=this.config["printer.type"],o=this.config["printer.heatedbed"];switch(s){case"makerbot_replicator2":s="r2";break;case"makerbot_replicator2x":s="r2x";break;case"makerbot_thingomatic":s="t6";break;case"makerbot_generic":s="r2";break;case"_3Dison_plus":s="r2"}var a=o?"":";";return t=t.replace(/{printingTemp}/gi,e),t=t.replace(/{printingBedTemp}/gi,i),t=t.replace(/{preheatTemp}/gi,r),t=t.replace(/{preheatBedTemp}/gi,n),t=t.replace(/{printerType}/gi,s),t=t.replace(/{if heatedBed}/gi,a)},D3D.Paths=function(t,e){"use strict";Array.call(this),this.setPaths(t||[]),this.closed=void 0!==e?e:!0},D3D.Paths.prototype=Object.create(Array.prototype),D3D.Paths.prototype.setPaths=function(t){"use strict";for(var e=0;el)&&(n=p,a=l,s=h,o=c)}else{var f=new THREE.Vector2(p[0].X,p[0].Y),l=f.sub(t).length();(a===!1||a>l)&&(n=p,a=l,r=!1,o=c);var g=new THREE.Vector2(p[p.length-1].X,p[p.length-1].Y),l=g.sub(t).length();a>l&&(n=p,a=l,r=!0,o=c)}}if(this.closed){n=n.concat(n.splice(0,s));var u=n[0]}else{r&&n.reverse();var u=n[n.length-1]}i.push(o),t=new THREE.Vector2(u.X,u.Y),e.push(n)}return e},D3D.Paths.prototype.tresholdArea=function(t){"use strict";for(var e=0;er&&(this.splice(e,1),e--)}return areas},D3D.Paths.prototype.join=function(t){"use strict";for(var e=0;eo;o++){var n=r[o%r.length];t.lineTo(2*n.X,2*n.Y)}t.stroke()}},D3D.Slicer=function(){"use strict";this.lines=[]},D3D.Slicer.prototype.setMesh=function(t){"use strict";t.updateMatrix();var e=t.geometry.clone();return e instanceof THREE.BufferGeometry&&(e=(new THREE.Geometry).fromBufferGeometry(e)),e.mergeVertices(),e.applyMatrix(t.matrix),this.geometry=e,this.createLines(),this},D3D.Slicer.prototype.createLines=function(){"use strict";function t(t,r){var n=e[t+"_"+r]||e[r+"_"+t];return void 0===n&&(n=i.lines.length,e[t+"_"+r]=n,i.lines.push({line:new THREE.Line3(i.geometry.vertices[t],i.geometry.vertices[r]),connects:[],normals:[],ignore:0})),n}this.lines=[];for(var e={},i=this,r=0;r=a;a++)a>=0&&(void 0===i[a]&&(i[a]=[]),i[a].push(r));for(var c=[],p=1;p0)break;f=-1}else f=-1}P.length>0&&v.push(new D3D.Paths([P]))}}for(var k=[],r=0;r0){E.join(C),I=!0;break}}I||k.push(C)}if(!(k.length>0))break;c.push(k)}return c},D3D.Slicer.prototype.slicesToData=function(t,e){"use strict";for(var i=100,r=e.config["printer.layerHeight"]*i,n=e.config["printer.dimensions.z"]*i,s=e.config["printer.wallThickness"]*i,o=e.config["printer.shellThickness"]*i,a=e.config["printer.fillSize"]*i,c=(e.config["printer.brimOffset"]*i,Math.ceil(o/r)),p=new THREE.Vector2(0,0),h=[],u=this.getFillTemplate({left:0,top:0,right:n,bottom:n},a,!0,!0),l=0;l=0)for(var D=t[l-c],y=0;y=b;b+=s){var B=w.offset(-b);x.join(B)}var T=(B||w).offset(-s/2),A=T.difference(P),S=T.difference(A),k=new D3D.Paths([],!1);if(k.join(u.intersect(S)),A.length>0){var C=this.getFillTemplate(A.bounds(),s,l%2===0,l%2===1);k.join(C.intersect(A))}w=w.optimizePath(p),x=x.optimizePath(w.lastPoint()),k=k.optimizePath(x.lastPoint()),p=k.lastPoint(),g.push({outerLayer:w.scaleDown(i),fill:k.scaleDown(i),insets:x.scaleDown(i)})}}return h},D3D.Slicer.prototype.getFillTemplate=function(t,e,i,r){"use strict";var n=new D3D.Paths([],!1);if(i)for(var s=Math.floor(t.left);s<=Math.ceil(t.right);s+=e)n.push([{X:s,Y:t.top},{X:s,Y:t.bottom}]);if(r)for(var s=Math.floor(t.top);s<=Math.floor(t.bottom);s+=e)n.push([{X:t.left,Y:s},{X:t.right,Y:s}]);return n},D3D.Slicer.prototype.dataToGcode=function(t,e){"use strict";function i(t){for(var e=[],i=0;ia;a++){var p=s[a%s.length];if(0===a)D>f&&u&&e.push(["G0","E"+(D-g).toFixed(3),"F"+(60*l).toFixed(3)].join(" ")),e.push(["G0","X"+p.X.toFixed(3)+" Y"+p.Y.toFixed(3)+" Z"+x,"F"+60*c].join(" ")),D>f&&u&&e.push(["G0","E"+D.toFixed(3),"F"+(60*l).toFixed(3)].join(" "));else{var d=(new THREE.Vector2).set(p.X,p.Y),m=(new THREE.Vector2).set(n.X,n.Y),w=d.distanceTo(m);D+=w*h*r/v*P,e.push(["G1","X"+p.X.toFixed(3)+" Y"+p.Y.toFixed(3)+" Z"+x,"F"+y,"E"+D.toFixed(3)].join(" "))}n=p}return e}for(var r=e.config["printer.layerHeight"],n=e.config["printer.speed"],s=e.config["printer.bottomLayerSpeed"],o=e.config["printer.firstLayerSlow"],a=e.config["printer.bottomFlowRate"],c=e.config["printer.travelSpeed"],p=e.config["printer.filamentThickness"],h=e.config["printer.wallThickness"],u=(e.config["printer.enableTraveling"],e.config["printer.retraction.enabled"]),l=e.config["printer.retraction.speed"],f=e.config["printer.retraction.minDistance"],g=e.config["printer.retraction.amount"],d=e.getStartCode(),D=0,y=o?(60*s).toFixed(3):(60*n).toFixed(3),v=Math.pow(p/2,2)*Math.PI,P=a,m=0;mp;p++)for(var h=o[p%o.length],u=0;u0&&this.printer.status.buffered_lines+this.batchSize<=this.maxBufferedLines?this.printBatch():this.updateState()},D3D.Box.prototype.updateState=function(){"use strict";var t=this;this.getInfoStatus(function(e){t.printer.status=e,void 0!==t.onupdate&&t.onupdate(e),t.update()})},D3D.Box.prototype.print=function(t){"use strict";for(this.currentBatch=0,t=t.clone();t.length>0;){var e=t.splice(0,Math.min(this.batchSize,t.length));this.printBatches.push(e)}return this},D3D.Box.prototype.printBatch=function(){"use strict";var t=this,e=this.printBatches.shift();this.setPrinterPrint({start:0===this.currentBatch?!0:!1,first:0===this.currentBatch?!0:!1,gcode:e.join("\n")},function(e){console.log("batch sent: "+t.currentBatch,e),t.printBatches.length>0&&t.currentBatch++,t.updateState()})},D3D.Box.prototype.stopPrint=function(){"use strict";this.printBatches=[],this.currentBatch=0;var t=["M107 ;fan off","G91 ;relative positioning","G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure","G1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more","G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way","M84 ;disable axes / steppers","G90 ;absolute positioning","M104 S180",";M140 S70","M117 Done ;display message (20 characters to clear whole screen)"];return this.setPrinterStop({gcode:t.join("\n")},function(t){console.log("Printer stop command sent")}),this},D3D.Box.prototype.getConfig=function(t,e){"use strict";return getAPI(this.api+"config/?"+t.join("=&")+"=",e),this},D3D.Box.prototype.getConfigAll=function(t){"use strict";return getAPI(this.api+"config/all",t),this},D3D.Box.prototype.setConfig=function(t,e){"use strict";var i=this;return sendAPI(this.api+"config",t,function(r){for(var n in r.validation)"ok"!==r.validation[n]&&delete t[n];i.updateConfig(t),i.printer.updateConfig(t),void 0!==e&&e(r)}),this},D3D.Box.prototype.getInfo=function(t){"use strict";return getAPI(this.api+"info",t),this},D3D.Box.prototype.getInfoStatus=function(t){"use strict";return getAPI(this.api+"info/status",t),this},D3D.Box.prototype.downloadInfoLogFiles=function(){"use strict";window.location=this.api+"info/logfiles"},D3D.Box.prototype.getInfoAcces=function(t){"use strict";return getAPI(this.api+"info/access",t),this},D3D.Box.prototype.getNetworkScan=function(t){"use strict";return getAPI(this.api+"network/scan",t),this},D3D.Box.prototype.getNetworkKnown=function(t){"use strict";return getAPI(this.api+"network/known",t),this},D3D.Box.prototype.getNetworkStatus=function(t){"use strict";return getAPI(this.api+"network/status",t),this},D3D.Box.prototype.setNetworkAssosiate=function(t,e){"use strict";return sendAPI(this.api+"network/associate",t,e),this},D3D.Box.prototype.setNetworkDisassosiate=function(t){"use strict";return sendAPI(this.api+"network/disassociate",{},t),this},D3D.Box.prototype.setNetworkOpenAP=function(t){"use strict";return sendAPI(this.api+"network/openap",{},t),this},D3D.Box.prototype.setNetworkRemove=function(t,e){"use strict";return sendAPI(this.api+"network/remove",{ssid:t},e),this},D3D.Box.prototype.getNetworkSignin=function(t){"use strict";return getAPI(this.api+"network/signin",t),this},D3D.Box.prototype.getNetworkAlive=function(t){"use strict";return getAPI(this.api+"network/alive",t),this},D3D.Box.prototype.getPrinterTemperature=function(t){"use strict";return getAPI(this.api+"printer/temperature",t),this},D3D.Box.prototype.getPrinterProgress=function(t){"use strict";return getAPI(this.api+"printer/progress",t),this},D3D.Box.prototype.getPrinterState=function(t){"use strict";return getAPI(this.api+"printer/state",t),this},D3D.Box.prototype.getPrinterListAll=function(t){"use strict";return getAPI(this.api+"printer/listall",t),this},D3D.Box.prototype.setPrinterHeatup=function(t){"use strict";return sendAPI(this.api+"printer/heatup",{},t),this},D3D.Box.prototype.setPrinterPrint=function(t,e){"use strict";return sendAPI(this.api+"printer/print",t,e),this},D3D.Box.prototype.setPrinterStop=function(t,e){"use strict";return sendAPI(this.api+"printer/stop",t,e),this},D3D.Box.prototype.getSketch=function(t,e){"use strict";return getAPI(this.api+"sketch/?id="+t,e),this},D3D.Box.prototype.setSketch=function(t,e){"use strict";return sendAPI(this.api+"sketch",{data:t},e),this},D3D.Box.prototype.getSketchStatus=function(t){"use strict";return getAPI(this.api+"sketch/status",t),this},D3D.Box.prototype.setSketchClear=function(t){"use strict";return sendAPI(this.api+"sketch/clear",t),this},D3D.Box.prototype.getSystemVersions=function(t){"use strict";return getAPI(this.api+"system/fwversions",t),this},D3D.Box.prototype.getUpdateStatus=function(t){"use strict";return getAPI(this.api+"update/status",t),this},D3D.Box.prototype.setUpdateDownload=function(t){"use strict";return sendAPI(this.api+"update/download",{},t),this},D3D.Box.prototype.setUpdateInstall=function(t){"use strict";return sendAPI(this.api+"update/install",{},t),this},D3D.Box.prototype.setUpdateClear=function(t){"use strict";return sendAPI(this.api+"update/clear",{},t),this},D3D.Printer=function(t){"use strict";this.status={},this.config={},this.updateConfig(t)},D3D.Printer.prototype.updateConfig=function(t){"use strict";for(var e in t)0===e.indexOf("printer")&&(this.config[e]=t[e]);return this},D3D.Printer.prototype.getStartCode=function(){"use strict";var t=this.config["printer.startcode"];return t=this.subsituteVariables(t),t.split("\n")},D3D.Printer.prototype.getEndCode=function(){"use strict";var t=this.config["printer.endcode"];return t=this.subsituteVariables(t),t.split("\n")},D3D.Printer.prototype.subsituteVariables=function(t){"use strict";var e=this.config["printer.temperature"],i=this.config["printer.bed.temperature"],r=this.config["printer.heatup.temperature"],n=this.config["printer.heatup.bed.temperature"],s=this.config["printer.type"],o=this.config["printer.heatedbed"];switch(s){case"makerbot_replicator2":s="r2";break;case"makerbot_replicator2x":s="r2x";break;case"makerbot_thingomatic":s="t6";break;case"makerbot_generic":s="r2";break;case"_3Dison_plus":s="r2"}var a=o?"":";";return t=t.replace(/{printingTemp}/gi,e),t=t.replace(/{printingBedTemp}/gi,i),t=t.replace(/{preheatTemp}/gi,r),t=t.replace(/{preheatBedTemp}/gi,n),t=t.replace(/{printerType}/gi,s),t=t.replace(/{if heatedBed}/gi,a)},D3D.Paths=function(t,e){"use strict";Array.call(this),this.setPaths(t||[]),this.closed=void 0!==e?e:!0},D3D.Paths.prototype=Object.create(Array.prototype),D3D.Paths.prototype.setPaths=function(t){"use strict";for(var e=0;e0&&this.push(i)}return this},D3D.Paths.prototype.clip=function(t,e){"use strict";var i=new ClipperLib.Paths,r=new ClipperLib.Clipper;return r.AddPaths(this,ClipperLib.PolyType.ptSubject,this.closed),r.AddPaths(t,ClipperLib.PolyType.ptClip,t.closed),r.Execute(e,i),new D3D.Paths(i,this.closed)},D3D.Paths.prototype.union=function(t){"use strict";return this.clip(t,ClipperLib.ClipType.ctUnion)},D3D.Paths.prototype.difference=function(t){"use strict";return this.clip(t,ClipperLib.ClipType.ctDifference)},D3D.Paths.prototype.intersect=function(t){"use strict";return this.clip(t,ClipperLib.ClipType.ctIntersection)},D3D.Paths.prototype.xor=function(){"use strict";return this.clip(path,ClipperLib.ClipType.ctXor)},D3D.Paths.prototype.offset=function(t){"use strict";var e=new ClipperLib.Paths,i=new ClipperLib.ClipperOffset(1,1);return i.AddPaths(this,ClipperLib.JoinType.jtRound,ClipperLib.EndType.etClosedPolygon),i.Execute(e,t),new D3D.Paths(e)},D3D.Paths.prototype.scaleUp=function(t){"use strict";ClipperLib.JS.ScaleUpPaths(this,t);return this},D3D.Paths.prototype.scaleDown=function(t){"use strict";ClipperLib.JS.ScaleDownPaths(this,t);return this},D3D.Paths.prototype.lastPoint=function(){"use strict";var t=this[this.length-1],e=this.closed?t[0]:t[t.length-1];return new THREE.Vector2(e.X,e.Y)},D3D.Paths.prototype.optimizePath=function(t){"use strict";for(var e=new D3D.Paths([],this.closed),i=[];e.length!==this.length;){for(var r,n,s,o,a=!1,c=0;cl)&&(n=p,a=l,s=h,o=c)}else{var f=new THREE.Vector2(p[0].X,p[0].Y),l=f.sub(t).length();(a===!1||a>l)&&(n=p,a=l,r=!1,o=c);var g=new THREE.Vector2(p[p.length-1].X,p[p.length-1].Y),l=g.sub(t).length();a>l&&(n=p,a=l,r=!0,o=c)}}if(this.closed){n=n.concat(n.splice(0,s));var u=n[0]}else{r&&n.reverse();var u=n[n.length-1]}i.push(o),t=new THREE.Vector2(u.X,u.Y),e.push(n)}return e},D3D.Paths.prototype.tresholdArea=function(t){"use strict";for(var e=0;er&&(this.splice(e,1),e--)}return areas},D3D.Paths.prototype.join=function(t){"use strict";for(var e=0;es;s++){var o=r[s%r.length];t.lineTo(2*o.X,2*o.Y)}t.stroke()}},D3D.Slicer=function(){"use strict";this.lines=[]},D3D.Slicer.prototype.setMesh=function(t){"use strict";var e=t.geometry.clone();e instanceof THREE.BufferGeometry&&(e=(new THREE.Geometry).fromBufferGeometry(e));for(var i=0;i=a;a++)a>=0&&(void 0===i[a]&&(i[a]=[]),i[a].push(r));for(var c=[],p=1;p0)break;f=-1}else f=-1}P.length>0&&v.push(new D3D.Paths([P]))}}for(var k=[],r=0;r0){E.join(C),I=!0;break}}I||k.push(C)}if(!(k.length>0))break;c.push(k)}return c},D3D.Slicer.prototype.slicesToData=function(t,e){"use strict";for(var i=100,r=e.config["printer.layerHeight"]*i,n=e.config["printer.dimensions.z"]*i,s=e.config["printer.wallThickness"]*i,o=e.config["printer.shellThickness"]*i,a=e.config["printer.fillSize"]*i,c=(e.config["printer.brimOffset"]*i,Math.ceil(o/r)),p=new THREE.Vector2(0,0),h=[],u=this.getFillTemplate({left:0,top:0,right:n,bottom:n},a,!0,!0),l=0;l=0)for(var D=t[l-c],y=0;y=b;b+=s){var B=w.offset(-b);x.join(B)}var T=(B||w).offset(-s/2),A=T.difference(P),S=T.difference(A),k=new D3D.Paths([],!1);if(u.length>0&&k.join(u.intersect(S)),A.length>0){var C=A.bounds(),I=l%2===0,E=this.getFillTemplate(C,s,I,!I);k.join(E.intersect(A))}w=w.optimizePath(p),x.length>0?(x=x.optimizePath(w.lastPoint()),k=k.optimizePath(x.lastPoint())):k=k.optimizePath(w.lastPoint()),p=k.length>0?k.lastPoint():x.length>0?x.lastPoint():w.lastPoint(),g.push({outerLayer:w.scaleDown(i),fill:k.scaleDown(i),insets:x.scaleDown(i)})}}return h},D3D.Slicer.prototype.getFillTemplate=function(t,e,i,r){"use strict";var n=new D3D.Paths([],!1);if(i)for(var s=Math.floor(t.left);s<=Math.ceil(t.right);s+=e)n.push([{X:s,Y:t.top},{X:s,Y:t.bottom}]);if(r)for(var s=Math.floor(t.top);s<=Math.floor(t.bottom);s+=e)n.push([{X:t.left,Y:s},{X:t.right,Y:s}]);return n},D3D.Slicer.prototype.dataToGcode=function(t,e){"use strict";function i(t){for(var e=[],i=0;ia;a++){var p=s[a%s.length];if(0===a)D>f&&u&&e.push(["G0","E"+(D-g).toFixed(3),"F"+(60*l).toFixed(3)].join(" ")),e.push(["G0","X"+p.X.toFixed(3)+" Y"+p.Y.toFixed(3)+" Z"+x,"F"+60*c].join(" ")),D>f&&u&&e.push(["G0","E"+D.toFixed(3),"F"+(60*l).toFixed(3)].join(" "));else{var d=(new THREE.Vector2).set(p.X,p.Y),m=(new THREE.Vector2).set(n.X,n.Y),w=d.distanceTo(m);D+=w*h*r/v*P,e.push(["G1","X"+p.X.toFixed(3)+" Y"+p.Y.toFixed(3)+" Z"+x,"F"+y,"E"+D.toFixed(3)].join(" "))}n=p}return e}for(var r=e.config["printer.layerHeight"],n=e.config["printer.speed"],s=e.config["printer.bottomLayerSpeed"],o=e.config["printer.firstLayerSlow"],a=e.config["printer.bottomFlowRate"],c=e.config["printer.travelSpeed"],p=e.config["printer.filamentThickness"],h=e.config["printer.wallThickness"],u=(e.config["printer.enableTraveling"],e.config["printer.retraction.enabled"]),l=e.config["printer.retraction.speed"],f=e.config["printer.retraction.minDistance"],g=e.config["printer.retraction.amount"],d=e.getStartCode(),D=0,y=o?(60*s).toFixed(3):(60*n).toFixed(3),v=Math.pow(p/2,2)*Math.PI,P=a,m=0;mp;p++)for(var h=o[p%o.length],u=0;uHO-cWLG)<-DZ+E)NBP2SurdEpuxVr4 zSJJ;&rdEGqw5k949GO$MuW`qxF(yJzRd%9{qas+F4HIeWgbd5Csr|Je7h?LnA<0TYT_?z}d&^<`uD%o;jk!*E}*vgQG5Yj>CKU-Or|S$u`;eRqq|%Hh21+00*( z$>%-YJKvPC)#Bv83m91LFGI;0kz!{HfBtOtYfIb4W_j{?x^{iiCQF5P+0wmsanq7* zu`+nDMY`K;)deM5blHxu>N+}FCF>}MRZ!b;2Da#!2oO}>v?_ro9Bi|jJ& zUmYL40@(6ZSNXWL^?B-F&Zc`WsoXg4z0tg}v1zbtLz(TjK&#ur*>ubtA^Rq2dO}3er<>0j4GW|>gedU!Bh6!&O zZO$Vv_>r$pS%JAzEUo9>*A~91kk!Cg!D81sMXO(}c2+@LUpXP?xvpb)@-L#|tiR1q zqpbu=p6K`s`@GSQ_P72l8=v{0rC9GacJa-Y$39gs;Z76s zHU1;7RmED+&+aVygGp8nsRyeZ880KhER{oAwJ~{RHZfLxxj|;s^)MaXQkS(Y?Ip8k`{;Ys>1|IwWY{a- zZh;@ev2gC4kDs&D^ZrBjzTl|u)sg`kz1^*e_)@i$dtnZo0hWJkd*!$+^wF)cy z$dXgrnO?f)Y3aPZD=lnQ8TmPU6ovn=G+rhn9VEscB`aYcj*(tG43rrKVGuPc7rXwEu^$=Ae?S$8e z>hy$dH#x@osQmWU@Rs21A>^Kmhj8#Nq8HY@qNS>MS)xZT*M1xKRx6CZX4##wN=uk> zR6`p>$hzf5QS|jC{rL3}MJd+aQMO9$p{-84@B`wfwH3s@nb9=5VRz9vBvm?Ayd~Bh zr`oBMJh{xqUfKo@Qr;sWgS^U$JvA=TvoRj5Scgp6xqe>@8I)`ED7YHzDKV zAIqmN)>>*`?yLWQ`A|D{%c-O2+cu4F?h+^WOy6s%eJjj_rx|AFEN^!=TC9GXtMAqI zj?u#9@LGfS`E&zXfEJq_vYPt4%M7!#Dc##XtIvU%mJX!8jtCEKA#OctCo)Qgn^R7c ztW}OFGGVBb3DIs>uE^XEr{%thSM<9Z?O04$=i9T9$+a2UTC~CG4K~Un2j-Yj?ok z(&@Km`a1se6GKRh2wrtwcHJbu-xBlyH|oV|R^3|aGy3+k;QEQfK1L^z(f%i)ST%U( z?QJ5pU0cpbmut(6gv>5zXr91li1Alecz$|#S9=_vAP>HMX?&7Y+%&%4GC8*3k`doO zAy<>m(=oxFnBBRrw3+J~8MCC5h#nhi`rPuUv}_#0R_&Oi-h5(v(@Bt2FY)qfY^KL( zhpbJzuE`3=d`-C84&BRUxi5buP0xSUSH7iL2y0QP9`9dfJMEotL59z>GNm|gFolo0 zB4ZLfg!?bQne4oe$h}`mnpU)0t|MABO5)p(j}rOwsF&&Q%FATTr6{)h)Hl0ZG_I0(+O!$FU-l^<@W3jo zZO8J)D_fc=x3Bau=d3Mb7Fu3jX{sYeTnrQ0Yj@E_4-XyAKEFdoOm1QvbauND-^yRD zw#j<$V~q=6PSa1Z%8n_*rmG#j*};vX6uw6lal_fn*VeNZ3Dr6Y^nIrnC&}GUhDlHR z?pj(^E^8&5<^1Q#x{h;C&KQpDpKGpFFPi1AYpzu})%W{e9Z8SV{Fb%1e7i|`b>p;u zhIX)!=!+c*2}}N)-mHIs7yGrpz?#7!8JyxE$+TMuq10kRD?|OROilcopB3Q_X z!_uW#iX}O0wsJE*F1E_DTuB#e_v`kNJP519yo+kGDvjQ8|G#%>Wk2=N(z-clC5oqM zC+q88%=(n^hufZa$KY)WVe!-VD~L@^N?Tk`jn?eq(v7)=zLpY=lC-SsKlGK?+|-+& zdl|uoy*4T~5iP2U5EstyiI)S}Qn&Vs-3=}7>e=&Pl6KHOPg4=6ANYy;+2{D@>VWfS*O~{8D1>-cXKSxV7CcmZ+Iu6~lMzV50f zQifim7ZbK=kuTz9k3xg#>#4(9%$M`B{5fJmA56%;0B5l_whKGEcDLF7(sSwF?zMLM z(MH7&wr*H5%PaW0cCYh#{XG1OO0WU*`ityqZX9g}dVSPK$m;ST%(3z!^VX7wD83?m zU5lP>kU5P$Tbe%jP1mtHKS0pX^?d2xtrUGK+DEh)x`i7a!SX$q819T;Ob2jV)7~7T zrLbS3_Uise?GMM3#_ZJBN{m8?;bT|kGqw_YFmnO_(xRrx_-9L&_-K&k+0fP0XYx3U z-1Un#G}_tJv0td=TzWD6mPB{m$#0DhVE4!xZkcpW-pel3Zu>7Vg)GUF@w=aBF%#$f zV0{jz*|4j%4^VTOiQPWZ!}uaBOe@;F$%N5>(W8VhN7r?0Zj!$8#UIY_!sRi%&9Gr? z`u?Tz&q+Jv8}ln8dKvUSgm^B<;7u=GH2Xaos~}Ly#!bjcyR)SGm@T?(kA0Ux_gf7Y zkJ_%JxbNs+jZ=$D(tb0`iA>aI^*+*?eR<*|*vbhMzaRoVH6dl=UYLjdwvJvoIGznW zFj%|XJl--ry1%K8X9wwjD%lv++F-)FK*+K&Z|Sg;;_Vo|RE&4 z%M1L{`ph!9Q6x$C@M#*3L`cG#iTtNdO~fIeR*K!l^T(6b^T8l{;Wy$6U2bU3&>~}0 zjBk?=o6=_fDff{f-hM2@FBl=?NP5(FupJA_smR2ebBd+L{1fdwAs&tUFds)77Wlad z$G44d9?^uXY~;;uM%l5=j?EPvh*l9t%k1KN>V}El<<=Q+NAW$HGe*eVJL$6WpnUyB zh23r?0t4N}@~k!-5h$geN9lrC!@ksLQLEK@GfJU7R}l|gUea~-7t=Yh{RP@3^siF` z%A1;0SjB!0%F}0M-=G|ul-S&m+r6KHz+4^CdIXTzP!vq}q63HN{8Plx+s zCfE3BQpv17zbEP5dG@t*P8~;ybukefa~zaHG$ChS&&i1DJu2hn*BQ#a!Wb8CrH**H zE2C#a$BgGX0;TZ2s)#<*%^v&TZ#(q#2L#5~h}OBj15u)gJ}`HROfVobfp%B5qA6v4 z#j3qC`KcDg86r?hjp3?Az2pTSiumWBJQOwxvm%u#N*feKFSA7d?*9W=PN z@m!N<66ZfQU}*ak<_;J=LaeU6HJl#TQY`t@T0wL?P}?+iyQ@6fed`Y~^^u<|vYLbE z8EQ&jCF;YR17kZqTFSpkFT^+HD@SGQsgNk7tb-yAd@w7YT^%^<$N}jUlQffg$C+mazjsj#?<<}GMu3E@8qkMssy3faej3J5YV%l~3Eb7q z64N3HymI$Q+J*5^@=su@Z9GdAdlgQ;!B!UT8+C-_n=M z{5DQ9-0HNF(jJv=qc+jZOSRFS@#=glrzS7&(6D1~T3_H-#F zZm+#VyR`HW81Entqee2K`wGs=Rbj2yby5(>y&;;AGUeCsfbJXk?h_*gt{nFbqbNe2 zPOK!(XP%@7+I3Lab7TsUNhf6dwl(~zVY_FI&l44f9`&g@{08}m!m_EfPsNuM$I2Y? zK}P<*$nwpDs|vwo&4z{7_Q?Uww zKA4cYcc$^9d&UW;s5p*x3GEfWU_vU?dSvAT-*e9c$P+f-Vtv-6>7 z6R`?_GbCikTWfLpKughQ!)uNl0I~)ckrTpJwGa&+xQd$E5{^#F@HPJG*=iuk>imvC$op~P_L&oNTd zD?f*4u-T8sdak!`VMZT?R&DRXna23BeYMO|%XFqlD;y|BzDuOx=WoyrnSt{2?VZL= zXU-a{UJR1QOZe;A10i>}E|eLL!uajqgxIZaBqr^-OJk?iWGIDbU&n^>R+&)kM%@WU zLY@`xAg;83YM>#_1fCi)|LVQEKkOK{``wLa^$k)Gc>Z|b2>D}ypLqROOh>Df;tB$J zQPiiiA8UPi)tVDTmD4d48CtCAV21pC@iE_j>(wQUgvSwU*>&X1?|Y?YET^Uw6VvMS zVWSt$q{w(7M~2l!LUPt!;cbTvXQ{J#ar8@=J0nM`TZR^kc~XNw_Uq78#a^LJR8R0} zmvEkcVG=8R`P7VYG|mKVz8)tgCh`Fx6B)0lnK4#3McQYDU2tK&XLy>h!-Ejp$Y;E% zc@UdoH&1Py%@?gAkr`RmN4ZqaO?-BSbJa74uQ zsw7QwQjAX?TIqLSX@^Mudc$}&?q(pzFNi?hgxs=fO1CCVVH;;v<+wuRMRDHV_yrMo-*nqvqJ*%k@(XKYK5WK&g?oh-gAhxF`6|?A*|NihG5% zRAqf6cEK?oGGaLEv~mu`x#ODD_i>@uOPaT55UZRTs_4LRai= zIJUiDK>h+FS?uc3D_9+O&`l%93#VzZnG1Su*D8CNr9cF7d3ZvO)(jOb)6#j$gD6jwLQY>rJd3%{&lY^*Y2}%~FBof~ZbG(I zKf(9eyyNa3dY1)sn_=XwBHr$w%q~79$UXP*RARc5wF;(K^03t#Y>=MJb%2IxE|mqs5qW z2Wf{VT@~+)o&o!^be3~dSMlU{Z8ot&rs0$C9ZR#1EwzD<^i~D%?Sbw0TgF%N)q>1- z^;q=M>@cx6b3NUCr>f$e5rHESa>Ou3JkCg`tCNh%tZ*i(j=itva+^E9vPDg=a`dSf zd81v?yLali)1IZuGUrjg0>2;vWB7lgQ2lqzw@xRtoXDPIMd&+1m;M)lmJ|64)r$Tr z{VxI;LCiT2{awfRUte`jA0uIuLiGPbd|L-f;hO%xS$%`Wd_&-B5skY4tK&NY$3+B= zq-PUF5r>X1@%H$ruLHkeWkcQFCS&*0UQ_4tfEFW_^FS%|sDzxkew8+{|C8_ev!7C9 z!CD&Hc|vMUs?5@MrgC=NpdipQs5<`IRh!=HdY)fvHBzZmqhCTskC6Ur=Fo&MpUpn+ z!Wr@mSc$_r6(OBBPs$v$wIcT)6{XbAv9_%uo~%BW>H9~0p0{#3Ln-9-G@*aeMsJnWj*yG4r5nwfKym|8Q>fKphy zQxV-uPc=019wFvL6;SLp!VYXi>wa+NA@f4(0P(ogJ&N^HL||{VUXPk~(J(o89Q!FP zjiT+tOjzXrymA}xk-tWWQRBiWc7I|D`|di$72-P7y}JKqj$z0Ue{s3(8;Vl6Z&+_3WP6=ibYeu9m=rfkSqIJ?_mGgn z6OYaNz66Qpr~guPpp?3f?XRAiuT~f>QhWVHaa@!_wEk-AnfOD`p{zpLeC0f_uMf|L z5MznX?81ucGaLvXr*{C?ar8xQB%F{^OLP>4pf_pzU0az6j3)^$`+y`Wzix zE{IL5_uPPEp%m&SHWJ$dkN24)kLe=)6K|iBHxZ(x`aHLo6pOSyg+v*cW0QBV-%*| ztF&hs+`;7|WjDJsoC!)HTJPn&y@sz?*_D2N5W?^a>O-zZw~5O}io5uSp16=7Xo?XpOo*ORe!)kUW5Rs%ASSjR(4M93UTg+qY7X!?3J z#To?GCR7eNEvT%hc%y(9R%xwNOi&8XN&kDC)0=qV4O{U%w~K;6eTXLH%BkzzD`^M| zejK6XYM6gu)US7>I1OM|syyRkcE?eyVdH9X7YI4-S4up*Fo@+u%S`mCI4=5NUB}Az zyh*`O=I>x*Mg-<(h$f^_mA7La9~TPVA}^0E2S)twYQ3*IsHUiI{iV2|G{ zHhg-wSn-31RuTWrC-nRS>x1|v@IC5W-_B}0xm1FoOx$#(Zh*BSME_UA_lyOP&#K1WO)H^PM$v~Onvf(@k$GZkYY{xAKf~LAw?yst$vxTLEK@7;cWzNiXAPoN z#Dzy5bmjdq%=5~h6umz7J*yqq;m$Wb|FE%V`>*s=bRa@y=%ZHbqh}5mP!I95g1~4= z)zRb6$(|);HP+x}FNWh{r<02KWY^cQ+B%HQBzu*56f!I-Ltnn!KyEnv6N{=?l_5`w sb5{{DgXVgUd{#wFzuTK()_`%ey1U^oW*Ppb{-R5!8igYQM 0) { + this.push(path); + } } return this; @@ -36,7 +38,7 @@ D3D.Paths.prototype.clip = function (path, type) { clipper.AddPaths(path, ClipperLib.PolyType.ptClip, path.closed); clipper.Execute(type, solution); - return new D3D.Paths(solution); + return new D3D.Paths(solution, this.closed); }; D3D.Paths.prototype.union = function (path) { "use strict"; diff --git a/src/slicer.js b/src/slicer.js index c7e03ee..4949f5a 100644 --- a/src/slicer.js +++ b/src/slicer.js @@ -50,8 +50,6 @@ D3D.Slicer.prototype.setMesh = function (mesh) { //get unique lines from geometry; this.createLines(); - console.log(this.lines); - return this; }; D3D.Slicer.prototype.createLines = function () { @@ -320,16 +318,25 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { var highFillTemplate = this.getFillTemplate(bounds, wallThickness, even, !even); fill.join(highFillTemplate.intersect(highFillArea)); } - - /* + outerLayer = outerLayer.optimizePath(start); - insets = insets.optimizePath(outerLayer.lastPoint()); - fill = fill.optimizePath(insets.lastPoint()); - start = fill.lastPoint(); - */ - fill = fill.optimizePath(insets.lastPoint()); - - + if (insets.length > 0) { + insets = insets.optimizePath(outerLayer.lastPoint()); + fill = fill.optimizePath(insets.lastPoint()); + } + else { + fill = fill.optimizePath(outerLayer.lastPoint()); + } + if (fill.length > 0) { + start = fill.lastPoint(); + } + else if (insets.length > 0) { + start = insets.lastPoint(); + } + else { + start = outerLayer.lastPoint(); + } + layerData.push({ outerLayer: outerLayer.scaleDown(scale), fill: fill.scaleDown(scale),