From 3a41b73c755159ace2f221e0f7d16710ebef1191 Mon Sep 17 00:00:00 2001 From: casperlamboo Date: Wed, 13 May 2015 12:12:15 +0200 Subject: [PATCH] Implemented new layer part structure --- gulpfile.js | 1 + library/clipper.js | 8 +-- models/cube.stl | Bin 0 -> 684 bytes slice_test.html | 16 ++++- src/path.js | 99 +++++++++++++---------------- src/paths.js | 151 +++++++++++++++++++++++++++++++++++++++++++++ src/slicer.js | 113 +++++++++++++++++---------------- 7 files changed, 273 insertions(+), 115 deletions(-) create mode 100644 models/cube.stl create mode 100644 src/paths.js diff --git a/gulpfile.js b/gulpfile.js index e9b67c5..84e4a3f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -10,6 +10,7 @@ var files = [ "src/utils.js", "src/box.js", "src/printer.js", + "src/paths.js", "src/path.js", "src/slicer.js" ]; diff --git a/library/clipper.js b/library/clipper.js index 5fb0652..7bc31a1 100755 --- a/library/clipper.js +++ b/library/clipper.js @@ -3100,7 +3100,7 @@ if (this.m_ExecuteLocked) return false; if (this.m_HasOpenPaths) - //ClipperLib.Error("Error: PolyTree struct is need for open path clipping."); + ClipperLib.Error("Error: PolyTree struct is need for open path clipping."); this.m_ExecuteLocked = true; ClipperLib.Clear(solution); this.m_SubjFillType = subjFillType; @@ -4884,8 +4884,8 @@ else ClipperLib.Clipper.Round = R2; // eg. browser.chrome || browser.firefox || browser.opera ClipperLib.Clipper.TopX = function (edge, currentY) { - //if (edge.Bot == edge.Curr) alert ("edge.Bot = edge.Curr"); - //if (edge.Bot == edge.Top) alert ("edge.Bot = edge.Top"); + //if (edge.Bot == edge.Curr) console.log ("edge.Bot = edge.Curr"); + //if (edge.Bot == edge.Top) console.log ("edge.Bot = edge.Top"); if (currentY == edge.Top.Y) return edge.Top.X; return edge.Bot.X + ClipperLib.Clipper.Round(edge.Dx * (currentY - edge.Bot.Y)); @@ -6596,7 +6596,7 @@ } catch (err) { - alert(err.message); + console.log(err.message); } }; // --------------------------------- diff --git a/models/cube.stl b/models/cube.stl new file mode 100644 index 0000000000000000000000000000000000000000..660d4cd345a26dfcafbb09c453b684018683f266 GIT binary patch literal 684 zcmb7>I}XAy5JcV4a0r)BfDl5Wj6vceC_xlJq5x9LoPe6sfT`&@11F%yV|!#Lq+uJ6 zHv9H7Sye?|p0ZSK%6u=EyX=r=cqW`D&^)`!s`wq`a+r;Vq3qJ?~f_k6YPsztZ|dMqeUQRuT_x? zUb`8n;PnlEOcjDObO)i34_>vk+e(ODu}z+r*Dd&N`|97V=v73hW))_TrpD_64!|n} V{h_0DI^2OOOX%pY8I2%K{RNV?g8%>k literal 0 HcmV?d00001 diff --git a/slice_test.html b/slice_test.html index 3b09b8f..8a58699 100644 --- a/slice_test.html +++ b/slice_test.html @@ -11,6 +11,7 @@ + @@ -69,7 +70,7 @@ var printerConfig = { var printer = new D3D.Printer(printerConfig); var localIp = location.hash.substring(1); -var doodleBox = new D3D.Box(localIp); +//var doodleBox = new D3D.Box(localIp); //var printer = doodleBox.printer; var scene = new THREE.Scene(); @@ -115,20 +116,29 @@ mesh.position.z = 100; //scene.add(mesh); var loader = new THREE.STLLoader(); -loader.load("models/cubes.stl", function (geometry) { +loader.load("models/cube.stl", function (geometry) { + var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1); + 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 is lifted a little bit... mesh.position.y = -0.6552429199218741; - + */ scene.add(mesh); var slicer = new D3D.Slicer().setMesh(mesh); + var canvas = document.getElementById("canvas"); + var context = canvas.getContext("2d"); + + var img = slicer.drawPaths(printer, 0, 1); + context.drawImage(img, 0, 0); + gcode = slicer.getGcode(printer); }); diff --git a/src/path.js b/src/path.js index f0fbb59..9781526 100644 --- a/src/path.js +++ b/src/path.js @@ -9,98 +9,93 @@ D3D.Path = function (path, closed) { "use strict"; - this.path = path || []; + 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"; - this.path = path; + 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"; - 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); - - return new D3D.Path(solution, this.closed); + return this.clip(path, ClipperLib.ClipType.ctUnion); }; D3D.Path.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.ctDifference, solution); - - return new D3D.Path(solution, this.closed); + return this.clip(path, ClipperLib.ClipType.ctDifference); }; D3D.Path.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.ctIntersection, solution); - - return new D3D.Path(solution, this.closed); + return this.clip(path, ClipperLib.ClipType.ctIntersection); }; D3D.Path.prototype.xor = function () { "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.ctXor); }; D3D.Path.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); + 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, this.closed); + return new D3D.Path(solution[0], this.closed); }; D3D.Path.prototype.scaleUp = function (factor) { "use strict"; - var path = ClipperLib.JS.ScaleUpPaths(this.path, factor); + ClipperLib.JS.ScaleUpPath(this, factor); return this; }; D3D.Path.prototype.scaleDown = function (factor) { "use strict"; - var path = ClipperLib.JS.ScaleDownPaths(this.path, factor); + var path = ClipperLib.JS.ScaleDownPath(this, factor); return this; }; D3D.Path.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 --; } } @@ -110,27 +105,19 @@ D3D.Path.prototype.tresholdArea = function (minArea) { D3D.Path.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) { "use strict"; - this.path = this.path.concat(path.path); + this.setPath(this.concat(path)); return this; } D3D.Path.prototype.clone = function () { "use strict"; - var path = ClipperLib.JS.Clone(this.path); + var path = ClipperLib.JS.Clone(this); return new D3D.Path(path, this.closed); } @@ -138,8 +125,8 @@ D3D.Path.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; diff --git a/src/paths.js b/src/paths.js new file mode 100644 index 0000000..9736c05 --- /dev/null +++ b/src/paths.js @@ -0,0 +1,151 @@ +/****************************************************** +* +* Path +* +* Abstraction layer for annoying clipper js +* +******************************************************/ + +D3D.Paths = function (paths) { + "use strict"; + + Array.call(this); + + this.setPaths(paths || []); + + this.closed = (this[0] !== undefined) ? this[0].closed : true; +}; +D3D.Paths.prototype = Object.create(Array.prototype); +D3D.Paths.prototype.setPaths = function (paths) { + "use strict"; + + 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); + } + + return this; +}; +D3D.Paths.prototype.clip = function (path, type) { + "use strict"; + + var solution = new ClipperLib.Paths(); + + 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.Execute(type, solution); + + return new D3D.Paths(solution); +}; +D3D.Paths.prototype.union = function (path) { + "use strict"; + + return this.clip(path, ClipperLib.ClipType.ctUnion); +}; +D3D.Paths.prototype.difference = function (path) { + "use strict"; + + return this.clip(path, ClipperLib.ClipType.ctDifference); +}; +D3D.Paths.prototype.intersect = function (path) { + "use strict"; + + return this.clip(path, ClipperLib.ClipType.ctIntersection); +}; +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, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon); + co.Execute(solution, offset); + + return new D3D.Paths(solution); +}; +D3D.Paths.prototype.scaleUp = function (factor) { + "use strict"; + + var path = ClipperLib.JS.ScaleUpPaths(this, factor); + + return this; +}; +D3D.Paths.prototype.scaleDown = function (factor) { + "use strict"; + + var path = ClipperLib.JS.ScaleDownPaths(this, factor); + + return this; +}; +D3D.Paths.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.Paths.prototype.area = function () { + "use strict"; + + return ClipperLib.Clipper.Area(this); +}; +D3D.Paths.prototype.join = function (path) { + "use strict"; + + for (var i = 0; i < path.length; i ++) { + this.push(path[i]); + } + + return this; +}; +D3D.Paths.prototype.clone = function () { + "use strict"; + + var paths = []; + + for (var i = 0; i < this.length; i ++) { + paths.push(this[i].clone()); + } + + return new D3D.Paths(paths); +}; +D3D.Paths.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/slicer.js b/src/slicer.js index fe8ccc9..bc91f4b 100644 --- a/src/slicer.js +++ b/src/slicer.js @@ -64,27 +64,24 @@ 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); - if (face.normal.y === 1 || face.normal.y === -1) { - this.lines[a].ignore ++; - this.lines[b].ignore ++; - this.lines[c].ignore ++; + this.lines[a].normals.push(normal); + this.lines[b].normals.push(normal); + this.lines[c].normals.push(normal); } } }; @@ -99,14 +96,12 @@ D3D.Slicer.prototype.slice = function (height, step) { var min = Math.ceil(Math.min(line.line.start.y, line.line.end.y) / step); var max = Math.floor(Math.max(line.line.start.y, line.line.end.y) / step); - if (line.ignore < 2) { - for (var layerIndex = min; layerIndex <= max; layerIndex ++) { - if (layerIndex >= 0) { - if (layersIntersections[layerIndex] === undefined) { - layersIntersections[layerIndex] = []; - } - layersIntersections[layerIndex].push(i); + for (var layerIndex = min; layerIndex <= max; layerIndex ++) { + if (layerIndex >= 0) { + if (layersIntersections[layerIndex] === undefined) { + layersIntersections[layerIndex] = []; } + layersIntersections[layerIndex].push(i); } } } @@ -130,12 +125,12 @@ 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]; if (done.indexOf(index) === -1) { - var shape = []; + var shape = new D3D.Path([], true); while (index !== -1) { var intersection = intersections[index]; @@ -198,8 +193,7 @@ D3D.Slicer.prototype.slice = function (height, step) { //stop when ther are no intersects if (slice.length > 0) { - slices.push(new D3D.Path(slice, true)); - //slices.push(slice); + slices.push(slice); } else { break; @@ -228,36 +222,50 @@ 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.Paths(); + var fills = new D3D.Paths(); + var outerLayers = new D3D.Paths(); - var insets = new D3D.Path(); - for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) { - var inset = outerLayer.offset(-offset); + 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 - insets.join(inset); - } + for (var i = 0; i < slice.length; i ++) { + var part = slice[i]; - var fillArea = (inset || outerLayer).offset(-wallThickness/2); + var outerLayer = part.clone(); + outerLayer.scaleUp(scale); - 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)); + for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) { + var inset = outerLayer.offset(-offset); - var lowFillArea = fillArea.difference(highFillArea); + insets.push(inset); + } + + var fillArea = (inset || outerLayer).offset(-wallThickness/2); + + var highFillArea = fillArea.difference(surroundingLayer); + + var lowFillArea = fillArea.difference(highFillArea); + + var fill = new D3D.Paths([]); + + fills.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)); - var highFillStrokes = highFillArea; - fill.join(highFillTemplate.intersect(highFillStrokes)); + fills.join(highFillTemplate.intersect(highFillArea)); + + console.log(highFillTemplate.intersect(highFillArea)); + + outerLayers.push(outerLayer); } data.push({ - outerLayer: outerLayer.scaleDown(scale), + outerLayer: outerLayers.scaleDown(scale), insets: insets.scaleDown(scale), - fill: fill.scaleDown(scale) + fill: fills.scaleDown(scale) }); } @@ -270,17 +278,17 @@ D3D.Slicer.prototype.getFillTemplate = function (dimension, size, even, uneven) if (even) { for (var length = 0; length <= dimension; length += size) { - paths.push([{X: length, Y: 0}, {X: length, Y: dimension}]); + paths.push(new D3D.Path([{X: length, Y: 0}, {X: length, Y: dimension}], false)); } } if (uneven) { for (var length = 0; length <= dimension; length += size) { - paths.push([{X: 0, Y: length}, {X: dimension, Y: length}]); + paths.push(new D3D.Path([{X: 0, Y: length}, {X: dimension, Y: length}], false)); } } //return paths; - return new D3D.Path(paths, false); + return new D3D.Paths(paths); }; D3D.Slicer.prototype.dataToGcode = function (data, printer) { "use strict"; @@ -302,8 +310,8 @@ 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; @@ -429,6 +437,7 @@ 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;