2015-04-24 16:12:48 +02:00
|
|
|
/******************************************************
|
|
|
|
*
|
|
|
|
* Slicer
|
|
|
|
*
|
|
|
|
******************************************************/
|
|
|
|
|
2015-04-28 14:11:41 +02:00
|
|
|
D3D.Slicer = function () {
|
2015-04-24 16:12:48 +02:00
|
|
|
"use strict";
|
2015-05-29 13:51:18 +02:00
|
|
|
|
|
|
|
this.progress = {
|
2015-06-05 09:56:58 +02:00
|
|
|
totalFaces: 0,
|
|
|
|
currentFace: 0,
|
2015-05-29 13:51:18 +02:00
|
|
|
totalLayers: 0,
|
|
|
|
sliceLayer: 0,
|
|
|
|
dataLayer: 0,
|
|
|
|
gcodeLayer: 0
|
|
|
|
};
|
2015-04-24 16:12:48 +02:00
|
|
|
};
|
2015-05-27 12:25:51 +02:00
|
|
|
D3D.Slicer.prototype.setMesh = function (geometry, matrix) {
|
2015-04-28 14:11:41 +02:00
|
|
|
"use strict";
|
|
|
|
|
2015-05-15 15:07:47 +02:00
|
|
|
//convert buffergeometry to geometry;
|
2015-05-29 13:51:18 +02:00
|
|
|
if (geometry instanceof THREE.BufferGeometry) {
|
|
|
|
geometry = new THREE.Geometry().fromBufferGeometry(geometry);
|
|
|
|
}
|
2015-05-15 15:07:47 +02:00
|
|
|
|
2015-06-09 11:08:06 +02:00
|
|
|
//apply mesh matrix on geometry;
|
|
|
|
geometry.applyMatrix(matrix);
|
|
|
|
geometry.mergeVertices();
|
|
|
|
geometry.computeFaceNormals();
|
|
|
|
geometry.computeBoundingBox();
|
|
|
|
|
2015-05-29 10:41:44 +02:00
|
|
|
/*
|
2015-06-09 11:08:06 +02:00
|
|
|
for (var i = 0; i < geometry.faces.length; i ++) {
|
|
|
|
var face = geometry.faces[i];
|
|
|
|
var normal = face.normal;
|
2015-05-15 15:07:47 +02:00
|
|
|
|
2015-06-09 11:08:06 +02:00
|
|
|
if (normal.x === 0 && normal.y === 0 && normal.z === 0) {
|
|
|
|
geometry.faces.splice(i, 1);
|
|
|
|
i --;
|
2015-05-15 15:07:47 +02:00
|
|
|
}
|
|
|
|
}
|
2015-05-29 10:41:44 +02:00
|
|
|
*/
|
2015-06-05 09:56:58 +02:00
|
|
|
|
2015-05-08 10:07:26 +02:00
|
|
|
this.geometry = geometry;
|
2015-04-28 14:11:41 +02:00
|
|
|
|
2015-05-15 15:07:47 +02:00
|
|
|
//get unique lines from geometry;
|
2015-04-28 14:11:41 +02:00
|
|
|
this.createLines();
|
|
|
|
|
|
|
|
return this;
|
|
|
|
};
|
2015-05-29 13:51:18 +02:00
|
|
|
D3D.Slicer.prototype.updateProgress = function () {
|
2015-06-05 09:56:58 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var faces = this.progress.currentFace / (this.progress.totalFaces - 1);
|
|
|
|
var slice = this.progress.sliceLayer / (this.progress.totalLayers - 1);
|
|
|
|
var data = this.progress.dataLayer / (this.progress.totalLayers - 2);
|
|
|
|
var gcode = this.progress.gcodeLayer / (this.progress.totalLayers - 2);
|
|
|
|
|
|
|
|
this.progress.procent = (faces + slice + data + gcode) / 4;
|
|
|
|
|
2015-05-29 13:51:18 +02:00
|
|
|
if (this.onProgress !== undefined) {
|
2015-06-05 09:56:58 +02:00
|
|
|
|
2015-05-29 13:51:18 +02:00
|
|
|
this.onProgress(this.progress);
|
|
|
|
}
|
|
|
|
};
|
2015-05-01 16:44:05 +02:00
|
|
|
D3D.Slicer.prototype.createLines = function () {
|
2015-05-01 14:09:45 +02:00
|
|
|
"use strict";
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-06-05 09:56:58 +02:00
|
|
|
this.progress.totalFaces = this.geometry.faces.length;
|
|
|
|
|
2015-05-01 16:44:05 +02:00
|
|
|
this.lines = [];
|
|
|
|
var lineLookup = {};
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-05-01 16:44:05 +02:00
|
|
|
var self = this;
|
|
|
|
function addLine (a, b) {
|
2015-06-09 11:08:06 +02:00
|
|
|
var index = lineLookup[b + "_" + a];
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-05-01 16:44:05 +02:00
|
|
|
if (index === undefined) {
|
|
|
|
index = self.lines.length;
|
|
|
|
lineLookup[a + "_" + b] = index;
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-05-01 16:44:05 +02:00
|
|
|
self.lines.push({
|
2015-05-07 14:09:36 +02:00
|
|
|
line: new THREE.Line3(self.geometry.vertices[a], self.geometry.vertices[b]),
|
|
|
|
connects: [],
|
2015-05-29 13:51:18 +02:00
|
|
|
normals: []
|
2015-05-01 16:44:05 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return index;
|
2015-05-07 11:04:48 +02:00
|
|
|
}
|
2015-04-24 16:12:48 +02:00
|
|
|
|
|
|
|
for (var i = 0; i < this.geometry.faces.length; i ++) {
|
|
|
|
var face = this.geometry.faces[i];
|
2015-05-13 12:12:15 +02:00
|
|
|
|
2015-05-17 19:58:44 +02:00
|
|
|
if (face.normal.y !== 1 && face.normal.y !== -1) {
|
|
|
|
var normal = new THREE.Vector2().set(face.normal.z, face.normal.x).normalize();
|
2015-05-13 12:12:15 +02:00
|
|
|
|
|
|
|
//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);
|
|
|
|
|
|
|
|
//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);
|
2015-05-17 19:58:44 +02:00
|
|
|
}
|
2015-06-05 09:56:58 +02:00
|
|
|
|
|
|
|
this.progress.currentFace = i;
|
|
|
|
this.updateProgress();
|
2015-04-24 16:12:48 +02:00
|
|
|
}
|
|
|
|
};
|
2015-05-20 19:10:18 +02:00
|
|
|
D3D.Slicer.prototype.slice = function (layerHeight, height) {
|
2015-04-24 16:12:48 +02:00
|
|
|
"use strict";
|
2015-06-09 11:08:06 +02:00
|
|
|
var numLayers = height / layerHeight;
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-05-07 17:27:41 +02:00
|
|
|
var layersIntersections = [];
|
|
|
|
|
2015-05-20 19:10:18 +02:00
|
|
|
for (var lineIndex = 0; lineIndex < this.lines.length; lineIndex ++) {
|
2015-05-26 11:44:15 +02:00
|
|
|
var line = this.lines[lineIndex].line;
|
2015-05-07 17:27:41 +02:00
|
|
|
|
2015-05-26 11:44:15 +02:00
|
|
|
var min = Math.ceil(Math.min(line.start.y, line.end.y) / layerHeight);
|
|
|
|
var max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight);
|
2015-05-07 17:27:41 +02:00
|
|
|
|
2015-05-13 12:12:15 +02:00
|
|
|
for (var layerIndex = min; layerIndex <= max; layerIndex ++) {
|
2015-06-09 11:08:06 +02:00
|
|
|
if (layerIndex >= 0 && layerIndex < numLayers) {
|
2015-05-13 12:12:15 +02:00
|
|
|
if (layersIntersections[layerIndex] === undefined) {
|
|
|
|
layersIntersections[layerIndex] = [];
|
2015-05-07 17:27:41 +02:00
|
|
|
}
|
2015-05-20 19:10:18 +02:00
|
|
|
layersIntersections[layerIndex].push(lineIndex);
|
2015-05-07 17:27:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-24 16:12:48 +02:00
|
|
|
var slices = [];
|
|
|
|
|
2015-05-17 23:22:27 +02:00
|
|
|
//still error in first layer, so remove first layer & last layer
|
|
|
|
//see https://github.com/Doodle3D/Doodle3D-Slicer/issues/1
|
2015-06-01 12:06:11 +02:00
|
|
|
for (var layer = 0; layer < layersIntersections.length; layer ++) {
|
2015-05-07 17:27:41 +02:00
|
|
|
var layerIntersections = layersIntersections[layer];
|
2015-05-29 10:41:44 +02:00
|
|
|
var y = layer * layerHeight;
|
2015-04-24 16:12:48 +02:00
|
|
|
|
|
|
|
var intersections = [];
|
2015-06-09 11:08:06 +02:00
|
|
|
var log = [];
|
2015-05-07 17:27:41 +02:00
|
|
|
for (var i = 0; i < layerIntersections.length; i ++) {
|
|
|
|
var index = layerIntersections[i];
|
|
|
|
var line = this.lines[index].line;
|
2015-05-08 10:07:26 +02:00
|
|
|
|
2015-06-05 09:56:58 +02:00
|
|
|
if (line.start.y === line.end.y) {
|
|
|
|
var x = line.start.x;
|
|
|
|
var z = line.start.z;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var alpha = (y - line.start.y) / (line.end.y - line.start.y);
|
|
|
|
var x = line.end.x * alpha + line.start.x * (1 - alpha);
|
|
|
|
var z = line.end.z * alpha + line.start.z * (1 - alpha);
|
|
|
|
}
|
2015-06-09 11:08:06 +02:00
|
|
|
|
2015-05-17 19:58:44 +02:00
|
|
|
intersections[index] = new THREE.Vector2(z, x);
|
2015-06-09 11:08:06 +02:00
|
|
|
log.push({x: z, y: x, index: index, connects: this.lines[index].connects});
|
2015-04-24 16:12:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var done = [];
|
2015-05-17 19:58:44 +02:00
|
|
|
var slice = [];
|
2015-05-07 17:27:41 +02:00
|
|
|
for (var i = 0; i < layerIntersections.length; i ++) {
|
|
|
|
var index = layerIntersections[i];
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-05-07 17:27:41 +02:00
|
|
|
if (done.indexOf(index) === -1) {
|
2015-05-13 17:37:52 +02:00
|
|
|
var shape = [];
|
2015-04-24 16:12:48 +02:00
|
|
|
|
|
|
|
while (index !== -1) {
|
|
|
|
var intersection = intersections[index];
|
2015-04-30 18:26:34 +02:00
|
|
|
shape.push({X: intersection.x, Y: intersection.y});
|
2015-04-24 16:12:48 +02:00
|
|
|
|
|
|
|
var connects = this.lines[index].connects;
|
2015-04-28 17:54:46 +02:00
|
|
|
var faceNormals = this.lines[index].normals;
|
2015-04-24 16:12:48 +02:00
|
|
|
for (var j = 0; j < connects.length; j ++) {
|
|
|
|
index = connects[j];
|
|
|
|
|
2015-06-09 11:08:06 +02:00
|
|
|
if (intersections[index] !== undefined && done.indexOf(index) === -1) {
|
|
|
|
done.push(index);
|
|
|
|
|
2015-05-19 17:15:59 +02:00
|
|
|
var a = new THREE.Vector2(intersection.x, intersection.y);
|
2015-04-30 20:34:57 +02:00
|
|
|
var b = intersections[index];
|
2015-04-28 17:54:46 +02:00
|
|
|
|
2015-06-09 11:08:06 +02:00
|
|
|
if (a.distanceTo(b) === 0) {
|
|
|
|
connects = connects.concat(this.lines[index].connects);
|
|
|
|
faceNormals = faceNormals.concat(this.lines[index].normals);
|
|
|
|
index = -1;
|
2015-06-05 09:56:58 +02:00
|
|
|
}
|
|
|
|
else {
|
2015-06-09 11:08:06 +02:00
|
|
|
var normal = a.sub(b).normal().normalize();
|
|
|
|
var faceNormal = faceNormals[Math.floor(j/2)];
|
|
|
|
|
|
|
|
if (normal.dot(faceNormal) >= 0) {
|
|
|
|
//if (true) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
index = -1;
|
|
|
|
}
|
2015-06-05 09:56:58 +02:00
|
|
|
}
|
2015-04-24 16:12:48 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
index = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-08 14:29:06 +02:00
|
|
|
/*
|
|
|
|
for (var i = 0; i < shape.length; i ++) {
|
|
|
|
var point = shape[i];
|
|
|
|
var previousPoint = shape[(i + shape.length - 1) % shape.length];
|
|
|
|
var nextPoint = shape[(i + 1) % shape.length];
|
|
|
|
|
|
|
|
var point = new THREE.Vector2(point.X, point.Y);
|
|
|
|
var previousPoint = new THREE.Vector2(previousPoint.X, previousPoint.Y);
|
|
|
|
var nextPoint = new THREE.Vector2(nextPoint.X, nextPoint.Y);
|
|
|
|
//var lineLength = nextPoint.sub(previousPoint).length();
|
|
|
|
|
|
|
|
var normal = nextPoint.sub(previousPoint).normal().normalize();
|
|
|
|
var distance = Math.abs(normal.dot(point.sub(previousPoint)));
|
|
|
|
|
|
|
|
//something better for offset check
|
|
|
|
if (distance <= 0.01) {
|
|
|
|
shape.splice(i, 1);
|
|
|
|
i --;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2015-04-24 16:12:48 +02:00
|
|
|
//think this check is not nescesary, always higher as 0
|
|
|
|
if (shape.length > 0) {
|
2015-05-13 17:37:52 +02:00
|
|
|
slice.push(new D3D.Paths([shape]));
|
2015-04-24 16:12:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-28 14:11:41 +02:00
|
|
|
|
2015-06-09 11:08:06 +02:00
|
|
|
|
2015-05-13 17:37:52 +02:00
|
|
|
var layerParts = [];
|
|
|
|
|
|
|
|
for (var i = 0; i < slice.length; i ++) {
|
|
|
|
var layerPart1 = slice[i];
|
|
|
|
var merge = false;
|
2015-05-13 13:18:37 +02:00
|
|
|
|
2015-05-13 17:37:52 +02:00
|
|
|
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);
|
2015-04-28 14:11:41 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
break;
|
|
|
|
}
|
2015-05-29 13:51:18 +02:00
|
|
|
|
|
|
|
this.progress.sliceLayer = layer;
|
|
|
|
this.updateProgress();
|
2015-04-24 16:12:48 +02:00
|
|
|
}
|
|
|
|
return slices;
|
|
|
|
};
|
2015-05-01 10:06:52 +02:00
|
|
|
D3D.Slicer.prototype.slicesToData = function (slices, printer) {
|
2015-04-30 20:34:57 +02:00
|
|
|
"use strict";
|
|
|
|
|
2015-04-30 18:26:34 +02:00
|
|
|
var scale = 100;
|
|
|
|
|
2015-05-01 10:06:52 +02:00
|
|
|
var layerHeight = printer.config["printer.layerHeight"] * scale;
|
|
|
|
var dimensionsZ = printer.config["printer.dimensions.z"] * scale;
|
2015-05-20 19:10:18 +02:00
|
|
|
var nozzleDiameter = printer.config["printer.nozzleDiameter"] * scale;
|
2015-05-01 11:03:07 +02:00
|
|
|
var shellThickness = printer.config["printer.shellThickness"] * scale;
|
|
|
|
var fillSize = printer.config["printer.fillSize"] * scale;
|
|
|
|
var brimOffset = printer.config["printer.brimOffset"] * scale;
|
2015-05-18 13:53:49 +02:00
|
|
|
var bottomThickness = printer.config["printer.bottomThickness"] * scale;
|
|
|
|
var topThickness = printer.config["printer.topThickness"] * scale;
|
2015-06-09 21:58:22 +02:00
|
|
|
var useSupport = printer.config["printer.support.use"];
|
|
|
|
var supportSize = printer.config["printer.support.size"] * scale;
|
|
|
|
var supportMinArea = printer.config["printer.support.minArea"] * Math.pow(scale, 2);
|
|
|
|
var supportMargin = printer.config["printer.support.margin"] * scale;
|
|
|
|
var supportOffset = printer.config["printer.support.offset"] * scale;
|
2015-05-19 17:15:59 +02:00
|
|
|
|
2015-05-18 13:53:49 +02:00
|
|
|
var bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
|
|
|
|
var topSkinCount = Math.ceil(topThickness/layerHeight);
|
2015-05-20 19:10:18 +02:00
|
|
|
var nozzleRadius = nozzleDiameter / 2;
|
2015-05-01 11:03:07 +02:00
|
|
|
|
2015-05-15 11:14:44 +02:00
|
|
|
var lowFillTemplate = this.getFillTemplate({
|
2015-05-17 23:22:27 +02:00
|
|
|
left: this.geometry.boundingBox.min.z * scale,
|
|
|
|
top: this.geometry.boundingBox.min.x * scale,
|
|
|
|
right: this.geometry.boundingBox.max.z * scale,
|
|
|
|
bottom: this.geometry.boundingBox.max.x * scale
|
2015-05-15 11:14:44 +02:00
|
|
|
}, fillSize, true, true);
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
var data = [];
|
|
|
|
|
|
|
|
//generate outerLayer and insets
|
2015-04-24 16:12:48 +02:00
|
|
|
for (var layer = 0; layer < slices.length; layer ++) {
|
|
|
|
var slice = slices[layer];
|
2015-06-09 21:58:22 +02:00
|
|
|
|
2015-05-13 17:37:52 +02:00
|
|
|
var layerData = [];
|
|
|
|
data.push(layerData);
|
2015-06-09 21:58:22 +02:00
|
|
|
|
|
|
|
for (var i = 0; i < slice.length; i ++) {
|
|
|
|
var part = slice[i];
|
|
|
|
|
|
|
|
var outerLayer = part.clone().scaleUp(scale).offset(-nozzleRadius);
|
|
|
|
|
|
|
|
var insets = new D3D.Paths([], true);
|
|
|
|
if (outerLayer.length > 0) {
|
|
|
|
for (var offset = nozzleDiameter; offset <= shellThickness; offset += nozzleDiameter) {
|
|
|
|
var inset = outerLayer.offset(-offset);
|
|
|
|
|
|
|
|
insets.join(inset);
|
|
|
|
}
|
|
|
|
|
|
|
|
layerData.push({
|
|
|
|
outerLayer: outerLayer,
|
|
|
|
insets: insets
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//generate infills
|
|
|
|
for (var layer = 0; layer < data.length; layer ++) {
|
|
|
|
var slice = data[layer];
|
2015-05-13 17:37:52 +02:00
|
|
|
|
2015-05-15 11:14:44 +02:00
|
|
|
var downSkin = new D3D.Paths([], true);
|
2015-05-18 13:53:49 +02:00
|
|
|
if (layer - bottomSkinCount >= 0) {
|
2015-06-09 21:58:22 +02:00
|
|
|
var downLayer = data[layer - bottomSkinCount];
|
2015-05-13 17:37:52 +02:00
|
|
|
for (var i = 0; i < downLayer.length; i ++) {
|
2015-06-09 21:58:22 +02:00
|
|
|
downSkin.join(downLayer[i].outerLayer);
|
2015-05-13 17:37:52 +02:00
|
|
|
}
|
|
|
|
}
|
2015-05-15 11:14:44 +02:00
|
|
|
var upSkin = new D3D.Paths([], true);
|
2015-06-09 21:58:22 +02:00
|
|
|
if (layer + topSkinCount < data.length) {
|
|
|
|
var upLayer = data[layer + topSkinCount];
|
2015-05-26 11:44:15 +02:00
|
|
|
for (var i = 0; i < upLayer.length; i ++) {
|
2015-06-09 21:58:22 +02:00
|
|
|
upSkin.join(upLayer[i].outerLayer);
|
2015-05-13 17:37:52 +02:00
|
|
|
}
|
|
|
|
}
|
2015-06-09 21:58:22 +02:00
|
|
|
var surroundingLayer = upSkin.intersect(downSkin);
|
2015-05-13 17:37:52 +02:00
|
|
|
var sliceData = [];
|
2015-04-30 18:26:34 +02:00
|
|
|
|
2015-05-13 12:12:15 +02:00
|
|
|
for (var i = 0; i < slice.length; i ++) {
|
|
|
|
var part = slice[i];
|
2015-06-09 21:58:22 +02:00
|
|
|
var outerLayer = part.outerLayer;
|
|
|
|
var insets = part.insets;
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-05-18 13:53:49 +02:00
|
|
|
if (outerLayer.length > 0) {
|
2015-06-09 21:58:22 +02:00
|
|
|
var fillArea = ((insets.length > 0) ? insets : outerLayer).offset(-nozzleRadius);
|
2015-05-18 13:53:49 +02:00
|
|
|
var highFillArea = fillArea.difference(surroundingLayer);
|
|
|
|
var lowFillArea = fillArea.difference(highFillArea);
|
2015-04-30 20:34:57 +02:00
|
|
|
|
2015-05-18 13:53:49 +02:00
|
|
|
var fill = new D3D.Paths([], false);
|
2015-05-13 12:12:15 +02:00
|
|
|
|
2015-05-18 13:53:49 +02:00
|
|
|
if (lowFillTemplate.length > 0) {
|
|
|
|
fill.join(lowFillTemplate.intersect(lowFillArea));
|
|
|
|
}
|
2015-04-30 20:34:57 +02:00
|
|
|
|
2015-05-18 13:53:49 +02:00
|
|
|
if (highFillArea.length > 0) {
|
|
|
|
var bounds = highFillArea.bounds();
|
|
|
|
var even = (layer % 2 === 0);
|
2015-05-20 19:10:18 +02:00
|
|
|
var highFillTemplate = this.getFillTemplate(bounds, nozzleDiameter, even, !even);
|
2015-05-18 13:53:49 +02:00
|
|
|
fill.join(highFillTemplate.intersect(highFillArea));
|
|
|
|
}
|
2015-05-20 19:10:18 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
part.fill = fill;
|
2015-05-15 17:35:18 +02:00
|
|
|
}
|
2015-04-30 20:34:57 +02:00
|
|
|
}
|
2015-05-29 13:51:18 +02:00
|
|
|
|
|
|
|
this.progress.dataLayer = layer;
|
|
|
|
this.updateProgress();
|
2015-04-30 18:26:34 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
//generate support
|
|
|
|
if (useSupport) {
|
|
|
|
var supportTemplate = this.getFillTemplate({
|
|
|
|
left: this.geometry.boundingBox.min.z * scale,
|
|
|
|
top: this.geometry.boundingBox.min.x * scale,
|
|
|
|
right: this.geometry.boundingBox.max.z * scale,
|
|
|
|
bottom: this.geometry.boundingBox.max.x * scale
|
|
|
|
}, supportSize, true, true);
|
2015-05-12 11:29:01 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
var supportAreas = new D3D.Paths([], true);
|
2015-05-12 11:29:01 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
for (var layer = data.length - 1; layer >= 0; layer --) {
|
|
|
|
var slice = data[layer];
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
if (supportAreas.length > 0) {
|
|
|
|
var currentSkin = new D3D.Paths([], true);
|
|
|
|
for (var i = 0; i < slice.length; i ++) {
|
|
|
|
currentSkin.join(slice[i].outerLayer);
|
|
|
|
}
|
|
|
|
currentSkin = currentSkin.offset(supportMargin);
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
supportAreas = supportAreas.difference(currentSkin);
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
slice[0].support = supportTemplate.intersect(supportAreas);
|
|
|
|
}
|
2015-05-13 17:37:52 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
if (layer !== 0) {
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
var supportSkin = new D3D.Paths([], true);
|
|
|
|
if (layer - 1 >= 0) {
|
|
|
|
var supportLayer = data[layer - 1];
|
|
|
|
for (var i = 0; i < supportLayer.length; i ++) {
|
|
|
|
supportSkin.join(supportLayer[i].outerLayer);
|
2015-04-24 16:12:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
for (var i = 0; i < slice.length; i ++) {
|
|
|
|
var slicePart = slice[i];
|
|
|
|
var outerLayer = slicePart.outerLayer;
|
2015-04-30 18:26:34 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
var overlap = supportSkin.intersect(outerLayer);
|
|
|
|
var overhang = outerLayer.difference(overlap);
|
2015-05-26 11:44:15 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
if (overlap.length === 0) {
|
|
|
|
var supportArea = overhang.offset(supportOffset);
|
|
|
|
supportAreas = supportAreas.union(supportArea);
|
|
|
|
}
|
|
|
|
else if (overhang.length > 0) {
|
|
|
|
var areas = overhang.areas();
|
|
|
|
|
|
|
|
for (var j = 0; j < areas.length; j ++) {
|
|
|
|
var area = areas[i];
|
2015-04-30 18:26:34 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
if (area > supportMinArea) {
|
|
|
|
var supportArea = new D3D.Paths([overhang[i]], false).offset(supportOffset);
|
|
|
|
supportAreas = supportAreas.union(supportArea);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-30 18:26:34 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
//finalize paths
|
|
|
|
var start = new THREE.Vector2(0, 0);
|
|
|
|
var order = ["outerLayer", "insets", "fill", "support"];
|
2015-04-30 18:26:34 +02:00
|
|
|
|
|
|
|
for (var layer = 0; layer < data.length; layer ++) {
|
|
|
|
var slice = data[layer];
|
|
|
|
|
2015-05-13 17:37:52 +02:00
|
|
|
for (var i = 0; i < slice.length; i ++) {
|
2015-06-09 21:58:22 +02:00
|
|
|
var part = slice[i];
|
2015-05-13 17:37:52 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
for (var j = 0; j < order.length; j ++) {
|
|
|
|
var property = order[j];
|
|
|
|
if (part[property] !== undefined && part[property].length > 0) {
|
|
|
|
part[property] = part[property].optimizePath(start);
|
|
|
|
start = part[property].lastPoint();
|
|
|
|
}
|
|
|
|
}
|
2015-05-29 13:51:18 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
part.outerLayer.scaleDown(100);
|
|
|
|
part.insets.scaleDown(100);
|
|
|
|
part.fill.scaleDown(100);
|
|
|
|
if (part.support !== undefined) {
|
|
|
|
part.support.scaleDown(100);
|
|
|
|
}
|
|
|
|
}
|
2015-04-24 16:12:48 +02:00
|
|
|
}
|
2015-06-09 21:58:22 +02:00
|
|
|
|
|
|
|
return data;
|
|
|
|
};
|
2015-04-24 16:12:48 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) {
|
|
|
|
"use strict";
|
2015-05-19 19:04:20 +02:00
|
|
|
|
2015-06-09 21:58:22 +02:00
|
|
|
var paths = new D3D.Paths([], false);
|
|
|
|
|
|
|
|
if (even) {
|
|
|
|
for (var length = Math.floor(bounds.left/size)*size; length <= Math.ceil(bounds.right/size)*size; length += size) {
|
|
|
|
paths.push([{X: length, Y: bounds.top}, {X: length, Y: bounds.bottom}]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (uneven) {
|
|
|
|
for (var length = Math.floor(bounds.top/size)*size; length <= Math.floor(bounds.bottom/size)*size; length += size) {
|
|
|
|
paths.push([{X: bounds.left, Y: length}, {X: bounds.right, Y: length}]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//return paths;
|
|
|
|
return paths;
|
2015-05-01 10:06:52 +02:00
|
|
|
};
|
2015-06-09 11:08:06 +02:00
|
|
|
D3D.Slicer.prototype.dataToGCode = function (data, printer) {
|
2015-05-01 12:15:46 +02:00
|
|
|
"use strict";
|
|
|
|
|
2015-06-05 09:56:58 +02:00
|
|
|
var gcode = new D3D.GCode().setSettings(printer);
|
2015-05-01 12:15:46 +02:00
|
|
|
|
2015-06-09 11:08:06 +02:00
|
|
|
function sliceToGCode (path, retract, unRetract) {
|
2015-06-05 09:56:58 +02:00
|
|
|
for (var i = 0; i < path.length; i ++) {
|
|
|
|
var shape = path[i];
|
2015-05-01 12:15:46 +02:00
|
|
|
|
2015-06-05 09:56:58 +02:00
|
|
|
var length = path.closed ? (shape.length + 1) : shape.length;
|
2015-05-01 12:15:46 +02:00
|
|
|
|
2015-06-05 09:56:58 +02:00
|
|
|
for (var j = 0; j < length; j ++) {
|
|
|
|
var point = shape[j % shape.length];
|
2015-05-01 14:09:45 +02:00
|
|
|
|
2015-06-05 09:56:58 +02:00
|
|
|
if (j === 0) {
|
|
|
|
gcode.moveTo(false, point.X, point.Y, layer);
|
|
|
|
|
|
|
|
if (unRetract) {
|
|
|
|
gcode.unRetract();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
gcode.moveTo(true, point.X, point.Y, layer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retract) {
|
|
|
|
gcode.retract();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var layer = 0; layer < data.length; layer ++) {
|
|
|
|
var slice = data[layer];
|
|
|
|
|
|
|
|
if (layer === 1) {
|
2015-06-09 11:08:06 +02:00
|
|
|
gcode.turnFanOn();
|
2015-06-05 09:56:58 +02:00
|
|
|
gcode.bottom = false;
|
|
|
|
}
|
2015-05-01 12:15:46 +02:00
|
|
|
|
2015-05-13 17:37:52 +02:00
|
|
|
for (var i = 0; i < slice.length; i ++) {
|
|
|
|
var layerPart = slice[i];
|
|
|
|
|
2015-06-09 11:08:06 +02:00
|
|
|
sliceToGCode(layerPart.outerLayer, false, true);
|
|
|
|
sliceToGCode(layerPart.insets, false, false);
|
2015-06-09 21:58:22 +02:00
|
|
|
sliceToGCode(layerPart.fill, (layerPart.support === undefined), false);
|
|
|
|
|
|
|
|
if (layerPart.support !== undefined) {
|
|
|
|
sliceToGCode(layerPart.support, true, false);
|
|
|
|
}
|
2015-05-13 17:37:52 +02:00
|
|
|
}
|
2015-06-05 09:56:58 +02:00
|
|
|
|
|
|
|
this.progress.gcodeLayer = layer;
|
|
|
|
this.updateProgress();
|
2015-05-01 12:15:46 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 11:08:06 +02:00
|
|
|
return gcode.getGCode();
|
2015-05-01 12:15:46 +02:00
|
|
|
};
|
2015-06-09 11:08:06 +02:00
|
|
|
D3D.Slicer.prototype.getGCode = function (printer) {
|
2015-05-01 10:06:52 +02:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
var layerHeight = printer.config["printer.layerHeight"];
|
|
|
|
var dimensionsZ = printer.config["printer.dimensions.z"];
|
|
|
|
|
2015-06-05 09:56:58 +02:00
|
|
|
this.progress.totalLayers = Math.floor(Math.min(this.geometry.boundingBox.max.y, dimensionsZ) / layerHeight);
|
2015-05-29 13:51:18 +02:00
|
|
|
this.progress.sliceLayer = 0;
|
|
|
|
this.progress.dataLayer = 0;
|
|
|
|
this.progress.gcodeLayer = 0;
|
|
|
|
|
2015-05-07 18:14:10 +02:00
|
|
|
var start = new Date().getTime();
|
2015-05-20 19:10:18 +02:00
|
|
|
var slices = this.slice(layerHeight, dimensionsZ);
|
2015-05-07 18:14:10 +02:00
|
|
|
var end = new Date().getTime();
|
|
|
|
console.log("Slicing: " + (end - start) + "ms");
|
|
|
|
|
2015-05-20 19:10:18 +02:00
|
|
|
start = new Date().getTime();
|
2015-05-01 10:06:52 +02:00
|
|
|
var data = this.slicesToData(slices, printer);
|
2015-05-20 19:10:18 +02:00
|
|
|
end = new Date().getTime();
|
2015-05-07 18:14:10 +02:00
|
|
|
console.log("Data: " + (end - start) + "ms");
|
|
|
|
|
2015-05-20 19:10:18 +02:00
|
|
|
start = new Date().getTime();
|
2015-06-09 11:08:06 +02:00
|
|
|
var gcode = this.dataToGCode(data, printer);
|
2015-05-20 19:10:18 +02:00
|
|
|
end = new Date().getTime();
|
2015-05-07 18:14:10 +02:00
|
|
|
console.log("Gcode: " + (end - start) + "ms");
|
|
|
|
|
2015-04-24 16:12:48 +02:00
|
|
|
return gcode;
|
|
|
|
};
|