From e441c142b441b9a106658759447b57679e045129 Mon Sep 17 00:00:00 2001 From: casperlamboo Date: Fri, 15 May 2015 15:07:47 +0200 Subject: [PATCH] fixed mergin vertexes --- build/d3d.js | 86 +++++++++++++++++++++++++----------- build/d3d.min.js | 2 +- models/sonder_one_piece.stl | Bin 0 -> 4284 bytes slice_test.html | 24 +++++----- src/paths.js | 4 +- src/slicer.js | 36 +++++++++++++-- 6 files changed, 108 insertions(+), 44 deletions(-) create mode 100644 models/sonder_one_piece.stl diff --git a/build/d3d.js b/build/d3d.js index b744a11..95c9744 100644 --- a/build/d3d.js +++ b/build/d3d.js @@ -644,41 +644,75 @@ D3D.Paths.prototype.scaleDown = function (factor) { return this; }; +D3D.Paths.prototype.lastPoint = function () { + "use strict"; + + var lastPath = this[this.length - 1]; + var lastPoint = this.closed ? lastPath[0] : lastPath[lastPath.length - 1]; + return new THREE.Vector2(lastPoint.X, lastPoint.Y); +}; D3D.Paths.prototype.optimizePath = function (start) { "use strict"; - var optimizedPaths = new D3D.Paths(); + var optimizedPaths = new D3D.Paths([], this.closed); + var donePaths = []; while (optimizedPaths.length !== this.length) { - var minLength = undefined; + var minLength = false; var reverse; var minPath; + var offset; + var pathIndex; for (var i = 0; i < this.length; i ++) { var path = this[i]; - if (optimizedPaths.indexOf(path) === -1) { - var startPoint = new THREE.Vector2(path[0].X, path[0].Y); - var endPoint = new THREE.Vector2(path[path.length - 1].X, path[path.length - 1].Y); - var length = startPoint.sub(start).length(); - if (minLength === undefined || length < minLength) { - minPath = path; - minLength = length; - reverse = false; + if (donePaths.indexOf(i) === -1) { + + if (this.closed) { + for (var j = 0; j < path.length; j ++) { + var point = new THREE.Vector2(path[j].X, path[j].Y); + var length = point.sub(start).length(); + if (minLength === false || length < minLength) { + minPath = path; + minLength = length; + offset = j; + pathIndex = i; + } + } } - var length = endPoint.sub(start).length(); - if (length < minLength) { - minPath = path; - minLength = length; - reverse = true; + else { + var startPoint = new THREE.Vector2(path[0].X, path[0].Y); + var length = startPoint.sub(start).length(); + if (minLength === false || length < minLength) { + minPath = path; + minLength = length; + reverse = false; + pathIndex = i; + } + var endPoint = new THREE.Vector2(path[path.length - 1].X, path[path.length - 1].Y); + var length = endPoint.sub(start).length(); + if (length < minLength) { + minPath = path; + minLength = length; + reverse = true; + pathIndex = i; + } } } } - if (reverse) { - minPath.reverse(); + if (this.closed) { + minPath = minPath.concat(minPath.splice(0, offset)); + var point = minPath[0]; } - var point = minPath[minPath.length - 1]; + else { + if (reverse) { + minPath.reverse(); + } + var point = minPath[minPath.length - 1]; + } + donePaths.push(pathIndex); start = new THREE.Vector2(point.X, point.Y); optimizedPaths.push(minPath); } @@ -728,8 +762,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; @@ -978,6 +1012,8 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { var brimOffset = printer.config["printer.brimOffset"] * scale; var skinCount = Math.ceil(shellThickness/layerHeight); + var start = new THREE.Vector2(0, 0); + var data = []; var lowFillTemplate = this.getFillTemplate({ @@ -1038,10 +1074,10 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { fill.join(highFillTemplate.intersect(highFillArea)); } - var lastPath = insets[insets.length - 1]; - var lastPoint = lastPath[lastPath.length - 1]; - var start = new THREE.Vector2(lastPoint.X, lastPoint.Y); - fill = fill.optimizePath(start); + outerLayer = outerLayer.optimizePath(start); + insets = insets.optimizePath(outerLayer.lastPoint()); + fill = fill.optimizePath(insets.lastPoint()); + start = fill.lastPoint(); layerData.push({ outerLayer: outerLayer.scaleDown(scale), @@ -1116,7 +1152,7 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { gcode.push([ "G0", "X" + point.X.toFixed(3) + " Y" + point.Y.toFixed(3) + " Z" + z, - "F" + (travelSpeed*60) + "F" + (travelSpeed * 60) ].join(" ")); if (extruder > retractionMinDistance && retractionEnabled) { diff --git a/build/d3d.min.js b/build/d3d.min.js index 0411b1c..5a968d5 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;ep)&&(r=o,n=p,i=!1);var p=c.sub(t).length();n>p&&(r=o,n=p,i=!0)}}i&&r.reverse();var h=r[r.length-1];t=new THREE.Vector2(h.X,h.Y),e.push(r)}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";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=[],h=this.getFillTemplate({left:0,top:0,right:n,bottom:n},a,!0,!0),u=0;u=0)for(var d=t[u-c],D=0;D=x;x+=s){var b=m.offset(-x);w.join(b)}var B=(b||m).offset(-s/2),T=B.difference(v),A=B.difference(T),S=new D3D.Paths([],!1);if(S.join(h.intersect(A)),T.length>0){var k=this.getFillTemplate(T.bounds(),s,u%2===0,u%2===1);S.join(k.intersect(T))}var C=w[w.length-1],I=C[C.length-1],E=new THREE.Vector2(I.X,I.Y);S=S.optimizePath(E),f.push({outerLayer:m.scaleDown(i),fill:S.scaleDown(i),insets:w.scaleDown(i)})}}return p},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;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;u6vwYwS}7_T+Em0^Dgo7Kppe43zq`I7Nk{VqTH*qV=!n6-^1&n2fEm)p zeBn%xwA55Y3c9ERD`>tk^TFukq>TodkIHGREVJL;o!|Jq%k0#&f54snp3m<*?z!jw zHaC0Gf^<`E_Tu!6oH^NxGfYbsWTa)7{`Y4pGd=|#x%#|qrAUi98zo2e~ccutyfnPuGYUaU*>0Kt?=9zvNyWO-B%&dO06yu zs34(6<;%T*%l|S%>0Rc5#I@6h#c}<6t>2b=nR^LTWM4^I_LZ!(T>GBx``g(E(uQwk z2bHL#g2cc3kOW%E?(vUG##X?w+pkY55FLM4Xg&QpU(E$O9Elyn2~?24`52f$E9`v6Qg=H@*7%hSrw6+at>pK{Jnl>w3KHl~*+CC>HTuI@ z*_kkWAfZO}hBMbAxuvo1H{t0-f5uGoomzjwn8--@N9DV1q#whFoIb`{KG*PJ%w3g` zJ^~TGsAi|;d-GU!{+$GzYK9ME+Q}#R=B__sC`hPL&FsziTngto%Y!*~xT*cHILj)v z>Fs|CJU5IXfeI3@PuMRWyIY}^X32XH2~<33b>h`7mD;#(x|{JyDuD_TKQwe(zr7&3xC>q5m-|ByMbbOO)$%+mIOQ=L4fcE1bcM zy>LE`f}gSR^4%E}-E>%JNjtUDO_#;n;~Pc)gGV&ih;w3i^hVJX*{r4fD64yBkf7l~ zHr};5m9RcoX?zl6)knwBhD}z!bdKr+3EWM_HeZe-OOTyso}Q-o*zB$n-(RZHZdP?O zW2G4@SrSbZd3L^d!W2RUiD|pmih9#0+OH@3=y}{uA4V-#>^vqUNg>b*_ldFgLlM;I za_~)&V+a)_aBmoUplUD`U2*W56f>cMMD2=YB654RHsk)s^{5&mo}w<(oIIf-ULnv5 zcayPSu9&Db#mP^MNFY>@z+05D^%fJ&b2@p_i=z|*t<)|lP6?wYn3JzOFqYg&7SU@& zgVvuy%y@I+9n9FlQ(@FV4!*wYRKgn)Z_et-L=iLhh_-rpZ$0zaqQMlu#m*xZ%~A-o z5|%tsIKN#hzi?H*)zU0c#6#`;=*~HW3KH(xQgL9_Y0YK1r4v7`9!d)fZT#cO^ArND z@U~;@!lf`8Q0U+rgC`Njj+vuB#s=IPNXK#=d|B>9LInw|p}yw_!-?E>ZmXN25NL%F zGFCJpimv9^dGc4ugbEVsslE8}Fv=;n@x-8Xg+MDc^KAo$)2WFzerV789t6$(yjc$hw~Kzt?=$*jHisE_a;(-i`(aIP@cQXfg(zO(b2$x{dwB(P%`TX}sj{kGY` zJCa{g2(-evqMzE3ft2@O-FO>{s=p?XKt(0){Z?n}AJtAXL;wH) literal 0 HcmV?d00001 diff --git a/slice_test.html b/slice_test.html index 49b0bd0..3d0cde8 100644 --- a/slice_test.html +++ b/slice_test.html @@ -115,12 +115,12 @@ mesh.position.z = 100; //scene.add(mesh); var loader = new THREE.STLLoader(); -loader.load("models/diamond.stl", function (geometry) { - var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1); +loader.load("models/sonder_one_piece.stl", function (geometry) { + //var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1); //var geometry = new THREE.SphereGeometry(10, 10, 10); //var geometry = new THREE.TorusGeometry(20, 10, 30, 30); - + /* var geometry = (function () { "use strict"; @@ -136,7 +136,7 @@ loader.load("models/diamond.stl", function (geometry) { matrix.makeRotationX(Math.PI*1.5); var geometry = new THREE.ExtrudeGeometry(circle, { - amount: 3, + amount: 10, bevelEnabled: false, steps: 1 }); @@ -144,19 +144,19 @@ loader.load("models/diamond.stl", function (geometry) { return geometry; })(); - + */ var mesh = new THREE.Mesh(geometry, material); mesh.position.x = 100; mesh.position.z = 100; - /* - mesh.rotation.x = -Math.PI/2; - mesh.scale.x = mesh.scale.y = mesh.scale.z = 3; + ///* + //mesh.rotation.x = -Math.PI/2; + mesh.scale.x = mesh.scale.y = mesh.scale.z = 1; //mesh is lifted a little bit... - mesh.position.y = -0.6552429199218741; - */ + //mesh.position.y = 26.5; + //*/ scene.add(mesh); var slicer = new D3D.Slicer().setMesh(mesh); @@ -164,8 +164,8 @@ loader.load("models/diamond.stl", function (geometry) { var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); - //var img = slicer.drawPaths(printer, 7, 8); - //context.drawImage(img, 0, 0); + var img = slicer.drawPaths(printer, 7, 8); + context.drawImage(img, 0, 0); gcode = slicer.getGcode(printer); }); diff --git a/src/paths.js b/src/paths.js index 4af0d8a..dd88b63 100644 --- a/src/paths.js +++ b/src/paths.js @@ -200,8 +200,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; diff --git a/src/slicer.js b/src/slicer.js index ca38398..c7e03ee 100644 --- a/src/slicer.js +++ b/src/slicer.js @@ -20,19 +20,38 @@ 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(); + console.log(this.lines); + return this; }; D3D.Slicer.prototype.createLines = function () { @@ -283,6 +302,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); @@ -290,17 +310,25 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { var fill = new D3D.Paths([], false); - fill.join(lowFillTemplate.intersect(lowFillArea)); + if (lowFillTemplate.length > 0) { + fill.join(lowFillTemplate.intersect(lowFillArea)); + } if (highFillArea.length > 0) { - var highFillTemplate = this.getFillTemplate(highFillArea.bounds(), wallThickness, (layer % 2 === 0), (layer % 2 === 1)); + 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(); + */ + fill = fill.optimizePath(insets.lastPoint()); + layerData.push({ outerLayer: outerLayer.scaleDown(scale),