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

View File

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