Path optimizer

This commit is contained in:
casperlamboo 2015-05-15 11:14:44 +02:00
parent 0bc518dcc9
commit 203fe6df19
5 changed files with 180 additions and 51 deletions

93
build/d3d.js vendored
View File

@ -644,7 +644,49 @@ D3D.Paths.prototype.scaleDown = function (factor) {
return this; return this;
}; };
D3D.Paths.prototype.optimizePath = function (start) {
"use strict";
var optimizedPaths = new D3D.Paths();
while (optimizedPaths.length !== this.length) {
var minLength = undefined;
var reverse;
var minPath;
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;
}
var length = endPoint.sub(start).length();
if (length < minLength) {
minPath = path;
minLength = length;
reverse = true;
}
}
}
if (reverse) {
minPath.reverse();
}
var point = minPath[minPath.length - 1];
start = new THREE.Vector2(point.X, point.Y);
optimizedPaths.push(minPath);
}
return optimizedPaths;
};
D3D.Paths.prototype.tresholdArea = function (minArea) { D3D.Paths.prototype.tresholdArea = function (minArea) {
//code not tested yet
"use strict"; "use strict";
for (var i = 0; i < this.length; i ++) { for (var i = 0; i < this.length; i ++) {
@ -660,11 +702,6 @@ D3D.Paths.prototype.tresholdArea = function (minArea) {
return areas; return areas;
}; };
D3D.Paths.prototype.area = function () {
"use strict";
return ClipperLib.Clipper.Area(this);
};
D3D.Paths.prototype.join = function (path) { D3D.Paths.prototype.join = function (path) {
"use strict"; "use strict";
@ -684,13 +721,6 @@ D3D.Paths.prototype.bounds = function () {
return ClipperLib.Clipper.GetBounds(this); 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) { D3D.Paths.prototype.draw = function (context, color) {
"use strict"; "use strict";
@ -698,6 +728,9 @@ D3D.Paths.prototype.draw = function (context, color) {
for (var i = 0; i < this.length; i ++) { for (var i = 0; i < this.length; i ++) {
var shape = this[i]; var shape = this[i];
//var point = shape[0];
//context.fillText(i, point.X*2, point.Y*2);
context.beginPath(); context.beginPath();
var length = this.closed ? (shape.length + 1) : shape.length; var length = this.closed ? (shape.length + 1) : shape.length;
for (var j = 0; j < length; j ++) { for (var j = 0; j < length; j ++) {
@ -947,7 +980,12 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var data = []; var data = [];
var lowFillTemplate = this.getFillTemplate(dimensionsZ, fillSize, true, true); var lowFillTemplate = this.getFillTemplate({
left: 0,
top: 0,
right: dimensionsZ,
bottom: dimensionsZ
}, fillSize, true, true);
for (var layer = 0; layer < slices.length; layer ++) { for (var layer = 0; layer < slices.length; layer ++) {
var slice = slices[layer]; var slice = slices[layer];
@ -955,14 +993,14 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var layerData = []; var layerData = [];
data.push(layerData); data.push(layerData);
var downSkin = new D3D.Paths(); var downSkin = new D3D.Paths([], true);
if (layer - skinCount >= 0) { if (layer - skinCount >= 0) {
var downLayer = slices[layer - skinCount]; var downLayer = slices[layer - skinCount];
for (var i = 0; i < downLayer.length; i ++) { for (var i = 0; i < downLayer.length; i ++) {
downSkin.join(downLayer[i]); downSkin.join(downLayer[i]);
} }
} }
var upSkin = new D3D.Paths(); var upSkin = new D3D.Paths([], true);
if (layer + skinCount < slices.length) { if (layer + skinCount < slices.length) {
var downLayer = slices[layer + skinCount]; var downLayer = slices[layer + skinCount];
for (var i = 0; i < downLayer.length; i ++) { for (var i = 0; i < downLayer.length; i ++) {
@ -978,7 +1016,7 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var outerLayer = part.clone(); var outerLayer = part.clone();
outerLayer.scaleUp(scale); outerLayer.scaleUp(scale);
var insets = new D3D.Paths(); var insets = new D3D.Paths([], true);
for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) { for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) {
var inset = outerLayer.offset(-offset); var inset = outerLayer.offset(-offset);
@ -991,12 +1029,19 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var lowFillArea = fillArea.difference(highFillArea); var lowFillArea = fillArea.difference(highFillArea);
var fill = new D3D.Paths([]); var fill = new D3D.Paths([], false);
fill.join(lowFillTemplate.intersect(lowFillArea)); fill.join(lowFillTemplate.intersect(lowFillArea));
var highFillTemplate = this.getFillTemplate(dimensionsZ, wallThickness, (layer % 2 === 0), (layer % 2 === 1)); if (highFillArea.length > 0) {
fill.join(highFillTemplate.intersect(highFillArea)); var highFillTemplate = this.getFillTemplate(highFillArea.bounds(), wallThickness, (layer % 2 === 0), (layer % 2 === 1));
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);
layerData.push({ layerData.push({
outerLayer: outerLayer.scaleDown(scale), outerLayer: outerLayer.scaleDown(scale),
@ -1008,19 +1053,19 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
return data; return data;
}; };
D3D.Slicer.prototype.getFillTemplate = function (dimension, size, even, uneven) { D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) {
"use strict"; "use strict";
var paths = new D3D.Paths([], false); var paths = new D3D.Paths([], false);
if (even) { if (even) {
for (var length = 0; length <= dimension; length += size) { for (var length = Math.floor(bounds.left); length <= Math.ceil(bounds.right); length += size) {
paths.push([{X: length, Y: 0}, {X: length, Y: dimension}]); paths.push([{X: length, Y: bounds.top}, {X: length, Y: bounds.bottom}]);
} }
} }
if (uneven) { if (uneven) {
for (var length = 0; length <= dimension; length += size) { for (var length = Math.floor(bounds.top); length <= Math.floor(bounds.bottom); length += size) {
paths.push([{X: 0, Y: length}, {X: dimension, Y: length}]); paths.push([{X: bounds.left, Y: length}, {X: bounds.right, Y: length}]);
} }
} }

2
build/d3d.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -106,7 +106,7 @@ var geometry = (function () {
})(); })();
var material = new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true}); var material = new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true});
//var geometry = new THREE.TorusGeometry(20, 10, 30, 30); var geometry = new THREE.TorusGeometry(20, 10, 30, 30);
var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1); var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1);
//var geometry = new THREE.SphereGeometry(10, 10, 10); //var geometry = new THREE.SphereGeometry(10, 10, 10);
var mesh = new THREE.Mesh(geometry, material); var mesh = new THREE.Mesh(geometry, material);
@ -117,8 +117,10 @@ mesh.position.z = 100;
var loader = new THREE.STLLoader(); var loader = new THREE.STLLoader();
loader.load("models/diamond.stl", function (geometry) { loader.load("models/diamond.stl", function (geometry) {
var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1); 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 = new THREE.TorusGeometry(20, 10, 30, 30);
var geometry = (function () { var geometry = (function () {
"use strict"; "use strict";
@ -143,6 +145,7 @@ loader.load("models/diamond.stl", function (geometry) {
return geometry; return geometry;
})(); })();
var mesh = new THREE.Mesh(geometry, material); var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = 100; mesh.position.x = 100;

View File

@ -82,7 +82,83 @@ D3D.Paths.prototype.scaleDown = function (factor) {
return this; 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([], this.closed);
var donePaths = [];
while (optimizedPaths.length !== this.length) {
var minLength = false;
var reverse;
var minPath;
var offset;
var pathIndex;
for (var i = 0; i < this.length; i ++) {
var path = this[i];
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;
}
}
}
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 (this.closed) {
minPath = minPath.concat(minPath.splice(0, offset));
var point = minPath[0];
}
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);
}
return optimizedPaths;
};
D3D.Paths.prototype.tresholdArea = function (minArea) { D3D.Paths.prototype.tresholdArea = function (minArea) {
//code not tested yet
"use strict"; "use strict";
for (var i = 0; i < this.length; i ++) { for (var i = 0; i < this.length; i ++) {
@ -98,11 +174,6 @@ D3D.Paths.prototype.tresholdArea = function (minArea) {
return areas; return areas;
}; };
D3D.Paths.prototype.area = function () {
"use strict";
return ClipperLib.Clipper.Area(this);
};
D3D.Paths.prototype.join = function (path) { D3D.Paths.prototype.join = function (path) {
"use strict"; "use strict";
@ -122,13 +193,6 @@ D3D.Paths.prototype.bounds = function () {
return ClipperLib.Clipper.GetBounds(this); 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) { D3D.Paths.prototype.draw = function (context, color) {
"use strict"; "use strict";
@ -136,6 +200,9 @@ D3D.Paths.prototype.draw = function (context, color) {
for (var i = 0; i < this.length; i ++) { for (var i = 0; i < this.length; i ++) {
var shape = this[i]; var shape = this[i];
var point = shape[0];
context.fillText(i, point.X*2, point.Y*2);
context.beginPath(); context.beginPath();
var length = this.closed ? (shape.length + 1) : shape.length; var length = this.closed ? (shape.length + 1) : shape.length;
for (var j = 0; j < length; j ++) { for (var j = 0; j < length; j ++) {

View File

@ -235,9 +235,16 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var brimOffset = printer.config["printer.brimOffset"] * scale; var brimOffset = printer.config["printer.brimOffset"] * scale;
var skinCount = Math.ceil(shellThickness/layerHeight); var skinCount = Math.ceil(shellThickness/layerHeight);
var start = new THREE.Vector2(0, 0);
var data = []; var data = [];
var lowFillTemplate = this.getFillTemplate(dimensionsZ, fillSize, true, true); var lowFillTemplate = this.getFillTemplate({
left: 0,
top: 0,
right: dimensionsZ,
bottom: dimensionsZ
}, fillSize, true, true);
for (var layer = 0; layer < slices.length; layer ++) { for (var layer = 0; layer < slices.length; layer ++) {
var slice = slices[layer]; var slice = slices[layer];
@ -245,14 +252,14 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var layerData = []; var layerData = [];
data.push(layerData); data.push(layerData);
var downSkin = new D3D.Paths(); var downSkin = new D3D.Paths([], true);
if (layer - skinCount >= 0) { if (layer - skinCount >= 0) {
var downLayer = slices[layer - skinCount]; var downLayer = slices[layer - skinCount];
for (var i = 0; i < downLayer.length; i ++) { for (var i = 0; i < downLayer.length; i ++) {
downSkin.join(downLayer[i]); downSkin.join(downLayer[i]);
} }
} }
var upSkin = new D3D.Paths(); var upSkin = new D3D.Paths([], true);
if (layer + skinCount < slices.length) { if (layer + skinCount < slices.length) {
var downLayer = slices[layer + skinCount]; var downLayer = slices[layer + skinCount];
for (var i = 0; i < downLayer.length; i ++) { for (var i = 0; i < downLayer.length; i ++) {
@ -268,7 +275,7 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var outerLayer = part.clone(); var outerLayer = part.clone();
outerLayer.scaleUp(scale); outerLayer.scaleUp(scale);
var insets = new D3D.Paths(); var insets = new D3D.Paths([], true);
for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) { for (var offset = wallThickness; offset <= shellThickness; offset += wallThickness) {
var inset = outerLayer.offset(-offset); var inset = outerLayer.offset(-offset);
@ -281,12 +288,19 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
var lowFillArea = fillArea.difference(highFillArea); var lowFillArea = fillArea.difference(highFillArea);
var fill = new D3D.Paths([]); var fill = new D3D.Paths([], false);
fill.join(lowFillTemplate.intersect(lowFillArea)); fill.join(lowFillTemplate.intersect(lowFillArea));
var highFillTemplate = this.getFillTemplate(dimensionsZ, wallThickness, (layer % 2 === 0), (layer % 2 === 1)); if (highFillArea.length > 0) {
fill.join(highFillTemplate.intersect(highFillArea)); var highFillTemplate = this.getFillTemplate(highFillArea.bounds(), wallThickness, (layer % 2 === 0), (layer % 2 === 1));
fill.join(highFillTemplate.intersect(highFillArea));
}
outerLayer = outerLayer.optimizePath(start);
insets = insets.optimizePath(outerLayer.lastPoint());
fill = fill.optimizePath(insets.lastPoint());
start = fill.lastPoint();
layerData.push({ layerData.push({
outerLayer: outerLayer.scaleDown(scale), outerLayer: outerLayer.scaleDown(scale),
@ -298,19 +312,19 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
return data; return data;
}; };
D3D.Slicer.prototype.getFillTemplate = function (dimension, size, even, uneven) { D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) {
"use strict"; "use strict";
var paths = new D3D.Paths([], false); var paths = new D3D.Paths([], false);
if (even) { if (even) {
for (var length = 0; length <= dimension; length += size) { for (var length = Math.floor(bounds.left); length <= Math.ceil(bounds.right); length += size) {
paths.push([{X: length, Y: 0}, {X: length, Y: dimension}]); paths.push([{X: length, Y: bounds.top}, {X: length, Y: bounds.bottom}]);
} }
} }
if (uneven) { if (uneven) {
for (var length = 0; length <= dimension; length += size) { for (var length = Math.floor(bounds.top); length <= Math.floor(bounds.bottom); length += size) {
paths.push([{X: 0, Y: length}, {X: dimension, Y: length}]); paths.push([{X: bounds.left, Y: length}, {X: bounds.right, Y: length}]);
} }
} }
@ -361,7 +375,7 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) {
gcode.push([ gcode.push([
"G0", "G0",
"X" + point.X.toFixed(3) + " Y" + point.Y.toFixed(3) + " Z" + z, "X" + point.X.toFixed(3) + " Y" + point.Y.toFixed(3) + " Z" + z,
"F" + (travelSpeed*60) "F" + (travelSpeed * 60)
].join(" ")); ].join(" "));
if (extruder > retractionMinDistance && retractionEnabled) { if (extruder > retractionMinDistance && retractionEnabled) {