improved slicing algoritm

This commit is contained in:
casperlamboo 2015-07-29 11:18:18 +02:00 committed by Simon Voordouw
parent a70cf6325a
commit 5c413267d0
2 changed files with 182 additions and 138 deletions

View File

@ -10,7 +10,9 @@ export default class Paths extends Array {
} }
setPaths (paths) { setPaths (paths) {
for (var path of paths) { for (var i = 0; i < paths.length; i ++) {
var path = paths[i];
if (path.length > 0) { if (path.length > 0) {
this.push(path); this.push(path);
} }
@ -75,6 +77,10 @@ export default class Paths extends Array {
} }
lastPoint () { lastPoint () {
if (this.length === 0) {
return new THREE.Vector2();
}
var lastPath = this[this.length - 1]; var lastPath = this[this.length - 1];
var lastPoint = this.closed ? lastPath[0] : lastPath[lastPath.length - 1]; var lastPoint = this.closed ? lastPath[0] : lastPath[lastPath.length - 1];
return new THREE.Vector2(lastPoint.X, lastPoint.Y); return new THREE.Vector2(lastPoint.X, lastPoint.Y);
@ -151,7 +157,8 @@ export default class Paths extends Array {
areas () { areas () {
var areas = []; var areas = [];
for (var shape of this) { for (var i = 0; i < this.length; i ++) {
var shape = this[i];
if (shape.closed) { if (shape.closed) {
var area = Math.abs(ClipperLib.Clipper.Area(shape)); var area = Math.abs(ClipperLib.Clipper.Area(shape));
areas.push(area); areas.push(area);
@ -165,7 +172,8 @@ export default class Paths extends Array {
var areas = this.areas(); var areas = this.areas();
var totalArea = 0; var totalArea = 0;
for (area of areas) { for (var i = 0; i < areas.length; i ++) {
var area = areas[i];
totalArea += area; totalArea += area;
} }
@ -174,7 +182,8 @@ export default class Paths extends Array {
tresholdArea (minArea) { tresholdArea (minArea) {
// code not tested yet // code not tested yet
for (var shape of this) { for (var i = 0; i < this.length; i ++) {
var shape = this[i];
var area = ClipperLib.Clipper.Area(shape); var area = ClipperLib.Clipper.Area(shape);
if (area < minArea) { if (area < minArea) {

View File

@ -7,7 +7,9 @@ export default class {
constructor () { constructor () {
this.progress = { this.progress = {
createdLines: false, createdLines: false,
calculatedLayerIntersections: false,
sliced: false, sliced: false,
generatedSlices: false,
generatedInnerLines: false, generatedInnerLines: false,
generatedInfills: false, generatedInfills: false,
generatedSupport: false, generatedSupport: false,
@ -52,10 +54,14 @@ export default class {
slice (settings) { slice (settings) {
var supportEnabled = settings.config['supportEnabled']; var supportEnabled = settings.config['supportEnabled'];
//get unique lines from geometry; // get unique lines from geometry;
var lines = this._createLines(settings); var lines = this._createLines(settings);
var slices = this._slice(lines, settings); var {layersIntersectionIndexes, layersIntersectionPoints} = this._calculateLayersIntersections(lines, settings);
var shapes = this._intersectionsToShapes(layersIntersectionIndexes, layersIntersectionPoints, lines, settings);
var slices = this._shapesToSlices(shapes, settings);
this._generateInnerLines(slices, settings); this._generateInnerLines(slices, settings);
@ -99,7 +105,8 @@ export default class {
return index; return index;
} }
for (var face of this.geometry.faces) { 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(face.normal.z, face.normal.x).normalize(); var normal = new THREE.Vector2(face.normal.z, face.normal.x).normalize();
@ -126,17 +133,19 @@ export default class {
return lines; return lines;
} }
_slice (lines, settings) { _calculateLayersIntersections (lines, settings) {
console.log("generating slices"); console.log('calculating layer intersections');
var layerHeight = settings.config["layerHeight"]; var layerHeight = settings.config["layerHeight"];
var height = settings.config["dimensionsZ"]; var height = settings.config["dimensionsZ"];
var numLayers = height / layerHeight; var numLayers = height / layerHeight;
var layersIntersections = []; var layersIntersectionIndexes = [];
var layersIntersectionPoints = [];
for (var layer = 0; layer < numLayers; layer ++) { for (var layer = 0; layer < numLayers; layer ++) {
layersIntersections[layer] = []; layersIntersectionIndexes[layer] = [];
layersIntersectionPoints[layer] = [];
} }
for (var lineIndex = 0; lineIndex < lines.length; lineIndex ++) { for (var lineIndex = 0; lineIndex < lines.length; lineIndex ++) {
@ -147,23 +156,10 @@ export default class {
for (var layerIndex = min; layerIndex <= max; layerIndex ++) { for (var layerIndex = min; layerIndex <= max; layerIndex ++) {
if (layerIndex >= 0 && layerIndex < numLayers) { if (layerIndex >= 0 && layerIndex < numLayers) {
layersIntersections[layerIndex].push(lineIndex);
}
}
}
var slices = []; layersIntersectionIndexes[layerIndex].push(lineIndex);
for (var layer = 1; layer < layersIntersections.length; layer ++) { var y = layerIndex * layerHeight;
var layerIntersections = layersIntersections[layer];
if (layerIntersections.length > 0) {
var y = layer * layerHeight;
var intersections = [];
for (var index of layerIntersections) {
var line = lines[index].line;
if (line.start.y === line.end.y) { if (line.start.y === line.end.y) {
var x = line.start.x; var x = line.start.x;
@ -174,49 +170,79 @@ export default class {
var x = line.end.x * alpha + line.start.x * (1 - alpha); var x = line.end.x * alpha + line.start.x * (1 - alpha);
var z = line.end.z * alpha + line.start.z * (1 - alpha); var z = line.end.z * alpha + line.start.z * (1 - alpha);
} }
intersections[index] = new THREE.Vector2(z, x);
layersIntersectionPoints[layerIndex][lineIndex] = new THREE.Vector2(z, x);
}
}
}
this.progress.calculatedLayerIntersections = true;
this._updateProgress(settings);
return {
layersIntersectionIndexes,
layersIntersectionPoints
};
}
_intersectionsToShapes (layersIntersectionIndexes, layersIntersectionPoints, lines, settings) {
console.log("generating slices");
var layerHeight = settings.config["layerHeight"];
var shapes = [];
for (var layer = 1; layer < layersIntersectionIndexes.length; layer ++) {
var layerIntersectionIndexes = layersIntersectionIndexes[layer];
var layerIntersectionPoints = layersIntersectionPoints[layer];
if (layerIntersectionIndexes.length === 0) {
continue;
}
var shapeParts = [];
for (var i = 0; i < layerIntersectionIndexes.length; i ++) {
var index = layerIntersectionIndexes[i];
if (layerIntersectionPoints[index] === undefined) {
continue;
} }
var done = [];
var sliceParts = [];
for (var index of layerIntersections) {
var firstPoint = index; var firstPoint = index;
var closed = false; var closed = false;
if (done.indexOf(index) === -1) {
var shape = []; var shape = [];
while (index !== -1) { while (index !== -1) {
done.push(index); var intersection = layerIntersectionPoints[index];
var intersection = intersections[index];
//uppercase X and Y because clipper vector //uppercase X and Y because clipper vector
shape.push({X: intersection.x, Y: intersection.y}); shape.push({X: intersection.x, Y: intersection.y});
var connects = lines[index].connects.map((value) => value); delete layerIntersectionPoints[index];
var faceNormals = lines[index].normals.map((value) => value);
for (var i = 0; i < connects.length; i ++) { var connects = lines[index].connects;
var index = connects[i]; var faceNormals = lines[index].normals;
if (shape.length > 2 && index === firstPoint) { for (var j = 0; j < connects.length; j ++) {
var index = connects[j];
if (index === firstPoint && shape.length > 2) {
closed = true; closed = true;
index = -1;
break; break;
} }
//check if index is already used // Check if index has an intersection or is already used
if (done.indexOf(index) === -1) { if (layerIntersectionPoints[index] !== undefined) {
//check if index has an intersection var faceNormal = faceNormals[Math.floor(j / 2)];
if (intersections[index] !== undefined) {
var faceNormal = faceNormals[Math.floor(i / 2)];
var a = new THREE.Vector2(intersection.x, intersection.y); var a = new THREE.Vector2(intersection.x, intersection.y);
var b = new THREE.Vector2(intersections[index].x, intersections[index].y); var b = new THREE.Vector2(layerIntersectionPoints[index].x, layerIntersectionPoints[index].y);
if (a.distanceTo(b) < 0.0001 || (faceNormal.x === 0 && faceNormal.y === 0)) { //threejs can't calculate normal if distance is smaller as 0.0001
done.push(index); if ((faceNormal.x === 0 && faceNormal.y === 0) || a.distanceTo(b) < 0.0001) {
delete layerIntersectionPoints[index];
connects = connects.concat(lines[index].connects); connects = connects.concat(lines[index].connects);
faceNormals = faceNormals.concat(lines[index].normals); faceNormals = faceNormals.concat(lines[index].normals);
@ -236,11 +262,6 @@ export default class {
} }
} }
} }
else {
done.push(index);
index = -1;
}
}
else { else {
index = -1; index = -1;
} }
@ -252,72 +273,86 @@ export default class {
while (index !== -1) { while (index !== -1) {
if (index !== firstPoint) { if (index !== firstPoint) {
done.push(index); var intersection = layerIntersectionPoints[index];
var intersection = intersections[index];
// PERFORMACE // PERFORMACE
// maybe performance can be increased by unshifting to sepperate // maybe performance can be increased by unshifting to sepperate
// array and to later concat the original en the new array // array and to later concat the original en the new array
shape.unshift({X: intersection.x, Y: intersection.y}); shape.unshift({X: intersection.x, Y: intersection.y});
delete layerIntersectionPoints[index];
} }
var connects = lines[index].connects; var connects = lines[index].connects;
for (var index of connects) { for (var i = 0; i < connects.length; i ++) {
if (done.indexOf(index) === -1) { var index = connects[i];
if (intersections[index] !== undefined) {
if (layerIntersectionPoints[index] !== undefined) {
break; break;
} }
else { else {
done.push(index); delete layerIntersectionPoints[index];
index = -1;
}
}
else {
index = -1; index = -1;
} }
} }
} }
} }
// don't think this check is nessecary
if (shape.length > 0) { if (shape.length > 0) {
var part = new Paths([shape], closed).clean(0.01); var part = new Paths([shape], closed).clean(0.01);
sliceParts.push(part); shapeParts.push(part);
}
} }
} }
sliceParts.sort((a, b) => { shapes.push(shapeParts);
return b.boundSize() - a.boundSize(); }
this.progress.sliced = true;
this._updateProgress(settings);
return shapes;
}
_shapesToSlices (shapes, settings) {
var slices = [];
for (var layer = 0; layer < shapes.length; layer ++) {
var shapeParts = shapes[layer];
shapeParts.sort((a, b) => {
return a.boundSize() - b.boundSize();
}); });
var slice = new Slice(); var slice = new Slice();
for (var slicePart1 of sliceParts) { for (var i = 0; i < shapeParts.length; i ++) {
if (slicePart1.closed) { var shapePart1 = shapeParts[i];
if (shapePart1.closed) {
var merge = false; var merge = false;
for (var slicePart2 of slice.parts) { for (var j = 0; j < slice.parts.length; j ++) {
if (slicePart2.closed && slicePart2.intersect(slicePart1).length > 0) { var shapePart2 = slice.parts[j].intersect;
slicePart2.join(slicePart1); if (shapePart2.closed && shapePart2.intersect(shapePart1).length > 0) {
shapePart2.join(shapePart1);
merge = true; merge = true;
break; break;
} }
} }
if (!merge) { if (!merge) {
slice.add(slicePart1); slice.add(shapePart1);
} }
} }
else { else {
slice.add(slicePart1); slice.add(shapePart1);
} }
} }
slices.push(slice); slices.push(slice);
} }
}
this.progress.sliced = true; this.progress.generatedSlices = true;
this._updateProgress(settings); this._updateProgress(settings);
return slices; return slices;