diff --git a/build/d3d.js b/build/d3d.js index f42af8b..98775db 100644 --- a/build/d3d.js +++ b/build/d3d.js @@ -568,140 +568,135 @@ D3D.Printer.prototype.subsituteVariables = function (gcode) { * ******************************************************/ -D3D.Path = function (path, closed) { +D3D.Paths = function (paths, closed) { "use strict"; - this.path = path || []; + Array.call(this); + + this.setPaths(paths || []); + this.closed = (closed !== undefined) ? closed : true; }; -D3D.Path.prototype.setPath = function (path) { +D3D.Paths.prototype = Object.create(Array.prototype); +D3D.Paths.prototype.setPaths = function (paths) { "use strict"; - this.path = path; + for (var i = 0; i < paths.length; i ++) { + var path = paths[i]; + this.push(path); + } return this; }; -D3D.Path.prototype.union = function (path) { +D3D.Paths.prototype.clip = function (path, type) { "use strict"; var solution = new ClipperLib.Paths(); var clipper = new ClipperLib.Clipper(); - clipper.AddPaths(this.path, ClipperLib.PolyType.ptSubject, this.closed); - clipper.AddPaths(path.path, ClipperLib.PolyType.ptClip, path.closed); - clipper.Execute(ClipperLib.ClipType.ctUnion, solution); + clipper.AddPaths(this, ClipperLib.PolyType.ptSubject, this.closed); + clipper.AddPaths(path, ClipperLib.PolyType.ptClip, path.closed); + clipper.Execute(type, solution); - return new D3D.Path(solution, this.closed); + return new D3D.Paths(solution); }; -D3D.Path.prototype.difference = function (path) { +D3D.Paths.prototype.union = function (path) { "use strict"; - var solution = new ClipperLib.Paths(); - - var clipper = new ClipperLib.Clipper(); - clipper.AddPaths(this.path, ClipperLib.PolyType.ptSubject, this.closed); - clipper.AddPaths(path.path, ClipperLib.PolyType.ptClip, path.closed); - clipper.Execute(ClipperLib.ClipType.ctDifference, solution); - - return new D3D.Path(solution, this.closed); + return this.clip(path, ClipperLib.ClipType.ctUnion); }; -D3D.Path.prototype.intersect = function (path) { +D3D.Paths.prototype.difference = function (path) { "use strict"; - var solution = new ClipperLib.Paths(); - - var clipper = new ClipperLib.Clipper(); - clipper.AddPaths(this.path, ClipperLib.PolyType.ptSubject, this.closed); - clipper.AddPaths(path.path, ClipperLib.PolyType.ptClip, path.closed); - clipper.Execute(ClipperLib.ClipType.ctIntersection, solution); - - return new D3D.Path(solution, this.closed); + return this.clip(path, ClipperLib.ClipType.ctDifference); }; -D3D.Path.prototype.xor = function () { +D3D.Paths.prototype.intersect = function (path) { "use strict"; - var solution = new ClipperLib.Paths(); - - var clipper = new ClipperLib.Clipper(); - clipper.AddPaths(this.path, ClipperLib.PolyType.ptSubject, this.closed); - clipper.AddPaths(path.path, ClipperLib.PolyType.ptClip, path.closed); - clipper.Execute(ClipperLib.ClipType.ctXor, solution); - - return new D3D.Path(solution, this.closed); + return this.clip(path, ClipperLib.ClipType.ctIntersection); }; -D3D.Path.prototype.offset = function (offset) { +D3D.Paths.prototype.xor = function () { + "use strict"; + + return this.clip(path, ClipperLib.ClipType.ctXor); +}; +D3D.Paths.prototype.offset = function (offset) { "use strict"; var solution = new ClipperLib.Paths(); var co = new ClipperLib.ClipperOffset(1, 1); - co.AddPaths(this.path, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon); + co.AddPaths(this, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon); co.Execute(solution, offset); - return new D3D.Path(solution, this.closed); + return new D3D.Paths(solution); }; -D3D.Path.prototype.scaleUp = function (factor) { +D3D.Paths.prototype.scaleUp = function (factor) { "use strict"; - var path = ClipperLib.JS.ScaleUpPaths(this.path, factor); + var path = ClipperLib.JS.ScaleUpPaths(this, factor); return this; }; -D3D.Path.prototype.scaleDown = function (factor) { +D3D.Paths.prototype.scaleDown = function (factor) { "use strict"; - var path = ClipperLib.JS.ScaleDownPaths(this.path, factor); + var path = ClipperLib.JS.ScaleDownPaths(this, factor); return this; }; -D3D.Path.prototype.tresholdArea = function (minArea) { +D3D.Paths.prototype.tresholdArea = function (minArea) { "use strict"; - for (var i = 0; i < this.path.length; i ++) { - var shape = this.path[i]; + for (var i = 0; i < this.length; i ++) { + var shape = this[i]; var area = ClipperLib.Clipper.Area(shape); if (area < minArea) { - this.path.splice(i, 1); + this.splice(i, 1); i --; } } return areas; }; -D3D.Path.prototype.area = function () { +D3D.Paths.prototype.area = function () { "use strict"; - var areas = []; - - for (var i = 0; i < this.path.length; i ++) { - var shape = this.path[i]; - - areas.push(ClipperLib.Clipper.Area(shape)) - } - - return areas; + return ClipperLib.Clipper.Area(this); }; -D3D.Path.prototype.join = function (path) { +D3D.Paths.prototype.join = function (path) { "use strict"; - this.path = this.path.concat(path.path); + for (var i = 0; i < path.length; i ++) { + this.push(path[i]); + } return this; -} -D3D.Path.prototype.clone = function () { +}; +D3D.Paths.prototype.clone = function () { "use strict"; - var path = ClipperLib.JS.Clone(this.path); + return new D3D.Paths(ClipperLib.JS.Clone(this), this.closed); +}; +D3D.Paths.prototype.bounds = function () { + "use strict"; - return new D3D.Path(path, this.closed); -} -D3D.Path.prototype.draw = function (context, color) { + return ClipperLib.Clipper.GetBounds(this); +}; +D3D.Paths.prototype.reverse = function () { + "use strict"; + + ClipperLib.Clipper.ReversePaths(this); + + return this; +}; +D3D.Paths.prototype.draw = function (context, color) { "use strict"; context.strokeStyle = color; - for (var i = 0; i < this.path.length; i ++) { - var shape = this.path[i]; + for (var i = 0; i < this.length; i ++) { + var shape = this[i]; context.beginPath(); var length = this.closed ? (shape.length + 1) : shape.length; @@ -738,12 +733,11 @@ D3D.Slicer.prototype.setMesh = function (mesh) { mesh.updateMatrix(); var geometry = mesh.geometry.clone(); - geometry.mergeVertices(); - geometry.applyMatrix(mesh.matrix); - if (geometry instanceof THREE.BufferGeometry) { geometry = new THREE.Geometry().fromBufferGeometry(geometry); } + geometry.mergeVertices(); + geometry.applyMatrix(mesh.matrix); this.geometry = geometry; @@ -770,7 +764,8 @@ D3D.Slicer.prototype.createLines = function () { self.lines.push({ line: new THREE.Line3(self.geometry.vertices[a], self.geometry.vertices[b]), connects: [], - normals: [] + normals: [], + ignore: 0 }); } @@ -779,22 +774,25 @@ D3D.Slicer.prototype.createLines = function () { for (var i = 0; i < this.geometry.faces.length; i ++) { var face = this.geometry.faces[i]; - var normal = new THREE.Vector2().set(face.normal.x, face.normal.z).normalize(); - //check for only adding unique lines - //returns index of said line - var a = addLine(face.a, face.b); - var b = addLine(face.b, face.c); - var c = addLine(face.c, face.a); + //if (face.normal.y !== 1 && face.normal.y !== -1) { + var normal = new THREE.Vector2().set(face.normal.x, face.normal.z).normalize(); - //set connecting lines (based on face) - this.lines[a].connects.push(b, c); - this.lines[b].connects.push(c, a); - this.lines[c].connects.push(a, b); + //check for only adding unique lines + //returns index of said line + var a = addLine(face.a, face.b); + var b = addLine(face.b, face.c); + var c = addLine(face.c, face.a); - this.lines[a].normals.push(normal); - this.lines[b].normals.push(normal); - this.lines[c].normals.push(normal); + //set connecting lines (based on face) + this.lines[a].connects.push(b, c); + this.lines[b].connects.push(c, a); + this.lines[c].connects.push(a, b); + + this.lines[a].normals.push(normal); + this.lines[b].normals.push(normal); + this.lines[c].normals.push(normal); + //} } }; D3D.Slicer.prototype.slice = function (height, step) { @@ -820,7 +818,7 @@ D3D.Slicer.prototype.slice = function (height, step) { var slices = []; - for (var layer = 1; layer < layersIntersections.length; layer ++) { + for (var layer = 1; layer < layersIntersections.length-1; layer ++) { var layerIntersections = layersIntersections[layer]; var y = layer*step; @@ -837,7 +835,7 @@ D3D.Slicer.prototype.slice = function (height, step) { } var done = []; - var slice = []; + var slice = new D3D.Paths([], true); for (var i = 0; i < layerIntersections.length; i ++) { var index = layerIntersections[i]; @@ -898,15 +896,34 @@ D3D.Slicer.prototype.slice = function (height, step) { //think this check is not nescesary, always higher as 0 if (shape.length > 0) { - slice.push(shape); + slice.push(new D3D.Paths([shape])); } } } + var layerParts = []; + + for (var i = 0; i < slice.length; i ++) { + var layerPart1 = slice[i]; + var merge = false; + + for (var j = 0; j < layerParts.length; j ++) { + var layerPart2 = layerParts[j]; + + if (layerPart2.intersect(layerPart1).length > 0) { + layerPart2.join(layerPart1); + merge = true; + break; + } + } + if (!merge) { + layerParts.push(layerPart1); + } + } + //stop when ther are no intersects - if (slice.length > 0) { - slices.push(new D3D.Path(slice, true)); - //slices.push(slice); + if (layerParts.length > 0) { + slices.push(layerParts); } else { break; @@ -934,37 +951,59 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { for (var layer = 0; layer < slices.length; layer ++) { var slice = slices[layer]; - - var outerLayer = slice.clone(); - outerLayer.scaleUp(scale); - - var insets = new D3D.Path(); - for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) { - var inset = outerLayer.offset(-offset); - - insets.join(inset); + + var layerData = []; + data.push(layerData); + + var downSkin = new D3D.Paths(); + if (layer - skinCount >= 0) { + var downLayer = slices[layer - skinCount]; + for (var i = 0; i < downLayer.length; i ++) { + downSkin.join(downLayer[i]); + } } + var upSkin = new D3D.Paths(); + if (layer + skinCount < slices.length) { + var downLayer = slices[layer + skinCount]; + for (var i = 0; i < downLayer.length; i ++) { + upSkin.join(downLayer[i]); + } + } + var surroundingLayer = upSkin.intersect(downSkin).clone().scaleUp(scale); + var sliceData = []; - var fillArea = (inset || outerLayer).offset(-wallThickness/2); + for (var i = 0; i < slice.length; i ++) { + var part = slice[i]; - var downFill = (layer - skinCount >= 0) ? slices[layer - skinCount] : new D3D.Path(); - var upFill = (layer + skinCount < slices.length) ? slices[layer + skinCount] : new D3D.Path(); - var highFillArea = fillArea.difference(downFill.intersect(upFill).scaleUp(scale)); + var outerLayer = part.clone(); + outerLayer.scaleUp(scale); - var lowFillArea = fillArea.difference(highFillArea); + var insets = new D3D.Paths(); + for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) { + var inset = outerLayer.offset(-offset); + + insets.join(inset); + } + + var fillArea = (inset || outerLayer).offset(-wallThickness/2); + + var highFillArea = fillArea.difference(surroundingLayer); + + var lowFillArea = fillArea.difference(highFillArea); + + var fill = new D3D.Paths([]); + + fill.join(lowFillTemplate.intersect(lowFillArea)); - var fill = new D3D.Path([], false); - fill.join(lowFillTemplate.intersect(lowFillArea)); - if (highFillArea.path.length > 0) { var highFillTemplate = this.getFillTemplate(dimensionsZ, wallThickness, (layer % 2 === 0), (layer % 2 === 1)); fill.join(highFillTemplate.intersect(highFillArea)); - } - data.push({ - outerLayer: outerLayer.scaleDown(scale), - insets: insets.scaleDown(scale), - fill: fill.scaleDown(scale) - }); + layerData.push({ + outerLayer: outerLayer.scaleDown(scale), + fill: fill.scaleDown(scale), + insets: insets.scaleDown(scale) + }); + } } return data; @@ -972,7 +1011,7 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { D3D.Slicer.prototype.getFillTemplate = function (dimension, size, even, uneven) { "use strict"; - var paths = []; + var paths = new D3D.Paths([], false); if (even) { for (var length = 0; length <= dimension; length += size) { @@ -986,7 +1025,7 @@ D3D.Slicer.prototype.getFillTemplate = function (dimension, size, even, uneven) } //return paths; - return new D3D.Path(paths, false); + return paths; }; D3D.Slicer.prototype.dataToGcode = function (data, printer) { "use strict"; @@ -1008,13 +1047,15 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { function sliceToGcode (slice) { var gcode = []; - for (var i = 0; i < slice.path.length; i ++) { - var shape = slice.path[i]; + for (var i = 0; i < slice.length; i ++) { + var shape = slice[i]; var previousPoint; - for (var j = 0; j < shape.length; j ++) { - var point = shape[j]; + var length = slice.closed ? (shape.length + 1) : shape.length; + + for (var j = 0; j < length; j ++) { + var point = shape[j % shape.length]; if (j === 0) { //TODO @@ -1082,9 +1123,13 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { var z = ((layer + 1) * layerHeight).toFixed(3); - gcode = gcode.concat(sliceToGcode(slice.outerLayer)); - gcode = gcode.concat(sliceToGcode(slice.insets)); - gcode = gcode.concat(sliceToGcode(slice.fill)); + for (var i = 0; i < slice.length; i ++) { + var layerPart = slice[i]; + + gcode = gcode.concat(sliceToGcode(layerPart.outerLayer)); + gcode = gcode.concat(sliceToGcode(layerPart.insets)); + gcode = gcode.concat(sliceToGcode(layerPart.fill)); + } } gcode = gcode.concat(printer.getEndCode()); @@ -1106,13 +1151,16 @@ D3D.Slicer.prototype.drawPaths = function (printer, min, max) { canvas.height = 400; var context = canvas.getContext("2d"); - for (var layer = min; layer < max; layer ++) { var slice = data[layer % data.length]; - slice.insets.draw(context, "blue"); - slice.outerLayer.draw(context, "green"); - slice.fill.draw(context, "red"); + for (var i = 0; i < slice.length; i ++) { + var layerPart = slice[i]; + + layerPart.insets.draw(context, "blue"); + layerPart.outerLayer.draw(context, "green"); + layerPart.fill.draw(context, "red"); + } } return canvas; diff --git a/build/d3d.min.js b/build/d3d.min.js index 6a49e7a..aad9a10 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.Path=function(t,e){"use strict";this.path=t||[],this.closed=void 0!==e?e:!0},D3D.Path.prototype.setPath=function(t){"use strict";return this.path=t,this},D3D.Path.prototype.union=function(t){"use strict";var e=new ClipperLib.Paths,i=new ClipperLib.Clipper;return i.AddPaths(this.path,ClipperLib.PolyType.ptSubject,this.closed),i.AddPaths(t.path,ClipperLib.PolyType.ptClip,t.closed),i.Execute(ClipperLib.ClipType.ctUnion,e),new D3D.Path(e,this.closed)},D3D.Path.prototype.difference=function(t){"use strict";var e=new ClipperLib.Paths,i=new ClipperLib.Clipper;return i.AddPaths(this.path,ClipperLib.PolyType.ptSubject,this.closed),i.AddPaths(t.path,ClipperLib.PolyType.ptClip,t.closed),i.Execute(ClipperLib.ClipType.ctDifference,e),new D3D.Path(e,this.closed)},D3D.Path.prototype.intersect=function(t){"use strict";var e=new ClipperLib.Paths,i=new ClipperLib.Clipper;return i.AddPaths(this.path,ClipperLib.PolyType.ptSubject,this.closed),i.AddPaths(t.path,ClipperLib.PolyType.ptClip,t.closed),i.Execute(ClipperLib.ClipType.ctIntersection,e),new D3D.Path(e,this.closed)},D3D.Path.prototype.xor=function(){"use strict";var t=new ClipperLib.Paths,e=new ClipperLib.Clipper;return e.AddPaths(this.path,ClipperLib.PolyType.ptSubject,this.closed),e.AddPaths(path.path,ClipperLib.PolyType.ptClip,path.closed),e.Execute(ClipperLib.ClipType.ctXor,t),new D3D.Path(t,this.closed)},D3D.Path.prototype.offset=function(t){"use strict";var e=new ClipperLib.Paths,i=new ClipperLib.ClipperOffset(1,1);return i.AddPaths(this.path,ClipperLib.JoinType.jtRound,ClipperLib.EndType.etClosedPolygon),i.Execute(e,t),new D3D.Path(e,this.closed)},D3D.Path.prototype.scaleUp=function(t){"use strict";ClipperLib.JS.ScaleUpPaths(this.path,t);return this},D3D.Path.prototype.scaleDown=function(t){"use strict";ClipperLib.JS.ScaleDownPaths(this.path,t);return this},D3D.Path.prototype.tresholdArea=function(t){"use strict";for(var e=0;er&&(this.path.splice(e,1),e--)}return areas},D3D.Path.prototype.area=function(){"use strict";for(var t=[],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.mergeVertices(),e.applyMatrix(t.matrix),e instanceof THREE.BufferGeometry&&(e=(new THREE.Geometry).fromBufferGeometry(e)),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:[]})),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 p=[],c=1;c0)break;f=-1}else f=-1}v.length>0&&P.push(v)}}if(!(P.length>0))break;p.push(new D3D.Path(P,!0))}return p},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,p=(e.config["printer.brimOffset"]*i,Math.ceil(o/r)),c=[],h=this.getFillTemplate(n,a,!0,!0),u=0;u=D;D+=s){var g=f.offset(-D);d.join(g)}var y=(g||f).offset(-s/2),P=u-p>=0?t[u-p]:new D3D.Path,v=u+p0){var b=this.getFillTemplate(n,s,u%2===0,u%2===1);x.join(b.intersect(w))}c.push({outerLayer:f.scaleDown(i),insets:d.scaleDown(i),fill:x.scaleDown(i)})}return c},D3D.Slicer.prototype.getFillTemplate=function(t,e,i,r){"use strict";var n=[];if(i)for(var s=0;t>=s;s+=e)n.push([{X:s,Y:0},{X:s,Y:t}]);if(r)for(var s=0;t>=s;s+=e)n.push([{X:0,Y:s},{X:t,Y:s}]);return new D3D.Path(n,!1)},D3D.Slicer.prototype.dataToGcode=function(t,e){"use strict";function i(t){for(var e=[],i=0;if&&u&&e.push(["G0","E"+(g-d).toFixed(3),"F"+(60*l).toFixed(3)].join(" ")),e.push(["G0","X"+a.X.toFixed(3)+" Y"+a.Y.toFixed(3)+" Z"+x,"F"+60*p].join(" ")),g>f&&u&&e.push(["G0","E"+g.toFixed(3),"F"+(60*l).toFixed(3)].join(" "));else{var c=(new THREE.Vector2).set(a.X,a.Y),D=(new THREE.Vector2).set(n.X,n.Y),w=c.distanceTo(D);g+=w*h*r/P*v,e.push(["G1","X"+a.X.toFixed(3)+" Y"+a.Y.toFixed(3)+" Z"+x,"F"+y,"E"+g.toFixed(3)].join(" "))}n=a}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"],p=e.config["printer.travelSpeed"],c=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"],d=e.config["printer.retraction.amount"],D=e.getStartCode(),g=0,y=o?(60*s).toFixed(3):(60*n).toFixed(3),P=Math.pow(c/2,2)*Math.PI,v=a,w=0;wc;c++){var h=o[c%o.length];h.insets.draw(p,"blue"),h.outerLayer.draw(p,"green"),h.fill.draw(p,"red")}return a},D3D.Slicer.prototype.getGcode=function(t){"use strict";var e=t.config["printer.layerHeight"],i=t.config["printer.dimensions.z"],r=(new Date).getTime(),n=this.slice(i,e),s=(new Date).getTime();console.log("Slicing: "+(s-r)+"ms");var r=(new Date).getTime(),o=this.slicesToData(n,t),s=(new Date).getTime();console.log("Data: "+(s-r)+"ms");var r=(new Date).getTime(),a=this.dataToGcode(o,t),s=(new Date).getTime();return console.log("Gcode: "+(s-r)+"ms"),a}; \ No newline at end of file +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;er&&(this.splice(e,1),e--)}return areas},D3D.Paths.prototype.area=function(){"use strict";return ClipperLib.Clipper.Area(this)},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 p=[],c=1;c0)break;f=-1}else f=-1}P.length>0&&v.push(new D3D.Paths([P]))}}for(var T=[],r=0;r0){L.join(k),I=!0;break}}I||T.push(k)}if(!(T.length>0))break;p.push(T)}return p},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,p=(e.config["printer.brimOffset"]*i,Math.ceil(o/r)),c=[],h=this.getFillTemplate(n,a,!0,!0),u=0;u=0)for(var D=t[u-p],d=0;d=x;x+=s){var b=m.offset(-x);w.join(b)}var B=(b||m).offset(-s/2),A=B.difference(v),C=B.difference(A),S=new D3D.Paths([]);S.join(h.intersect(C));var T=this.getFillTemplate(n,s,u%2===0,u%2===1);S.join(T.intersect(A)),f.push({outerLayer:m.scaleDown(i),fill:S.scaleDown(i),insets:w.scaleDown(i)})}}return c},D3D.Slicer.prototype.getFillTemplate=function(t,e,i,r){"use strict";var n=new D3D.Paths([],!1);if(i)for(var s=0;t>=s;s+=e)n.push([{X:s,Y:0},{X:s,Y:t}]);if(r)for(var s=0;t>=s;s+=e)n.push([{X:0,Y:s},{X:t,Y:s}]);return n},D3D.Slicer.prototype.dataToGcode=function(t,e){"use strict";function i(t){for(var e=[],i=0;ia;a++){var c=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"+c.X.toFixed(3)+" Y"+c.Y.toFixed(3)+" Z"+x,"F"+60*p].join(" ")),d>f&&u&&e.push(["G0","E"+d.toFixed(3),"F"+(60*l).toFixed(3)].join(" "));else{var D=(new THREE.Vector2).set(c.X,c.Y),m=(new THREE.Vector2).set(n.X,n.Y),w=D.distanceTo(m);d+=w*h*r/v*P,e.push(["G1","X"+c.X.toFixed(3)+" Y"+c.Y.toFixed(3)+" Z"+x,"F"+y,"E"+d.toFixed(3)].join(" "))}n=c}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"],p=e.config["printer.travelSpeed"],c=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(c/2,2)*Math.PI,P=a,m=0;mc;c++)for(var h=o[c%o.length],u=0;u - @@ -119,6 +118,31 @@ var loader = new THREE.STLLoader(); loader.load("models/diamond.stl", function (geometry) { var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1); //var geometry = new THREE.TorusGeometry(20, 10, 30, 30); + + var geometry = (function () { + "use strict"; + + var circle = new THREE.Shape(); + circle.absarc(0, 0, 10, 0, Math.PI*2, false); + + var hole = new THREE.Path(); + hole.absarc(0, 0, 5, 0, Math.PI*2, true ); + + circle.holes.push(hole); + + var matrix = new THREE.Matrix4(); + matrix.makeRotationX(Math.PI*1.5); + + var geometry = new THREE.ExtrudeGeometry(circle, { + amount: 3, + bevelEnabled: false, + steps: 1 + }); + geometry.applyMatrix(matrix); + + return geometry; + })(); + var mesh = new THREE.Mesh(geometry, material); mesh.position.x = 100; @@ -137,8 +161,8 @@ loader.load("models/diamond.stl", function (geometry) { var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); - var img = slicer.drawPaths(printer, 0, 10); - 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/path.js b/src/path.js deleted file mode 100644 index 9781526..0000000 --- a/src/path.js +++ /dev/null @@ -1,140 +0,0 @@ -/****************************************************** -* -* Path -* -* Abstraction layer for annoying clipper js -* -******************************************************/ - -D3D.Path = function (path, closed) { - "use strict"; - - Array.call(this); - - this.setPath(path || []); - - this.closed = (closed !== undefined) ? closed : true; -}; -D3D.Path.prototype = Object.create(Array.prototype); -D3D.Path.prototype.setPath = function (path) { - "use strict"; - - for (var i = 0; i < path.length; i ++) { - this.push(path[i]); - } - - return this; -}; -D3D.Path.prototype.clip = function (path, type) { - "use strict"; - - var solution = new ClipperLib.Paths(); - - var clipper = new ClipperLib.Clipper(); - clipper.AddPath(this, ClipperLib.PolyType.ptSubject, true); - if (path instanceof D3D.Path) { - clipper.AddPath(path, ClipperLib.PolyType.ptClip, true); - } - else if (path instanceof D3D.Paths) { - clipper.AddPaths(path, ClipperLib.PolyType.ptClip, true); - } - clipper.Execute(type, solution); - - return new D3D.Paths(solution, this.closed); -}; -D3D.Path.prototype.union = function (path) { - "use strict"; - - return this.clip(path, ClipperLib.ClipType.ctUnion); -}; -D3D.Path.prototype.difference = function (path) { - "use strict"; - - return this.clip(path, ClipperLib.ClipType.ctDifference); -}; -D3D.Path.prototype.intersect = function (path) { - "use strict"; - - return this.clip(path, ClipperLib.ClipType.ctIntersection); -}; -D3D.Path.prototype.xor = function () { - "use strict"; - - return this.clip(path, ClipperLib.ClipType.ctXor); -}; -D3D.Path.prototype.offset = function (offset) { - "use strict"; - - var solution = new ClipperLib.Path(); - var co = new ClipperLib.ClipperOffset(2, 0.25); - co.AddPath(this, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon); - co.Execute(solution, offset); - - return new D3D.Path(solution[0], this.closed); -}; -D3D.Path.prototype.scaleUp = function (factor) { - "use strict"; - - ClipperLib.JS.ScaleUpPath(this, factor); - - return this; -}; -D3D.Path.prototype.scaleDown = function (factor) { - "use strict"; - - var path = ClipperLib.JS.ScaleDownPath(this, factor); - - return this; -}; -D3D.Path.prototype.tresholdArea = function (minArea) { - "use strict"; - - for (var i = 0; i < this.length; i ++) { - var shape = this[i]; - - var area = ClipperLib.Clipper.Area(shape); - - if (area < minArea) { - this.splice(i, 1); - i --; - } - } - - return areas; -}; -D3D.Path.prototype.area = function () { - "use strict"; - - return ClipperLib.Clipper.Area(this); -}; -D3D.Path.prototype.join = function (path) { - "use strict"; - - this.setPath(this.concat(path)); - - return this; -} -D3D.Path.prototype.clone = function () { - "use strict"; - - var path = ClipperLib.JS.Clone(this); - - return new D3D.Path(path, this.closed); -} -D3D.Path.prototype.draw = function (context, color) { - "use strict"; - - context.strokeStyle = color; - for (var i = 0; i < this.length; i ++) { - var shape = this[i]; - - context.beginPath(); - var length = this.closed ? (shape.length + 1) : shape.length; - for (var j = 0; j < length; j ++) { - var point = shape[j % shape.length]; - - context.lineTo(point.X*2, point.Y*2); - } - context.stroke(); - } -}; \ No newline at end of file diff --git a/src/paths.js b/src/paths.js index 9736c05..ba7ac12 100644 --- a/src/paths.js +++ b/src/paths.js @@ -6,14 +6,14 @@ * ******************************************************/ -D3D.Paths = function (paths) { +D3D.Paths = function (paths, closed) { "use strict"; Array.call(this); this.setPaths(paths || []); - this.closed = (this[0] !== undefined) ? this[0].closed : true; + this.closed = (closed !== undefined) ? closed : true; }; D3D.Paths.prototype = Object.create(Array.prototype); D3D.Paths.prototype.setPaths = function (paths) { @@ -21,10 +21,6 @@ D3D.Paths.prototype.setPaths = function (paths) { for (var i = 0; i < paths.length; i ++) { var path = paths[i]; - if (!(path instanceof D3D.Path)) { - //console.log("Path not instance of D3D.Path, converting path to D3D.Path"); - path = new D3D.Path(path, true); - } this.push(path); } @@ -37,12 +33,7 @@ D3D.Paths.prototype.clip = function (path, type) { var clipper = new ClipperLib.Clipper(); clipper.AddPaths(this, ClipperLib.PolyType.ptSubject, this.closed); - if (path instanceof D3D.Paths) { - clipper.AddPaths(path, ClipperLib.PolyType.ptClip, path.closed); - } - else if (path instanceof D3D.Path) { - clipper.AddPath(path, ClipperLib.PolyType.ptClip, path.closed); - } + clipper.AddPaths(path, ClipperLib.PolyType.ptClip, path.closed); clipper.Execute(type, solution); return new D3D.Paths(solution); @@ -124,13 +115,19 @@ D3D.Paths.prototype.join = function (path) { D3D.Paths.prototype.clone = function () { "use strict"; - var paths = []; + return new D3D.Paths(ClipperLib.JS.Clone(this), this.closed); +}; +D3D.Paths.prototype.bounds = function () { + "use strict"; - for (var i = 0; i < this.length; i ++) { - paths.push(this[i].clone()); - } + return ClipperLib.Clipper.GetBounds(this); +}; +D3D.Paths.prototype.reverse = function () { + "use strict"; - return new D3D.Paths(paths); + ClipperLib.Clipper.ReversePaths(this); + + return this; }; D3D.Paths.prototype.draw = function (context, color) { "use strict"; diff --git a/src/slicer.js b/src/slicer.js index 47cde27..b3ce248 100644 --- a/src/slicer.js +++ b/src/slicer.js @@ -65,7 +65,7 @@ D3D.Slicer.prototype.createLines = function () { for (var i = 0; i < this.geometry.faces.length; i ++) { var face = this.geometry.faces[i]; - if (!(face.normal.y === 1 || face.normal.y === -1)) { + //if (face.normal.y !== 1 && face.normal.y !== -1) { var normal = new THREE.Vector2().set(face.normal.x, face.normal.z).normalize(); //check for only adding unique lines @@ -82,7 +82,7 @@ D3D.Slicer.prototype.createLines = function () { this.lines[a].normals.push(normal); this.lines[b].normals.push(normal); this.lines[c].normals.push(normal); - } + //} } }; D3D.Slicer.prototype.slice = function (height, step) { @@ -108,7 +108,7 @@ D3D.Slicer.prototype.slice = function (height, step) { var slices = []; - for (var layer = 1; layer < layersIntersections.length; layer ++) { + for (var layer = 1; layer < layersIntersections.length-1; layer ++) { var layerIntersections = layersIntersections[layer]; var y = layer*step; @@ -130,7 +130,7 @@ D3D.Slicer.prototype.slice = function (height, step) { var index = layerIntersections[i]; if (done.indexOf(index) === -1) { - var shape = new D3D.Path([], true); + var shape = []; while (index !== -1) { var intersection = intersections[index]; @@ -186,16 +186,34 @@ D3D.Slicer.prototype.slice = function (height, step) { //think this check is not nescesary, always higher as 0 if (shape.length > 0) { - slice.push(shape); + slice.push(new D3D.Paths([shape])); } } } - //stop when ther are no intersects - if (slice.length > 0) { - var layerParts = []; + var layerParts = []; - slices.push(slice); + for (var i = 0; i < slice.length; i ++) { + var layerPart1 = slice[i]; + var merge = false; + + for (var j = 0; j < layerParts.length; j ++) { + var layerPart2 = layerParts[j]; + + if (layerPart2.intersect(layerPart1).length > 0) { + layerPart2.join(layerPart1); + merge = true; + break; + } + } + if (!merge) { + layerParts.push(layerPart1); + } + } + + //stop when ther are no intersects + if (layerParts.length > 0) { + slices.push(layerParts); } else { break; @@ -223,16 +241,26 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { for (var layer = 0; layer < slices.length; layer ++) { var slice = slices[layer]; - - var insets = new D3D.Paths(); - var fills = new D3D.Paths(); - var outerLayers = new D3D.Paths(); - - var downFill = (layer - skinCount >= 0) ? slices[layer - skinCount] : new D3D.Paths(); - var upFill = (layer + skinCount < slices.length) ? slices[layer + skinCount] : new D3D.Paths(); - //var surroundingLayer = downFill.intersect(upFill); - var surroundingLayer = upFill.clone().scaleUp(scale); - //D3D.Paths surroundingLayer + + var layerData = []; + data.push(layerData); + + var downSkin = new D3D.Paths(); + if (layer - skinCount >= 0) { + var downLayer = slices[layer - skinCount]; + for (var i = 0; i < downLayer.length; i ++) { + downSkin.join(downLayer[i]); + } + } + var upSkin = new D3D.Paths(); + if (layer + skinCount < slices.length) { + var downLayer = slices[layer + skinCount]; + for (var i = 0; i < downLayer.length; i ++) { + upSkin.join(downLayer[i]); + } + } + var surroundingLayer = upSkin.intersect(downSkin).clone().scaleUp(scale); + var sliceData = []; for (var i = 0; i < slice.length; i ++) { var part = slice[i]; @@ -240,10 +268,11 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { var outerLayer = part.clone(); outerLayer.scaleUp(scale); + var insets = new D3D.Paths(); for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) { var inset = outerLayer.offset(-offset); - insets.push(inset); + insets.join(inset); } var fillArea = (inset || outerLayer).offset(-wallThickness/2); @@ -254,19 +283,17 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { var fill = new D3D.Paths([]); - fills.join(lowFillTemplate.intersect(lowFillArea)); + fill.join(lowFillTemplate.intersect(lowFillArea)); var highFillTemplate = this.getFillTemplate(dimensionsZ, wallThickness, (layer % 2 === 0), (layer % 2 === 1)); - fills.join(highFillTemplate.intersect(highFillArea)); + fill.join(highFillTemplate.intersect(highFillArea)); - outerLayers.push(outerLayer); + layerData.push({ + outerLayer: outerLayer.scaleDown(scale), + fill: fill.scaleDown(scale), + insets: insets.scaleDown(scale) + }); } - - data.push({ - outerLayer: outerLayers.scaleDown(scale), - insets: insets.scaleDown(scale), - fill: fills.scaleDown(scale) - }); } return data; @@ -274,21 +301,21 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) { D3D.Slicer.prototype.getFillTemplate = function (dimension, size, even, uneven) { "use strict"; - var paths = []; + var paths = new D3D.Paths([], false); if (even) { for (var length = 0; length <= dimension; length += size) { - paths.push(new D3D.Path([{X: length, Y: 0}, {X: length, Y: dimension}], false)); + paths.push([{X: length, Y: 0}, {X: length, Y: dimension}]); } } if (uneven) { for (var length = 0; length <= dimension; length += size) { - paths.push(new D3D.Path([{X: 0, Y: length}, {X: dimension, Y: length}], false)); + paths.push([{X: 0, Y: length}, {X: dimension, Y: length}]); } } //return paths; - return new D3D.Paths(paths); + return paths; }; D3D.Slicer.prototype.dataToGcode = function (data, printer) { "use strict"; @@ -315,8 +342,10 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { var previousPoint; - for (var j = 0; j < shape.length; j ++) { - var point = shape[j]; + var length = slice.closed ? (shape.length + 1) : shape.length; + + for (var j = 0; j < length; j ++) { + var point = shape[j % shape.length]; if (j === 0) { //TODO @@ -384,9 +413,13 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) { var z = ((layer + 1) * layerHeight).toFixed(3); - gcode = gcode.concat(sliceToGcode(slice.outerLayer)); - gcode = gcode.concat(sliceToGcode(slice.insets)); - gcode = gcode.concat(sliceToGcode(slice.fill)); + for (var i = 0; i < slice.length; i ++) { + var layerPart = slice[i]; + + gcode = gcode.concat(sliceToGcode(layerPart.outerLayer)); + gcode = gcode.concat(sliceToGcode(layerPart.insets)); + gcode = gcode.concat(sliceToGcode(layerPart.fill)); + } } gcode = gcode.concat(printer.getEndCode()); @@ -411,9 +444,13 @@ D3D.Slicer.prototype.drawPaths = function (printer, min, max) { for (var layer = min; layer < max; layer ++) { var slice = data[layer % data.length]; - //slice.insets.draw(context, "blue"); - slice.outerLayer.draw(context, "green"); - slice.fill.draw(context, "red"); + for (var i = 0; i < slice.length; i ++) { + var layerPart = slice[i]; + + layerPart.insets.draw(context, "blue"); + layerPart.outerLayer.draw(context, "green"); + layerPart.fill.draw(context, "red"); + } } return canvas; @@ -437,7 +474,6 @@ D3D.Slicer.prototype.getGcode = function (printer) { var data = this.slicesToData(slices, printer); var end = new Date().getTime(); - console.log(data); console.log("Data: " + (end - start) + "ms"); //return data;