mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-04 21:53:25 +01:00
Merge branch 'webworker'
This commit is contained in:
commit
dd41e6d3e7
1319
build/d3d.js
vendored
1319
build/d3d.js
vendored
File diff suppressed because it is too large
Load Diff
1
build/d3d.min.js
vendored
1
build/d3d.min.js
vendored
File diff suppressed because one or more lines are too long
27
gulpfile.js
27
gulpfile.js
@ -1,27 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var rename = require('gulp-rename');
|
||||
var uglify = require('gulp-uglify');
|
||||
var concat = require('gulp-concat');
|
||||
var watch = require('gulp-watch');
|
||||
|
||||
var files = [
|
||||
"src/utils.js",
|
||||
"src/box.js",
|
||||
"src/printer.js",
|
||||
"src/paths.js",
|
||||
"src/slicer.js"
|
||||
];
|
||||
|
||||
var destination = 'build/';
|
||||
|
||||
gulp.task('default', function () {
|
||||
return gulp.src(files)
|
||||
// .pipe(watch(files))
|
||||
.pipe(concat('d3d.js'))
|
||||
.pipe(gulp.dest(destination))
|
||||
.pipe(uglify())
|
||||
.pipe(rename({extname: '.min.js'}))
|
||||
.pipe(gulp.dest(destination));
|
||||
});
|
11
index.html
11
index.html
@ -20,9 +20,15 @@ $(document).ready(function () {
|
||||
|
||||
var listDoodle = $("#printers-doodle");
|
||||
var listSliceTest = $("#printers-slicetest");
|
||||
var listSliceWebworker = $("#printers-webworker");
|
||||
|
||||
listDoodle.append("<li><a href='doodle.html#192.168.5.1'>Wired Printer</a></li>");
|
||||
listSliceTest.append("<li><a href='slice_test.html#192.168.5.1'>Wired Printer</a></li>");
|
||||
listSliceWebworker.append("<li><a href='webworker_test.html#192.168.5.1'>Wired Printer</a></li>");
|
||||
|
||||
listDoodle.append("<li><a href='doodle.html#" + window.location.host + ":3000'>Node Server</a></li>");
|
||||
listSliceTest.append("<li><a href='slice_test.html#" + window.location.host + ":3000'>Node Server</a></li>");
|
||||
listSliceWebworker.append("<li><a href='webworker_test.html#" + window.location.host + ":3000'>Node Server</a></li>");
|
||||
|
||||
/*
|
||||
printers.push({
|
||||
@ -44,6 +50,7 @@ $(document).ready(function () {
|
||||
|
||||
listDoodle.append("<li><a href='doodle.html#" + box.localip + "'>" + box.wifiboxid + "</a></li>");
|
||||
listSliceTest.append("<li><a href='slice_test.html#" + box.localip + "'>" + box.wifiboxid + "</a></li>");
|
||||
listSliceWebworker.append("<li><a href='webworker_test.html#" + box.localip + "'>" + box.wifiboxid + "</a></li>");
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -54,6 +61,10 @@ $(document).ready(function () {
|
||||
|
||||
<p>Slice Test</p>
|
||||
<ul id="printers-slicetest"></ul>
|
||||
|
||||
<p>Webworkers</p>
|
||||
<ul id="printers-webworker"></ul>
|
||||
|
||||
<!--
|
||||
<table>
|
||||
<tr>
|
||||
|
3919
library/benchmark.js
Normal file
3919
library/benchmark.js
Normal file
File diff suppressed because it is too large
Load Diff
2329
library/cal.js
Normal file
2329
library/cal.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -9342,6 +9342,21 @@ THREE.BufferGeometry.prototype = {
|
||||
|
||||
this.dispatchEvent( { type: 'dispose' } );
|
||||
|
||||
},
|
||||
|
||||
getBuffers: function () {
|
||||
|
||||
var buffers = [];
|
||||
|
||||
for ( var i = 0; i < this.attributesKeys.length; i ++ ) {
|
||||
|
||||
var key = this.attributesKeys[ i ];
|
||||
buffers.push( this.attributes[ key ].array.buffer );
|
||||
|
||||
}
|
||||
|
||||
return buffers;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
BIN
models/dom.stl
Normal file
BIN
models/dom.stl
Normal file
Binary file not shown.
BIN
models/support_test.stl
Normal file
BIN
models/support_test.stl
Normal file
Binary file not shown.
BIN
models/ultimaker_robot.stl
Executable file
BIN
models/ultimaker_robot.stl
Executable file
Binary file not shown.
@ -5,7 +5,7 @@
|
||||
"printer.dimensions.y": 200,
|
||||
"printer.dimensions.z": 200,
|
||||
"printer.endcode": "M107 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;disable axes / steppers\nG90 ;absolute positioning\nM104 S{preheatTemp}\n{if heatedBed}M140 S{preheatBedTemp}\nM117 Done ;display message (20 characters to clear whole screen)",
|
||||
"printer.filamentThickness": 2.89,
|
||||
"printer.filamentThickness": 2.85,
|
||||
"printer.heatedbed": false,
|
||||
"printer.heatup.bed.temperature": 70,
|
||||
"printer.heatup.enabled": true,
|
||||
@ -13,5 +13,35 @@
|
||||
"printer.nozzleDiameter": 0.4,
|
||||
"printer.startcode": ";Generated with Doodle3D (default)\nM109 S{printingTemp} ;set target temperature \n{if heatedBed}M190 S{printingBedTemp} ;set target bed temperature\nG21 ;metric values\nG91 ;relative positioning\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nG92 E0 ;zero the extruded length again\nG1 F9000\nG90 ;absolute positioning\nM117 Printing Doodle... ;display message (20 characters to clear whole screen)",
|
||||
"printer.type": "ultimaker"
|
||||
},
|
||||
"ultimaker2": {
|
||||
"printer.baudrate": "115200",
|
||||
"printer.dimensions.x": 223,
|
||||
"printer.dimensions.y": 223,
|
||||
"printer.dimensions.z": 205,
|
||||
"printer.endcode": "M107 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+5.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 ;home the printer\nM84 ;disable axes / steppers\nG90 ;absolute positioning\nM104 S{preheatTemp}\n{if heatedBed}M140 S{preheatBedTemp}\nM117 Done ;display message (20 characters to clear whole screen)",
|
||||
"printer.filamentThickness": 2.85,
|
||||
"printer.heatedbed": true,
|
||||
"printer.heatup.bed.temperature": 70,
|
||||
"printer.heatup.enabled": true,
|
||||
"printer.heatup.temperature": 180,
|
||||
"printer.nozzleDiameter": 0.4,
|
||||
"printer.startcode": ";Generated with Doodle3D (ultimaker2)\nM109 S{printingTemp} ;set target temperature \n{if heatedBed}M190 S{printingBedTemp} ;set target bed temperature\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nG28 ; home to endstops\nG1 Z15 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\nM117 Printing Doodle... ;display message (20 characters to clear whole screen)",
|
||||
"printer.type": "ultimaker2"
|
||||
},
|
||||
"ultimaker2go": {
|
||||
"printer.baudrate": "115200",
|
||||
"printer.dimensions.x": 120,
|
||||
"printer.dimensions.y": 120,
|
||||
"printer.dimensions.z": 115,
|
||||
"printer.endcode": "M107 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+5.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 ;home the printer\nM84 ;disable axes / steppers\nG90 ;absolute positioning\nM104 S{preheatTemp}\n{if heatedBed}M140 S{preheatBedTemp}\nM117 Done ;display message (20 characters to clear whole screen)",
|
||||
"printer.filamentThickness": 2.85,
|
||||
"printer.heatedbed": false,
|
||||
"printer.heatup.bed.temperature": 70,
|
||||
"printer.heatup.enabled": true,
|
||||
"printer.heatup.temperature": 180,
|
||||
"printer.nozzleDiameter": 0.4,
|
||||
"printer.startcode": ";Generated with Doodle3D (ultimaker2)\nM109 S{printingTemp} ;set target temperature \n{if heatedBed}M190 S{printingBedTemp} ;set target bed temperature\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nG28 ; home to endstops\nG1 Z15 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\nM117 Printing Doodle... ;display message (20 characters to clear whole screen)",
|
||||
"printer.type": "ultimaker2g0"
|
||||
}
|
||||
}
|
@ -1,18 +1,24 @@
|
||||
{
|
||||
"printer.normalFlowRate": 1.0,
|
||||
"printer.bottomFlowRate": 2.0,
|
||||
"printer.bottomLayerSpeed": 35,
|
||||
"printer.bottomLayerSpeed": 35.0,
|
||||
"printer.bottomThickness": 0.4,
|
||||
"printer.fillSize": 5,
|
||||
"printer.fillSize": 5.0,
|
||||
"printer.firstLayerSlow": true,
|
||||
"printer.layerHeight": 0.2,
|
||||
"printer.retraction.amount": 3,
|
||||
"printer.layerHeight": 0.2,
|
||||
"printer.retraction.amount": 3.0,
|
||||
"printer.retraction.enabled": true,
|
||||
"printer.retraction.speed": 50,
|
||||
"printer.retraction.minDistance": 5,
|
||||
"printer.retraction.minDistance": 5.0,
|
||||
"printer.shellThickness": 0.4,
|
||||
"printer.speed": 50,
|
||||
"printer.temperature": 230,
|
||||
"printer.speed": 50.0,
|
||||
"printer.temperature": 210.0,
|
||||
"printer.topThickness": 0.8,
|
||||
"printer.travelSpeed": 200
|
||||
"printer.travelSpeed": 200.0,
|
||||
"printer.support.accaptanceSize": 1.5,
|
||||
"printer.support.distanceY": 0.4,
|
||||
"printer.support.use": true,
|
||||
"printer.support.gritSize": 6.0,
|
||||
"printer.support.margin": 2.0,
|
||||
"printer.support.plateSize": 4.0
|
||||
}
|
@ -12,11 +12,9 @@
|
||||
<script src="src/box.js"></script>
|
||||
<script src="src/printer.js"></script>
|
||||
<script src="src/paths.js"></script>
|
||||
<script src="src/gcode.js"></script>
|
||||
<script src="src/slicer.js"></script>
|
||||
|
||||
<script src="gcode/testgcode.js"></script>
|
||||
<script src="gcode/easterbunny.js"></script>
|
||||
|
||||
<style>
|
||||
canvas {border: 1px solid black;}
|
||||
</style>
|
||||
@ -33,12 +31,12 @@ function init () {
|
||||
var scene = createScene();
|
||||
|
||||
var localIp = location.hash.substring(1);
|
||||
doodleBox = new D3D.Box(localIp);
|
||||
//doodleBox = new D3D.Box(localIp);
|
||||
|
||||
var printer = new D3D.Printer(USER_SETTINGS, PRINTER_SETTINGS["ultimaker"]);
|
||||
var printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS["ultimaker"]);
|
||||
|
||||
var loader = new THREE.STLLoader();
|
||||
loader.load("models/pokemon/pikachu.stl", function (geometry) {
|
||||
loader.load('models/support_test.stl', function (geometry) {
|
||||
//var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1);
|
||||
//var geometry = new THREE.SphereGeometry(10, 20, 10);
|
||||
//var geometry = new THREE.TorusGeometry(20, 10, 30, 30);
|
||||
@ -72,23 +70,23 @@ function init () {
|
||||
|
||||
mesh.rotation.x = -Math.PI/2;
|
||||
mesh.scale.x = mesh.scale.y = mesh.scale.z = 1;
|
||||
mesh.position.x = 100;
|
||||
mesh.position.z = 100;
|
||||
mesh.position.y = -0.1;
|
||||
mesh.position.x = 60;
|
||||
mesh.position.z = 60;
|
||||
|
||||
//scene.add(mesh);
|
||||
mesh.updateMatrix();
|
||||
|
||||
var slicer = new D3D.Slicer().setMesh(mesh);
|
||||
|
||||
var mesh = new THREE.Mesh(slicer.geometry, material);
|
||||
scene.add(mesh);
|
||||
|
||||
var canvas = document.getElementById("canvas");
|
||||
var context = canvas.getContext("2d");
|
||||
|
||||
var img = slicer.drawPaths(printer, 0, 1);
|
||||
context.drawImage(img, 0, 0);
|
||||
var slicer = new D3D.Slicer().setMesh(mesh.geometry, mesh.matrix);
|
||||
|
||||
gcode = slicer.getGcode(printer);
|
||||
//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);
|
||||
});
|
||||
}
|
||||
|
||||
|
64
src/box.js
64
src/box.js
@ -14,14 +14,14 @@
|
||||
|
||||
D3D.Box = function (localIp) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
var scope = this;
|
||||
|
||||
this.batchSize = 512;
|
||||
this.maxBufferedLines = 4096;
|
||||
|
||||
this.localIp = localIp;
|
||||
this.api = "http://" + localIp + "/d3dapi/";
|
||||
|
||||
|
||||
this.config = {};
|
||||
this.status = {};
|
||||
|
||||
@ -31,13 +31,13 @@ D3D.Box = function (localIp) {
|
||||
this.loaded = false;
|
||||
|
||||
this.getConfigAll(function (data) {
|
||||
self.updateConfig(data);
|
||||
scope.updateConfig(data);
|
||||
|
||||
self.update();
|
||||
scope.update();
|
||||
|
||||
self.loaded = true;
|
||||
if (self.onload !== undefined) {
|
||||
self.onload();
|
||||
scope.loaded = true;
|
||||
if (scope.onload !== undefined) {
|
||||
scope.onload();
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -52,6 +52,7 @@ D3D.Box.prototype.updateConfig = function (config) {
|
||||
};
|
||||
D3D.Box.prototype.update = function () {
|
||||
"use strict";
|
||||
var scope = this;
|
||||
//TODO
|
||||
//Code is zo op gezet dat maar api call te gelijk is
|
||||
//Bij error wordt gelijk zelfde data opnieuw gestuurd
|
||||
@ -62,22 +63,24 @@ D3D.Box.prototype.update = function () {
|
||||
this.printBatch();
|
||||
}
|
||||
else {
|
||||
this.updateState();
|
||||
setTimeout(function () {
|
||||
scope.updateState();
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
D3D.Box.prototype.updateState = function () {
|
||||
//que api calls so they don't overload the d3d box
|
||||
"use strict";
|
||||
var self = this;
|
||||
var scope = this;
|
||||
|
||||
this.getInfoStatus(function (data) {
|
||||
self.status = data;
|
||||
scope.status = data;
|
||||
|
||||
if (self.onupdate !== undefined) {
|
||||
self.onupdate(data);
|
||||
if (scope.onupdate !== undefined) {
|
||||
scope.onupdate(data);
|
||||
}
|
||||
|
||||
self.update();
|
||||
scope.update();
|
||||
});
|
||||
};
|
||||
D3D.Box.prototype.print = function (gcode) {
|
||||
@ -98,50 +101,37 @@ D3D.Box.prototype.print = function (gcode) {
|
||||
};
|
||||
D3D.Box.prototype.printBatch = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
var scope = this;
|
||||
|
||||
var gcode = this.printBatches.shift();
|
||||
|
||||
this.setPrinterPrint({
|
||||
"start": ((this.currentBatch === 0) ? true : false),
|
||||
"first": ((this.currentBatch === 0) ? true : false),
|
||||
"gcode": gcode.join("\n")
|
||||
"gcode": gcode.join("\n"),
|
||||
"last": ((this.printBatches.length === 0) ? true : false) //only for debug purposes
|
||||
}, function (data) {
|
||||
console.log("batch sent: " + self.currentBatch, data);
|
||||
console.log("batch sent: " + scope.currentBatch, data);
|
||||
|
||||
if (self.printBatches.length > 0) {
|
||||
if (scope.printBatches.length > 0) {
|
||||
//sent new batch
|
||||
self.currentBatch ++;
|
||||
scope.currentBatch ++;
|
||||
}
|
||||
else {
|
||||
//finish sending
|
||||
}
|
||||
|
||||
self.updateState();
|
||||
scope.updateState();
|
||||
});
|
||||
};
|
||||
D3D.Box.prototype.stopPrint = function () {
|
||||
D3D.Box.prototype.stopPrint = function (printer) {
|
||||
"use strict";
|
||||
|
||||
this.printBatches = [];
|
||||
this.currentBatch = 0;
|
||||
|
||||
var finishMove = [
|
||||
"M107 ;fan off",
|
||||
"G91 ;relative positioning",
|
||||
"G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure",
|
||||
"G1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more",
|
||||
"G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way",
|
||||
"M84 ;disable axes / steppers",
|
||||
"G90 ;absolute positioning",
|
||||
"M104 S180",
|
||||
";M140 S70",
|
||||
"M117 Done ;display message (20 characters to clear whole screen)"
|
||||
];
|
||||
|
||||
this.setPrinterStop({
|
||||
//"gcode": {}
|
||||
"gcode": finishMove.join("\n")
|
||||
"gcode": printer.getEndCode().join("\n")
|
||||
}, function (data) {
|
||||
console.log("Printer stop command sent");
|
||||
});
|
||||
@ -167,12 +157,12 @@ D3D.Box.prototype.getConfigAll = function (callback) {
|
||||
};
|
||||
D3D.Box.prototype.setConfig = function (data, callback) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
var scope = this;
|
||||
|
||||
sendAPI(this.api + "config", data, function (response) {
|
||||
for (var i in response.validation) {
|
||||
if (response.validation[i] === "ok") {
|
||||
self[i] = data[i];
|
||||
scope[i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
184
src/gcode.js
Normal file
184
src/gcode.js
Normal file
@ -0,0 +1,184 @@
|
||||
/******************************************************
|
||||
*
|
||||
* GCode
|
||||
*
|
||||
* Manages the gcode
|
||||
* Also handles different flavours of gcode
|
||||
* TODO
|
||||
* calculate extrusion length and total time
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
D3D.GCode = function () {
|
||||
"use strict";
|
||||
|
||||
this.gcode = [];
|
||||
this.current = {};
|
||||
|
||||
this.extruder = 0.0;
|
||||
this.bottom = true;
|
||||
this.isRetracted = false;
|
||||
this.isFanOn = false;
|
||||
this.nozzlePosition = new THREE.Vector2(0, 0);
|
||||
};
|
||||
D3D.GCode.prototype.addGCode = function (command) {
|
||||
"use strict";
|
||||
|
||||
var str = [];
|
||||
|
||||
for (var i in command) {
|
||||
if (i === "G") {
|
||||
str.push(i + command[i]);
|
||||
}
|
||||
else if (this.current[i] !== command[i]) {
|
||||
str.push(i + command[i]);
|
||||
this.current[i] = command[i];
|
||||
}
|
||||
}
|
||||
|
||||
str = str.join(" ");
|
||||
if (str.length > 0) {
|
||||
this.gcode.push(str);
|
||||
}
|
||||
};
|
||||
D3D.GCode.prototype.setSettings = function (printer) {
|
||||
"use strict";
|
||||
|
||||
this.settings = printer;
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.GCode.prototype.turnFanOn = function (fanSpeed) {
|
||||
"use strict";
|
||||
|
||||
this.isFanOn = true;
|
||||
|
||||
var gcode = {
|
||||
"M": 106
|
||||
};
|
||||
|
||||
if (fanSpeed !== undefined) {
|
||||
gcode["S"] = fanSpeed;
|
||||
}
|
||||
|
||||
this.addGCode(gcode);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.GCode.prototype.turnFanOff = function () {
|
||||
"use strict";
|
||||
|
||||
this.isFanOn = false;
|
||||
|
||||
this.addGCode({
|
||||
"M": 107
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.GCode.prototype.moveTo = function (extrude, x, y, layer) {
|
||||
"use strict";
|
||||
|
||||
var layerHeight = this.settings.config["printer.layerHeight"];
|
||||
var firstLayerSlow = this.settings.config["printer.firstLayerSlow"];
|
||||
var normalSpeed = this.settings.config["printer.speed"];
|
||||
var bottomSpeed = this.settings.config["printer.bottomLayerSpeed"];
|
||||
var normalSpeed = this.settings.config["printer.speed"];
|
||||
var bottomSpeed = this.settings.config["printer.bottomLayerSpeed"];
|
||||
var nozzleDiameter = this.settings.config["printer.nozzleDiameter"];
|
||||
var filamentThickness = this.settings.config["printer.filamentThickness"];
|
||||
var bottomFlowRate = this.settings.config["printer.bottomFlowRate"];
|
||||
var normalFlowRate = this.settings.config["printer.normalFlowRate"];
|
||||
var travelSpeed = this.settings.config["printer.travelSpeed"];
|
||||
|
||||
if (this.bottom) {
|
||||
var speed = bottomSpeed * 60;
|
||||
var flowRate = bottomFlowRate;
|
||||
}
|
||||
else {
|
||||
var speed = normalSpeed * 60;
|
||||
var flowRate = normalFlowRate;
|
||||
}
|
||||
var z = (layer + 1) * layerHeight;
|
||||
|
||||
if (extrude) {
|
||||
var lineLength = this.nozzlePosition.distanceTo(new THREE.Vector2(x, y));
|
||||
|
||||
var filamentSurfaceArea = Math.pow((filamentThickness/2), 2) * Math.PI;
|
||||
this.extruder += lineLength * nozzleDiameter * layerHeight / filamentSurfaceArea * flowRate;
|
||||
|
||||
this.addGCode({
|
||||
"G": 1,
|
||||
"X": x.toFixed(3), "Y": y.toFixed(3), "Z": z.toFixed(3),
|
||||
"F": speed.toFixed(3),
|
||||
"E": this.extruder.toFixed(3)
|
||||
});
|
||||
}
|
||||
else {
|
||||
var speed = travelSpeed * 60;
|
||||
|
||||
this.addGCode({
|
||||
"G": 0,
|
||||
"X": x.toFixed(3), "Y": y.toFixed(3), "Z": z.toFixed(3),
|
||||
"F": speed.toFixed(3)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
this.nozzlePosition = new THREE.Vector2(x, y);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.GCode.prototype.unRetract = function () {
|
||||
"use strict";
|
||||
|
||||
if (this.isRetracted) {
|
||||
this.isRetracted = false;
|
||||
|
||||
var retractionAmount = this.settings.config["printer.retraction.amount"];
|
||||
var retractionEnabled = this.settings.config["printer.retraction.enabled"];
|
||||
var retractionMinDistance = this.settings.config["printer.retraction.minDistance"];
|
||||
var retractionSpeed = this.settings.config["printer.retraction.speed"];
|
||||
|
||||
var speed = retractionSpeed * 60;
|
||||
|
||||
if (this.extruder > retractionMinDistance && retractionEnabled) {
|
||||
this.addGCode({
|
||||
"G": 0,
|
||||
"E": this.extruder.toFixed(3),
|
||||
"F": speed.toFixed(3)
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
D3D.GCode.prototype.retract = function () {
|
||||
"use strict";
|
||||
|
||||
if (!this.isRetracted) {
|
||||
this.isRetracted = true;
|
||||
|
||||
var retractionAmount = this.settings.config["printer.retraction.amount"];
|
||||
var retractionEnabled = this.settings.config["printer.retraction.enabled"];
|
||||
var retractionMinDistance = this.settings.config["printer.retraction.minDistance"];
|
||||
var retractionSpeed = this.settings.config["printer.retraction.speed"];
|
||||
|
||||
var speed = retractionSpeed * 60;
|
||||
|
||||
if (this.extruder > retractionMinDistance && retractionEnabled) {
|
||||
this.addGCode({
|
||||
"G": 0,
|
||||
"E": (this.extruder - retractionAmount).toFixed(3),
|
||||
"F": speed.toFixed(3)
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
D3D.GCode.prototype.getGCode = function () {
|
||||
"use strict";
|
||||
|
||||
return this.settings.getStartCode().concat(this.gcode, this.settings.getEndCode());
|
||||
};
|
24
src/paths.js
24
src/paths.js
@ -160,6 +160,20 @@ D3D.Paths.prototype.optimizePath = function (start) {
|
||||
|
||||
return optimizedPaths;
|
||||
};
|
||||
D3D.Paths.prototype.areas = function () {
|
||||
"use strict";
|
||||
|
||||
var areas = [];
|
||||
|
||||
for (var i = 0; i < this.length; i ++) {
|
||||
var shape = this[i];
|
||||
|
||||
var area = Math.abs(ClipperLib.Clipper.Area(shape));
|
||||
areas.push(area);
|
||||
}
|
||||
|
||||
return areas;
|
||||
};
|
||||
D3D.Paths.prototype.tresholdArea = function (minArea) {
|
||||
//code not tested yet
|
||||
"use strict";
|
||||
@ -196,6 +210,16 @@ D3D.Paths.prototype.bounds = function () {
|
||||
|
||||
return ClipperLib.Clipper.GetBounds(this);
|
||||
};
|
||||
D3D.Paths.prototype.boundSize = function () {
|
||||
"use strict";
|
||||
|
||||
var bounds = this.bounds();
|
||||
|
||||
var width = bounds.right - bounds.left;
|
||||
var height = bounds.top - bounds.bottom;
|
||||
|
||||
return width * height;
|
||||
};
|
||||
D3D.Paths.prototype.draw = function (context, color) {
|
||||
"use strict";
|
||||
|
||||
|
@ -5,13 +5,10 @@
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
D3D.Printer = function (printerSettings, userSettings) {
|
||||
D3D.Printer = function () {
|
||||
"use strict";
|
||||
|
||||
this.config = {};
|
||||
|
||||
this.updateConfig(printerSettings);
|
||||
this.updateConfig(userSettings);
|
||||
};
|
||||
D3D.Printer.prototype.updateConfig = function (config) {
|
||||
"use strict";
|
||||
@ -36,6 +33,7 @@ D3D.Printer.prototype.getEndCode = function () {
|
||||
"use strict";
|
||||
|
||||
var gcode = this.config["printer.endcode"];
|
||||
|
||||
gcode = this.subsituteVariables(gcode);
|
||||
|
||||
return gcode.split("\n");
|
||||
|
457
src/slicer.js
457
src/slicer.js
@ -2,48 +2,46 @@
|
||||
*
|
||||
* Slicer
|
||||
*
|
||||
* TODO (optimalisatie)
|
||||
* sorteer lijnen op laagste hoogte -> stop loop wanneer hij een lijn zonder intersectie heeft gevonden
|
||||
* verwijder lijnen die ooit interactie gehad hebben, maar nu niet meer
|
||||
* helft van lijnen toevoegen omdat 4face altijd recht is, en 3face dus te veel data bevat
|
||||
*
|
||||
* omliggende lagen -> difference && sum omliggende lijnen
|
||||
* voor laag 5 = 5 diff (3 && 4 && 6 && 7))
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
D3D.Slicer = function () {
|
||||
"use strict";
|
||||
|
||||
this.progress = {
|
||||
totalFaces: 0,
|
||||
currentFace: 0,
|
||||
totalLayers: 0,
|
||||
sliceLayer: 0,
|
||||
dataLayer: 0,
|
||||
gcodeLayer: 0
|
||||
};
|
||||
};
|
||||
D3D.Slicer.prototype.setMesh = function (mesh) {
|
||||
D3D.Slicer.prototype.setMesh = function (geometry, matrix) {
|
||||
"use strict";
|
||||
|
||||
//convert buffergeometry to geometry;
|
||||
var geometry = mesh.geometry.clone();
|
||||
if (geometry instanceof THREE.BufferGeometry) {
|
||||
geometry = new THREE.Geometry().fromBufferGeometry(geometry);
|
||||
}
|
||||
|
||||
//remove duplicate vertices;
|
||||
for (var i = 0; i < geometry.vertices.length; i ++) {
|
||||
var vertexA = geometry.vertices[i];
|
||||
|
||||
for (var j = i + 1; j < geometry.vertices.length; j ++) {
|
||||
var vertexB = geometry.vertices[j];
|
||||
|
||||
if (vertexA.equals(vertexB)) {
|
||||
geometry.vertices[j] = vertexA;
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry.mergeVertices();
|
||||
|
||||
//apply mesh matrix on geometry;
|
||||
mesh.updateMatrix();
|
||||
geometry.applyMatrix(mesh.matrix);
|
||||
geometry.applyMatrix(matrix);
|
||||
geometry.mergeVertices();
|
||||
geometry.computeFaceNormals();
|
||||
geometry.computeBoundingBox();
|
||||
|
||||
/*
|
||||
for (var i = 0; i < geometry.faces.length; i ++) {
|
||||
var face = geometry.faces[i];
|
||||
var normal = face.normal;
|
||||
|
||||
if (normal.x === 0 && normal.y === 0 && normal.z === 0) {
|
||||
geometry.faces.splice(i, 1);
|
||||
i --;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
this.geometry = geometry;
|
||||
|
||||
//get unique lines from geometry;
|
||||
@ -51,17 +49,32 @@ D3D.Slicer.prototype.setMesh = function (mesh) {
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Slicer.prototype.updateProgress = function () {
|
||||
'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;
|
||||
|
||||
if (this.onProgress !== undefined) {
|
||||
|
||||
this.onProgress(this.progress);
|
||||
}
|
||||
};
|
||||
D3D.Slicer.prototype.createLines = function () {
|
||||
"use strict";
|
||||
|
||||
this.progress.totalFaces = this.geometry.faces.length;
|
||||
|
||||
this.lines = [];
|
||||
var lineLookup = {};
|
||||
|
||||
var self = this;
|
||||
function addLine (a, b) {
|
||||
|
||||
//think lookup can only be b_a, a_b is only possible when face is flipped
|
||||
var index = lineLookup[b + "_" + a] || lineLookup[a + "_" + b];
|
||||
var index = lineLookup[b + "_" + a];
|
||||
|
||||
if (index === undefined) {
|
||||
index = self.lines.length;
|
||||
@ -70,8 +83,7 @@ D3D.Slicer.prototype.createLines = function () {
|
||||
self.lines.push({
|
||||
line: new THREE.Line3(self.geometry.vertices[a], self.geometry.vertices[b]),
|
||||
connects: [],
|
||||
normals: [],
|
||||
ignore: 0
|
||||
normals: []
|
||||
});
|
||||
}
|
||||
|
||||
@ -99,10 +111,14 @@ D3D.Slicer.prototype.createLines = function () {
|
||||
this.lines[b].normals.push(normal);
|
||||
this.lines[c].normals.push(normal);
|
||||
}
|
||||
|
||||
this.progress.currentFace = i;
|
||||
this.updateProgress();
|
||||
}
|
||||
};
|
||||
D3D.Slicer.prototype.slice = function (layerHeight, height) {
|
||||
"use strict";
|
||||
var numLayers = height / layerHeight;
|
||||
|
||||
var layersIntersections = [];
|
||||
|
||||
@ -113,7 +129,7 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
|
||||
var max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight);
|
||||
|
||||
for (var layerIndex = min; layerIndex <= max; layerIndex ++) {
|
||||
if (layerIndex >= 0) {
|
||||
if (layerIndex >= 0 && layerIndex < numLayers) {
|
||||
if (layersIntersections[layerIndex] === undefined) {
|
||||
layersIntersections[layerIndex] = [];
|
||||
}
|
||||
@ -126,21 +142,28 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
|
||||
|
||||
//still error in first layer, so remove first layer & last layer
|
||||
//see https://github.com/Doodle3D/Doodle3D-Slicer/issues/1
|
||||
for (var layer = 1; layer < layersIntersections.length-1; layer ++) {
|
||||
//for (var layer = 0; layer < layersIntersections.length; layer ++) {
|
||||
for (var layer = 0; layer < layersIntersections.length; layer ++) {
|
||||
var layerIntersections = layersIntersections[layer];
|
||||
var y = layer*layerHeight;
|
||||
var y = layer * layerHeight;
|
||||
|
||||
var intersections = [];
|
||||
var log = [];
|
||||
for (var i = 0; i < layerIntersections.length; i ++) {
|
||||
var index = layerIntersections[i];
|
||||
var line = this.lines[index].line;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
intersections[index] = new THREE.Vector2(z, x);
|
||||
log.push({x: z, y: x, index: index, connects: this.lines[index].connects});
|
||||
}
|
||||
|
||||
var done = [];
|
||||
@ -155,24 +178,33 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
|
||||
var intersection = intersections[index];
|
||||
shape.push({X: intersection.x, Y: intersection.y});
|
||||
|
||||
done.push(index);
|
||||
|
||||
var connects = this.lines[index].connects;
|
||||
var faceNormals = this.lines[index].normals;
|
||||
for (var j = 0; j < connects.length; j ++) {
|
||||
index = connects[j];
|
||||
|
||||
if (intersections[index] && done.indexOf(index) === -1) {
|
||||
if (intersections[index] !== undefined && done.indexOf(index) === -1) {
|
||||
done.push(index);
|
||||
|
||||
var a = new THREE.Vector2(intersection.x, intersection.y);
|
||||
var b = intersections[index];
|
||||
var normal = a.sub(b).normal().normalize();
|
||||
var faceNormal = faceNormals[Math.floor(j/2)];
|
||||
|
||||
if (normal.dot(faceNormal) > 0) {
|
||||
break;
|
||||
if (a.distanceTo(b) === 0) {
|
||||
connects = connects.concat(this.lines[index].connects);
|
||||
faceNormals = faceNormals.concat(this.lines[index].normals);
|
||||
index = -1;
|
||||
}
|
||||
else {
|
||||
index = -1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -205,11 +237,12 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
|
||||
|
||||
//think this check is not nescesary, always higher as 0
|
||||
if (shape.length > 0) {
|
||||
slice.push(new D3D.Paths([shape]));
|
||||
slice.push(new D3D.Paths([shape], true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var layerParts = [];
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
@ -237,8 +270,10 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.sliceLayer = layer;
|
||||
this.updateProgress();
|
||||
}
|
||||
return slices;
|
||||
};
|
||||
D3D.Slicer.prototype.slicesToData = function (slices, printer) {
|
||||
@ -246,23 +281,25 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
|
||||
|
||||
var scale = 100;
|
||||
|
||||
var layerHeight = printer.config["printer.layerHeight"] * scale;
|
||||
var dimensionsZ = printer.config["printer.dimensions.z"] * scale;
|
||||
var layerHeight = printer.config["printer.layerHeight"];
|
||||
var nozzleDiameter = printer.config["printer.nozzleDiameter"] * scale;
|
||||
var shellThickness = printer.config["printer.shellThickness"] * scale;
|
||||
var fillSize = printer.config["printer.fillSize"] * scale;
|
||||
var brimOffset = printer.config["printer.brimOffset"] * scale;
|
||||
var bottomThickness = printer.config["printer.bottomThickness"] * scale;
|
||||
var topThickness = printer.config["printer.topThickness"] * scale;
|
||||
var bottomThickness = printer.config["printer.bottomThickness"];
|
||||
var topThickness = printer.config["printer.topThickness"];
|
||||
var useSupport = printer.config["printer.support.use"];
|
||||
var supportGritSize = printer.config["printer.support.gritSize"] * scale;
|
||||
var supportAccaptanceSize = printer.config["printer.support.accaptanceSize"] * scale;
|
||||
var supportMargin = printer.config["printer.support.margin"] * scale;
|
||||
var plateSize = printer.config["printer.support.plateSize"] * scale;
|
||||
var supportDistanceY = printer.config["printer.support.distanceY"];
|
||||
|
||||
var supportDistanceLayers = Math.ceil(supportDistanceY / layerHeight);
|
||||
var bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
|
||||
var topSkinCount = Math.ceil(topThickness/layerHeight);
|
||||
var nozzleRadius = nozzleDiameter / 2;
|
||||
|
||||
var start = new THREE.Vector2(0, 0);
|
||||
|
||||
var data = [];
|
||||
|
||||
var lowFillTemplate = this.getFillTemplate({
|
||||
left: this.geometry.boundingBox.min.z * scale,
|
||||
top: this.geometry.boundingBox.min.x * scale,
|
||||
@ -270,45 +307,64 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
|
||||
bottom: this.geometry.boundingBox.max.x * scale
|
||||
}, fillSize, true, true);
|
||||
|
||||
var data = [];
|
||||
|
||||
//generate outerLayer and insets
|
||||
for (var layer = 0; layer < slices.length; layer ++) {
|
||||
var slice = slices[layer];
|
||||
|
||||
|
||||
var layerData = [];
|
||||
data.push(layerData);
|
||||
|
||||
var downSkin = new D3D.Paths([], true);
|
||||
if (layer - bottomSkinCount >= 0) {
|
||||
var downLayer = slices[layer - bottomSkinCount];
|
||||
for (var i = 0; i < downLayer.length; i ++) {
|
||||
downSkin.join(downLayer[i]);
|
||||
}
|
||||
}
|
||||
var upSkin = new D3D.Paths([], true);
|
||||
if (layer + topSkinCount < slices.length) {
|
||||
var upLayer = slices[layer + topSkinCount];
|
||||
for (var i = 0; i < upLayer.length; i ++) {
|
||||
upSkin.join(upLayer[i]);
|
||||
}
|
||||
}
|
||||
var surroundingLayer = upSkin.intersect(downSkin).scaleUp(scale);
|
||||
var sliceData = [];
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
var part = slice[i];
|
||||
|
||||
//var outerLayer = part.clone();
|
||||
var outerLayer = part.clone().scaleUp(scale).offset(-nozzleRadius);
|
||||
|
||||
var insets = new D3D.Paths([], true);
|
||||
if (outerLayer.length > 0) {
|
||||
var insets = new D3D.Paths([], true);
|
||||
for (var offset = nozzleDiameter; offset <= shellThickness; offset += nozzleDiameter) {
|
||||
var inset = outerLayer.offset(-offset);
|
||||
|
||||
insets.join(inset);
|
||||
}
|
||||
|
||||
var fillArea = (inset || outerLayer).offset(-nozzleRadius);
|
||||
//var fillArea = (inset || outerLayer).clone();
|
||||
layerData.push({
|
||||
outerLayer: outerLayer,
|
||||
insets: insets
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//generate infills
|
||||
for (var layer = 0; layer < data.length; layer ++) {
|
||||
var slice = data[layer];
|
||||
|
||||
var downSkin = new D3D.Paths([], true);
|
||||
if (layer - bottomSkinCount >= 0) {
|
||||
var downLayer = data[layer - bottomSkinCount];
|
||||
for (var i = 0; i < downLayer.length; i ++) {
|
||||
downSkin.join(downLayer[i].outerLayer);
|
||||
}
|
||||
}
|
||||
var upSkin = new D3D.Paths([], true);
|
||||
if (layer + topSkinCount < data.length) {
|
||||
var upLayer = data[layer + topSkinCount];
|
||||
for (var i = 0; i < upLayer.length; i ++) {
|
||||
upSkin.join(upLayer[i].outerLayer);
|
||||
}
|
||||
}
|
||||
var surroundingLayer = upSkin.intersect(downSkin);
|
||||
var sliceData = [];
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
var part = slice[i];
|
||||
var outerLayer = part.outerLayer;
|
||||
var insets = part.insets;
|
||||
|
||||
if (outerLayer.length > 0) {
|
||||
var fillArea = ((insets.length > 0) ? insets : outerLayer).offset(-nozzleRadius);
|
||||
var highFillArea = fillArea.difference(surroundingLayer);
|
||||
var lowFillArea = fillArea.difference(highFillArea);
|
||||
|
||||
@ -325,36 +381,107 @@ D3D.Slicer.prototype.slicesToData = function (slices, printer) {
|
||||
fill.join(highFillTemplate.intersect(highFillArea));
|
||||
}
|
||||
|
||||
outerLayer = outerLayer.optimizePath(start);
|
||||
if (insets.length > 0) {
|
||||
insets = insets.optimizePath(outerLayer.lastPoint());
|
||||
fill = fill.optimizePath(insets.lastPoint());
|
||||
}
|
||||
else {
|
||||
fill = fill.optimizePath(outerLayer.lastPoint());
|
||||
part.fill = fill;
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.dataLayer = layer;
|
||||
this.updateProgress();
|
||||
}
|
||||
|
||||
//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
|
||||
}, supportGritSize, true, true);
|
||||
|
||||
var supportAreas = new D3D.Paths([], true);
|
||||
|
||||
for (var layer = data.length - 1 - supportDistanceLayers; layer >= 0; layer --) {
|
||||
if (supportAreas.length > 0) {
|
||||
|
||||
if (layer >= supportDistanceLayers) {
|
||||
var sliceSkin = new D3D.Paths([], true);
|
||||
var slice = data[layer - supportDistanceLayers];
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
sliceSkin.join(slice[i].outerLayer);
|
||||
}
|
||||
sliceSkin = sliceSkin.offset(supportMargin);
|
||||
|
||||
supportAreas = supportAreas.difference(sliceSkin);
|
||||
}
|
||||
|
||||
if (fill.length > 0) {
|
||||
start = fill.lastPoint();
|
||||
}
|
||||
else if (insets.length > 0) {
|
||||
start = insets.lastPoint();
|
||||
var currentSlice = data[layer];
|
||||
|
||||
if (layer === 0) {
|
||||
supportAreas = supportAreas.offset(plateSize).difference(sliceSkin);
|
||||
|
||||
var template = this.getFillTemplate(supportAreas.bounds(), nozzleDiameter, true, false);
|
||||
|
||||
currentSlice[0].support = template.intersect(supportAreas);
|
||||
}
|
||||
else {
|
||||
start = outerLayer.lastPoint();
|
||||
currentSlice[0].support = supportTemplate.intersect(supportAreas).join(supportAreas.clone());
|
||||
}
|
||||
}
|
||||
|
||||
layerData.push({
|
||||
outerLayer: outerLayer.scaleDown(scale),
|
||||
fill: fill.scaleDown(scale),
|
||||
insets: insets.scaleDown(scale)
|
||||
});
|
||||
var supportSlice = data[layer + supportDistanceLayers - 1];
|
||||
var supportSkin = new D3D.Paths([], true);
|
||||
for (var i = 0; i < supportSlice.length; i ++) {
|
||||
//supportSkin = supportSkin.union(supportSlice[i].outerLayer);
|
||||
supportSkin.join(supportSlice[i].outerLayer);
|
||||
}
|
||||
|
||||
var slice = data[layer + supportDistanceLayers];
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
var slicePart = slice[i];
|
||||
var outerLayer = slicePart.outerLayer;
|
||||
|
||||
var overlap = supportSkin.offset(supportAccaptanceSize).intersect(outerLayer);
|
||||
var overhang = outerLayer.difference(overlap);
|
||||
|
||||
if (overlap.length === 0 || overhang.length > 0) {
|
||||
var supportArea = outerLayer.difference(supportSkin.intersect(outerLayer));
|
||||
supportAreas = supportAreas.union(supportArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//finalize paths
|
||||
var start = new THREE.Vector2(0, 0);
|
||||
var order = ["outerLayer", "insets", "fill", "support"];
|
||||
|
||||
for (var layer = 0; layer < data.length; layer ++) {
|
||||
var slice = data[layer];
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
var part = slice[i];
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
part.outerLayer.scaleDown(100);
|
||||
part.insets.scaleDown(100);
|
||||
part.fill.scaleDown(100);
|
||||
if (part.support !== undefined) {
|
||||
part.support.scaleDown(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) {
|
||||
"use strict";
|
||||
|
||||
@ -374,154 +501,74 @@ D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) {
|
||||
//return paths;
|
||||
return paths;
|
||||
};
|
||||
D3D.Slicer.prototype.dataToGcode = function (data, printer) {
|
||||
D3D.Slicer.prototype.dataToGCode = function (data, printer) {
|
||||
"use strict";
|
||||
|
||||
var layerHeight = printer.config["printer.layerHeight"];
|
||||
var normalSpeed = printer.config["printer.speed"];
|
||||
var bottomSpeed = printer.config["printer.bottomLayerSpeed"];
|
||||
var firstLayerSlow = printer.config["printer.firstLayerSlow"];
|
||||
var bottomFlowRate = printer.config["printer.bottomFlowRate"];
|
||||
var normalFlowRate = printer.config["printer.normalFlowRate"];
|
||||
var travelSpeed = printer.config["printer.travelSpeed"];
|
||||
var filamentThickness = printer.config["printer.filamentThickness"];
|
||||
var nozzleDiameter = printer.config["printer.nozzleDiameter"];
|
||||
var enableTraveling = printer.config["printer.enableTraveling"];
|
||||
var retractionEnabled = printer.config["printer.retraction.enabled"];
|
||||
var retractionSpeed = printer.config["printer.retraction.speed"];
|
||||
var retractionMinDistance = printer.config["printer.retraction.minDistance"];
|
||||
var retractionAmount = printer.config["printer.retraction.amount"];
|
||||
|
||||
function sliceToGcode (path) {
|
||||
var gcode = [];
|
||||
var gcode = new D3D.GCode().setSettings(printer);
|
||||
|
||||
function sliceToGCode (path, retract, unRetract) {
|
||||
for (var i = 0; i < path.length; i ++) {
|
||||
var shape = path[i];
|
||||
|
||||
var previousPoint;
|
||||
|
||||
var length = path.closed ? (shape.length + 1) : shape.length;
|
||||
|
||||
for (var j = 0; j < length; j ++) {
|
||||
var point = shape[j % shape.length];
|
||||
|
||||
if (j === 0) {
|
||||
//TODO
|
||||
//add retraction
|
||||
gcode.moveTo(false, point.X, point.Y, layer);
|
||||
|
||||
gcode.push([
|
||||
"G0",
|
||||
"X" + point.X.toFixed(3) + " Y" + point.Y.toFixed(3) + " Z" + z,
|
||||
"F" + (travelSpeed * 60)
|
||||
].join(" "));
|
||||
|
||||
|
||||
if (extruder > retractionMinDistance && retractionEnabled && j === 0) {
|
||||
gcode.push([
|
||||
"G0",
|
||||
"E" + extruder.toFixed(3),
|
||||
"F" + (retractionSpeed * 60).toFixed(3)
|
||||
].join(" "));
|
||||
if (unRetract) {
|
||||
gcode.unRetract();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
var a = new THREE.Vector2(point.X, point.Y);
|
||||
var b = new THREE.Vector2(previousPoint.X, previousPoint.Y);
|
||||
var lineLength = a.distanceTo(b);
|
||||
|
||||
extruder += lineLength * nozzleDiameter * layerHeight / filamentSurfaceArea * flowRate;
|
||||
|
||||
gcode.push([
|
||||
"G1",
|
||||
"X" + point.X.toFixed(3) + " Y" + point.Y.toFixed(3) + " Z" + z,
|
||||
"F" + speed,
|
||||
"E" + extruder.toFixed(3)
|
||||
].join(" "));
|
||||
gcode.moveTo(true, point.X, point.Y, layer);
|
||||
}
|
||||
|
||||
previousPoint = point;
|
||||
}
|
||||
}
|
||||
|
||||
if (extruder > retractionMinDistance && retractionEnabled) {
|
||||
gcode.push([
|
||||
"G0",
|
||||
"E" + (extruder - retractionAmount).toFixed(3),
|
||||
"F" + (retractionSpeed * 60).toFixed(3)
|
||||
].join(" "));
|
||||
|
||||
if (retract) {
|
||||
gcode.retract();
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
var gcode = printer.getStartCode();
|
||||
|
||||
var extruder = 0.0;
|
||||
var speed = firstLayerSlow ? (bottomSpeed*60).toFixed(3) : (normalSpeed*60).toFixed(3);
|
||||
var filamentSurfaceArea = Math.pow((filamentThickness/2), 2) * Math.PI;
|
||||
var flowRate = bottomFlowRate;
|
||||
|
||||
for (var layer = 0; layer < data.length; layer ++) {
|
||||
var slice = data[layer];
|
||||
|
||||
//turn on fan on layer 1
|
||||
if (layer === 1) {
|
||||
gcode.push("M106");
|
||||
speed = (normalSpeed*60).toFixed(3);
|
||||
flowRate = normalFlowRate;
|
||||
gcode.turnFanOn();
|
||||
gcode.bottom = false;
|
||||
}
|
||||
|
||||
var z = ((layer + 1) * layerHeight).toFixed(3);
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
var layerPart = slice[i];
|
||||
|
||||
gcode = gcode.concat(sliceToGcode(layerPart.outerLayer));
|
||||
gcode = gcode.concat(sliceToGcode(layerPart.insets));
|
||||
gcode = gcode.concat(sliceToGcode(layerPart.fill));
|
||||
sliceToGCode(layerPart.outerLayer, false, true);
|
||||
sliceToGCode(layerPart.insets, false, false);
|
||||
sliceToGCode(layerPart.fill, true, false);
|
||||
|
||||
if (layerPart.support !== undefined) {
|
||||
sliceToGCode(layerPart.support, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
this.progress.gcodeLayer = layer;
|
||||
this.updateProgress();
|
||||
}
|
||||
|
||||
gcode = gcode.concat(printer.getEndCode());
|
||||
|
||||
return gcode;
|
||||
return gcode.getGCode();
|
||||
};
|
||||
//only for debug purposes
|
||||
D3D.Slicer.prototype.drawPaths = function (printer, min, max) {
|
||||
D3D.Slicer.prototype.getGCode = function (printer) {
|
||||
"use strict";
|
||||
|
||||
var layerHeight = printer.config["printer.layerHeight"];
|
||||
var dimensionsZ = printer.config["printer.dimensions.z"];
|
||||
|
||||
var slices = this.slice(layerHeight, dimensionsZ);
|
||||
|
||||
var data = this.slicesToData(slices, printer);
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = 400;
|
||||
canvas.height = 400;
|
||||
var context = canvas.getContext("2d");
|
||||
|
||||
for (var layer = min; layer < max; layer ++) {
|
||||
var slice = data[layer % data.length];
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
var layerPart = slice[i];
|
||||
|
||||
layerPart.insets.draw(context, "blue");
|
||||
layerPart.outerLayer.draw(context, "green");
|
||||
layerPart.fill.draw(context, "red");
|
||||
}
|
||||
}
|
||||
|
||||
return canvas;
|
||||
};
|
||||
D3D.Slicer.prototype.getGcode = function (printer) {
|
||||
"use strict";
|
||||
|
||||
var layerHeight = printer.config["printer.layerHeight"];
|
||||
var dimensionsZ = printer.config["printer.dimensions.z"];
|
||||
this.progress.totalLayers = Math.floor(Math.min(this.geometry.boundingBox.max.y, dimensionsZ) / layerHeight);
|
||||
this.progress.sliceLayer = 0;
|
||||
this.progress.dataLayer = 0;
|
||||
this.progress.gcodeLayer = 0;
|
||||
|
||||
var start = new Date().getTime();
|
||||
var slices = this.slice(layerHeight, dimensionsZ);
|
||||
@ -534,7 +581,7 @@ D3D.Slicer.prototype.getGcode = function (printer) {
|
||||
console.log("Data: " + (end - start) + "ms");
|
||||
|
||||
start = new Date().getTime();
|
||||
var gcode = this.dataToGcode(data, printer);
|
||||
var gcode = this.dataToGCode(data, printer);
|
||||
end = new Date().getTime();
|
||||
console.log("Gcode: " + (end - start) + "ms");
|
||||
|
||||
|
78
src/slicerworker.js
Normal file
78
src/slicerworker.js
Normal file
@ -0,0 +1,78 @@
|
||||
D3D.SlicerWorker = function () {
|
||||
'use strict';
|
||||
|
||||
this.worker = new Worker('webworker/worker.js');
|
||||
|
||||
var scope = this;
|
||||
this.worker.addEventListener('message', function (event) {
|
||||
switch (event.data['cmd']) {
|
||||
case 'PROGRESS':
|
||||
|
||||
if (scope.onprogress !== undefined) {
|
||||
var progress = event.data['progress'];
|
||||
|
||||
scope.onprogress(progress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'GCODE':
|
||||
if (scope.onfinish !== undefined) {
|
||||
var gcode = event.data['gcode'];
|
||||
|
||||
scope.onfinish(gcode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
D3D.SlicerWorker.prototype.setSettings = function (USER_SETTINGS, PRINTER_SETTINGS) {
|
||||
'use strict';
|
||||
|
||||
this.worker.postMessage({
|
||||
'cmd': 'SET_SETTINGS',
|
||||
'USER_SETTINGS': USER_SETTINGS,
|
||||
'PRINTER_SETTINGS': PRINTER_SETTINGS
|
||||
});
|
||||
};
|
||||
D3D.SlicerWorker.prototype.setMesh = function (mesh) {
|
||||
'use strict';
|
||||
|
||||
if (mesh.geometry instanceof THREE.Geometry) {
|
||||
var geometry = new THREE.BufferGeometry().fromGeometry(mesh.geometry);
|
||||
}
|
||||
else {
|
||||
var geometry = mesh.geometry.clone();
|
||||
}
|
||||
|
||||
var buffers = [];
|
||||
|
||||
for (var i = 0; i < geometry.attributesKeys.length; i ++) {
|
||||
var key = geometry.attributesKeys[i];
|
||||
buffers.push(geometry.attributes[key].array.buffer);
|
||||
}
|
||||
|
||||
mesh.updateMatrix();
|
||||
|
||||
this.worker.postMessage({
|
||||
'cmd': 'SET_MESH',
|
||||
'geometry': {
|
||||
'attributes': geometry.attributes,
|
||||
'attributesKeys': geometry.attributesKeys
|
||||
},
|
||||
'matrix': mesh.matrix.toArray()
|
||||
}, buffers);
|
||||
};
|
||||
D3D.SlicerWorker.prototype.slice = function () {
|
||||
'use strict';
|
||||
|
||||
this.worker.postMessage({
|
||||
'cmd': 'SLICE'
|
||||
});
|
||||
};
|
||||
D3D.SlicerWorker.prototype.close = function () {
|
||||
'use strict';
|
||||
|
||||
this.worker.postMessage({
|
||||
'cmd': 'CLOSE'
|
||||
});
|
||||
};
|
57
src/utils.js
57
src/utils.js
@ -1,7 +1,7 @@
|
||||
/******************************************************
|
||||
*
|
||||
* Utils
|
||||
* requires jQuery, Three.js
|
||||
* dependices Three.js
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
@ -14,6 +14,37 @@ var D3D = {
|
||||
function sendAPI (url, data, callback) {
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
var form = new FormData();
|
||||
|
||||
for (var i in data) {
|
||||
form.append(i, JSON.stringify(data[i]));
|
||||
}
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('POST', url, true);
|
||||
request.send(data);
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4 && request.status === 200) {
|
||||
var response = JSON.parse(request.responseText);
|
||||
|
||||
if (response.status === "success") {
|
||||
if (callback !== undefined) {
|
||||
callback(response.data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.warn(response.msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log(request);
|
||||
console.warn("Failed connecting to " + url);
|
||||
//sendAPI(url, data, callback);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
@ -38,7 +69,30 @@ function sendAPI (url, data, callback) {
|
||||
|
||||
function getAPI (url, callback) {
|
||||
"use strict";
|
||||
/*
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.send();
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4 && request.status === 200) {
|
||||
var response = JSON.parse(request.responseText);
|
||||
|
||||
if (response.status === "success") {
|
||||
if (callback !== undefined) {
|
||||
callback(response.data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.warn(response.msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.warn("Failed connecting to " + url);
|
||||
sendAPI(url, callback);
|
||||
}
|
||||
};*/
|
||||
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
dataType: "json",
|
||||
@ -57,6 +111,7 @@ function getAPI (url, callback) {
|
||||
console.warn("Failed connecting to " + url);
|
||||
getAPI(url, callback);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function loadSettings (url, callback) {
|
||||
|
9
webworker/benchmark.js
Normal file
9
webworker/benchmark.js
Normal file
@ -0,0 +1,9 @@
|
||||
self.addEventListener("message", function (event) {
|
||||
"use strict";
|
||||
|
||||
//console.log(event.data);
|
||||
|
||||
if (event.data === "close") {
|
||||
self.close();
|
||||
}
|
||||
});
|
57
webworker/worker.js
Normal file
57
webworker/worker.js
Normal file
@ -0,0 +1,57 @@
|
||||
importScripts("../library/three.js");
|
||||
importScripts("../library/clipper.js");
|
||||
importScripts("../src/utils.js");
|
||||
importScripts("../src/printer.js");
|
||||
importScripts("../src/paths.js");
|
||||
importScripts("../src/slicer.js");
|
||||
importScripts("../src/gcode.js");
|
||||
|
||||
var printer = new D3D.Printer();
|
||||
var slicer = new D3D.Slicer();
|
||||
slicer.onProgress = function (progress) {
|
||||
"use strict";
|
||||
|
||||
self.postMessage({
|
||||
"cmd": "PROGRESS",
|
||||
"progress": progress
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
self.addEventListener("message", function (event) {
|
||||
"use strict";
|
||||
|
||||
switch (event.data["cmd"]) {
|
||||
case "SET_MESH":
|
||||
|
||||
//hack...
|
||||
//because boundings loses functions when converting
|
||||
event.data["geometry"].boundingBox = event.data["geometry"].boundingSphere = null;
|
||||
|
||||
var geometry = new THREE.Geometry().fromBufferGeometry(event.data["geometry"]);
|
||||
var matrix = new THREE.Matrix4().fromArray(event.data["matrix"]);
|
||||
|
||||
slicer.setMesh(geometry, matrix);
|
||||
|
||||
break;
|
||||
|
||||
case "SET_SETTINGS":
|
||||
printer.updateConfig(event.data["USER_SETTINGS"]);
|
||||
printer.updateConfig(event.data["PRINTER_SETTINGS"]);
|
||||
break;
|
||||
|
||||
case "SLICE":
|
||||
var gcode = slicer.getGCode(printer);
|
||||
|
||||
self.postMessage({
|
||||
"cmd": "GCODE",
|
||||
"gcode": gcode
|
||||
});
|
||||
break;
|
||||
|
||||
case "CLOSE":
|
||||
self.close();
|
||||
break;
|
||||
|
||||
}
|
||||
});
|
74
webworker_benchmark.html
Normal file
74
webworker_benchmark.html
Normal file
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="library/benchmark.js"></script>
|
||||
<script src="library/three.js"></script>
|
||||
|
||||
<title>Doedel Drie Dee || Webworker Benchmark</title>
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var worker = new Worker('webworker/benchmark.js');
|
||||
var geometry = new THREE.BoxGeometry(10, 30, 10).clone();
|
||||
//var geometry = new THREE.TorusKnotGeometry(10, 3, 200, 200).clone();
|
||||
|
||||
new Benchmark.Suite().add('Buffer Geometry', function () {
|
||||
|
||||
var bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);
|
||||
|
||||
worker.postMessage(bufferGeometry);
|
||||
|
||||
//this happens in the worker
|
||||
var workerGeometry = new THREE.Geometry().fromBufferGeometry(bufferGeometry);
|
||||
workerGeometry.mergeVertices();
|
||||
|
||||
}).add('Buffer Geometry Transferrable Object', function () {
|
||||
|
||||
var bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);
|
||||
|
||||
var buffers = [];
|
||||
|
||||
for (var i = 0; i < bufferGeometry.attributesKeys.length; i ++) {
|
||||
var key = bufferGeometry.attributesKeys[i];
|
||||
buffers.push(bufferGeometry.attributes[key].array.buffer);
|
||||
}
|
||||
|
||||
worker.postMessage(bufferGeometry, buffers);
|
||||
|
||||
//this happens in the worker
|
||||
//this is redundant...
|
||||
//buffers are transferred to worker so the do not exist in this part of the script
|
||||
//[TEST NOT VIABLE]
|
||||
var workerGeometry = new THREE.Geometry().fromBufferGeometry(bufferGeometry);
|
||||
workerGeometry.mergeVertices();
|
||||
|
||||
}).add('Geometry JSON', function () {
|
||||
|
||||
var json = geometry.toJSON().data;
|
||||
worker.postMessage(json);
|
||||
|
||||
//worker.postMessage(geometry);
|
||||
|
||||
//this happens in the worker
|
||||
var loader = new THREE.JSONLoader();
|
||||
var workerGeometry = loader.parse(json).geometry;
|
||||
workerGeometry.mergeVertices();
|
||||
|
||||
}).on('cycle', function (event) {
|
||||
|
||||
document.body.innerHTML += "<p>" + String(event.target) + "</p>";
|
||||
|
||||
}).on('complete', function () {
|
||||
|
||||
document.body.innerHTML += "<p>" + 'Fastest is "' + this.filter('fastest').pluck('name') + '"' + "</p>";
|
||||
|
||||
}).run({
|
||||
'async': true
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
19
webworker_benchmark_resutaten.txt
Normal file
19
webworker_benchmark_resutaten.txt
Normal file
@ -0,0 +1,19 @@
|
||||
----------- RESULTATEN TORUS KNOT --------------
|
||||
|
||||
Buffer Geometry x 0.53 ops/sec ±134.70% (8 runs sampled)
|
||||
|
||||
Buffer Geometry Transferrable Object x 63.04 ops/sec ±2.19% (67 runs sampled)
|
||||
|
||||
Geometry JSON x 0.50 ops/sec ±6.55% (6 runs sampled)
|
||||
|
||||
Fastest is "Buffer Geometry Transferrable Object"
|
||||
|
||||
----------- RESULTATEN KUBUS --------------
|
||||
|
||||
Buffer Geometry x 5,360 ops/sec ±19.42% (85 runs sampled)
|
||||
|
||||
Buffer Geometry Transferrable Object x 1,535 ops/sec ±10.17% (35 runs sampled)
|
||||
|
||||
Geometry JSON x 3,831 ops/sec ±2.52% (82 runs sampled)
|
||||
|
||||
Fastest is "Buffer Geometry"
|
207
webworker_test.html
Normal file
207
webworker_test.html
Normal file
@ -0,0 +1,207 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<script src='library/jquery.js'></script>
|
||||
<script src='library/three.js'></script>
|
||||
<script src='library/stl_loader.js'></script>
|
||||
|
||||
<script src='src/utils.js'></script>
|
||||
<script src='src/box.js'></script>
|
||||
<script src='src/printer.js'></script>
|
||||
<script src='src/slicerworker.js'></script>
|
||||
|
||||
<title>Doedel Drie Dee || Webworker Test</title>
|
||||
<style>
|
||||
canvas {border: 1px solid black;}
|
||||
#progress {height: 20px; width: 200px; border: 1px solid black; overflow: hidden;}
|
||||
#progress_bar {height: 20px; background-color: lightblue; width: 0%;}
|
||||
.block {border: 1px solid black; width: 400px; height: 400px; display: inline-block;}
|
||||
#start_print, #download {display: none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<canvas id='3d-preview' height='400' width='400'></canvas>
|
||||
<div class='block'>
|
||||
<p>State: <span id='state'></span></p>
|
||||
<p>Bed Temp: <span id='bed_temp'></span></p>
|
||||
<p>Bed Target Temp: <span id='bed_target_temp'></span></p>
|
||||
<p>Nozzle Temp: <span id='nozzle_temp'></span></p>
|
||||
<p>Nozzle Target Temp: <span id='nozzle_target_temp'></span></p>
|
||||
<p>Current Line: <span id='current_line'></span></p>
|
||||
<p>Buffered Lines: <span id='buffered_lines'></span></p>
|
||||
<p>Total Lines: <span id='total_lines'></span></p>
|
||||
<p>Batches To Send: <span id='print_batches'></span></p>
|
||||
<div id='progress'><div id='progress_bar'></div></div>
|
||||
<button id="stop_print">Stop Print</button>
|
||||
<button id="start_print">Start Print</button>
|
||||
<button id="download">Download Gcode</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var USER_SETTINGS, PRINTER_SETTINGS, doodleBox, gcode, slicerWorker, printer;
|
||||
|
||||
function init () {
|
||||
'use strict';
|
||||
var scene = createScene();
|
||||
|
||||
var localIp = location.hash.substring(1);
|
||||
doodleBox = new D3D.Box(localIp);
|
||||
|
||||
doodleBox.onupdate = function (data) {
|
||||
document.getElementById('state').innerHTML = data.state;
|
||||
document.getElementById('bed_temp').innerHTML = data.bed;
|
||||
document.getElementById('bed_target_temp').innerHTML = data.bed_target;
|
||||
document.getElementById('nozzle_temp').innerHTML = data.hotend;
|
||||
document.getElementById('nozzle_target_temp').innerHTML = data.hotend_target;
|
||||
document.getElementById('current_line').innerHTML = data.current_line;
|
||||
document.getElementById('buffered_lines').innerHTML = data.buffered_lines;
|
||||
document.getElementById('total_lines').innerHTML = data.total_lines;
|
||||
document.getElementById('print_batches').innerHTML = doodleBox.printBatches.length;
|
||||
};
|
||||
|
||||
printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS['ultimaker2go']);
|
||||
|
||||
document.getElementById('stop_print').onclick = function () {
|
||||
doodleBox.stopPrint(printer);
|
||||
};
|
||||
|
||||
var slicer = new D3D.SlicerWorker();
|
||||
|
||||
slicer.setSettings(USER_SETTINGS, PRINTER_SETTINGS['ultimaker2go']);
|
||||
|
||||
var progressBar = document.getElementById('progress_bar');
|
||||
slicer.onprogress = function (progress) {
|
||||
progressBar.style.width = progress.procent * 100 + '%';
|
||||
};
|
||||
slicer.onfinish = function (_gcode) {
|
||||
gcode = _gcode;
|
||||
var startPrintButton = document.getElementById('start_print');
|
||||
var downloadButton = document.getElementById('download');
|
||||
|
||||
startPrintButton.style.display = 'initial';
|
||||
startPrintButton.onclick = function () {
|
||||
doodleBox.print(gcode);
|
||||
};
|
||||
|
||||
downloadButton.style.display = 'initial';
|
||||
downloadButton.onclick = function () {
|
||||
downloadFile("gcode.gcode", gcode.join('\n'));
|
||||
};
|
||||
};
|
||||
|
||||
var loader = new THREE.STLLoader();
|
||||
loader.load('models/robot.stl', function (geometry) {
|
||||
//var geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone();
|
||||
|
||||
var material = new THREE.MeshPhongMaterial({color: 0x00ff00, wireframe: false});
|
||||
//var material = new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true});
|
||||
var mesh = new THREE.Mesh(geometry, material);
|
||||
|
||||
mesh.rotation.x = -Math.PI/2;
|
||||
mesh.scale.x = mesh.scale.y = mesh.scale.z = 1;
|
||||
mesh.position.y = -0.1;
|
||||
mesh.position.x = 60;
|
||||
mesh.position.z = 60;
|
||||
|
||||
scene.add(mesh);
|
||||
|
||||
slicer.setMesh(mesh);
|
||||
slicer.slice();
|
||||
|
||||
slicer.close();
|
||||
});
|
||||
}
|
||||
|
||||
function createScene () {
|
||||
var scene = new THREE.Scene();
|
||||
|
||||
var renderer = new THREE.WebGLRenderer({canvas: document.getElementById('3d-preview'), antialias: true});
|
||||
renderer.setClearColor(0xffffff, 1);
|
||||
|
||||
var camera = new THREE.PerspectiveCamera(75, renderer.domElement.width/renderer.domElement.height, 1, 10000);
|
||||
scene.add(camera);
|
||||
|
||||
var light = new THREE.AmbientLight(0x404040);
|
||||
scene.add(light);
|
||||
|
||||
var directionalLight = new THREE.PointLight(0xffffff, 0.5);
|
||||
camera.add(directionalLight);
|
||||
|
||||
applyMouseControls(renderer, camera, new THREE.Vector3(50, 0, 50), 1000);
|
||||
|
||||
function applyMouseControls (renderer, camera, center, maxDistance) {
|
||||
var distance = 20;
|
||||
var rotX = 0;
|
||||
var rotY = 0;
|
||||
var moveCamera = false;
|
||||
|
||||
function updateCamera () {
|
||||
camera.position.set(
|
||||
Math.cos(rotY)*Math.sin(rotX)*distance,
|
||||
Math.sin(rotY)*distance,
|
||||
Math.cos(rotY)*Math.cos(rotX)*distance
|
||||
).add(center);
|
||||
camera.lookAt(center);
|
||||
}
|
||||
|
||||
$(renderer.domElement).on('mousedown', function (e) {
|
||||
moveCamera = true;
|
||||
}).on('wheel', function (e) {
|
||||
var event = e.originalEvent;
|
||||
|
||||
event.preventDefault();
|
||||
distance = THREE.Math.clamp(distance - event.wheelDelta, 1, maxDistance);
|
||||
|
||||
updateCamera();
|
||||
});
|
||||
|
||||
$(window).on('mouseup', function (e) {
|
||||
moveCamera = false;
|
||||
}).on('mousemove', function (e) {
|
||||
var event = e.originalEvent;
|
||||
|
||||
if (moveCamera === true) {
|
||||
rotX = (rotX - event.webkitMovementX/100) % (2*Math.PI);
|
||||
rotY = THREE.Math.clamp(rotY + event.webkitMovementY/100, -Math.PI/2, Math.PI/2);
|
||||
|
||||
updateCamera();
|
||||
}
|
||||
});
|
||||
|
||||
updateCamera();
|
||||
}
|
||||
|
||||
(function animate () {
|
||||
requestAnimationFrame(animate);
|
||||
renderer.render(scene, camera);
|
||||
})();
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var loadedItems = 0;
|
||||
function loaded () {
|
||||
loadedItems ++;
|
||||
if (loadedItems === 2) {
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
loadSettings('settings/user_settings.json', function (data) {
|
||||
USER_SETTINGS = data;
|
||||
loaded();
|
||||
});
|
||||
loadSettings('settings/printer_settings.json', function (data) {
|
||||
PRINTER_SETTINGS = data;
|
||||
loaded();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user