mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-11-22 13:37:58 +01:00
Merge branch 'develop'
This commit is contained in:
commit
a5384b3de1
23
.gitignore
vendored
23
.gitignore
vendored
@ -1,23 +1,8 @@
|
||||
|
||||
.DS_Store
|
||||
*.DS_Store
|
||||
|
||||
.DS_Store
|
||||
jspm_packages/*
|
||||
|
||||
src/.DS_Store
|
||||
node_modules/*
|
||||
|
||||
src/.DS_Store
|
||||
|
||||
src/library/.DS_Store
|
||||
|
||||
.DS_Store
|
||||
|
||||
src/script/.DS_Store
|
||||
|
||||
src/.DS_Store
|
||||
|
||||
bower_components/
|
||||
src/oldcode.js
|
||||
|
||||
test.html
|
||||
|
||||
print_manager.html
|
||||
bundle.js
|
||||
|
45
README.md
45
README.md
@ -1,32 +1,25 @@
|
||||
# Doodle3D-Slicer
|
||||
|
||||
The Doodle3D Slicer is designed for developers to make it easier to export 3d models to the Doodle3D WiFi-Box. The slicers includes a gcode slicer and a class designed for communication with the WiFi-Box. All the classes are in the D3D name space.
|
||||
|
||||
Three.js, Clipper.js and jQuery are required to run the Doodl3D slicer. All are included in the source.
|
||||
|
||||
This is an example of code.
|
||||
JavaScript gcode slicer, Intended to use with the Doodle3D WiFi-Box
|
||||
# Usage
|
||||
|
||||
```javascript
|
||||
var localIp = "192.168.5.1";
|
||||
var doodleBox = new D3D.Box(localIp);
|
||||
import * as THREE from 'three';
|
||||
import { defaultSettings, Slicer } from 'Doodle3D/Doodle3D-Slicer';
|
||||
|
||||
doodleBox.onload = function () {
|
||||
"use strict";
|
||||
|
||||
var printer = new D3D.Printer(printerSettings, userSettings);
|
||||
|
||||
var geometry = new THREE.BoxGeometry(20, 20, 20, 1, 1, 1);
|
||||
var material = new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true});
|
||||
var mesh = new THREE.Mesh(geometry, material);
|
||||
mesh.position.x = 100;
|
||||
mesh.position.z = 100;
|
||||
mesh.position.y = 10;
|
||||
|
||||
var slicer = new D3D.Slicer().setMesh(mesh);
|
||||
var gcode = slicer.getGcode(printer);
|
||||
|
||||
doodleBox.print(gcode);
|
||||
const settings = {
|
||||
...defaultSettings.base,
|
||||
...defaultSettings.material.pla,
|
||||
...defaultSettings.printer.ultimaker2go,
|
||||
...defaultSettings.quality.high
|
||||
};
|
||||
```
|
||||
|
||||
For more information see http://www.doodle3d.com/
|
||||
const geometry = new THREE.TorusGeometry(20, 10, 30, 30);
|
||||
|
||||
const slicer = new SLICER.Slicer();
|
||||
slicer.setGeometry(geometry);
|
||||
const gcode = await slicer.slice(settings)
|
||||
.progress(({ done, total, action }) => {
|
||||
const percentage = `${(done / total * 100).toFixed()}%`
|
||||
console.log(action, percentage);
|
||||
});
|
||||
```
|
||||
|
149
doodle.html
149
doodle.html
@ -1,149 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Doedel Drie Dee</title>
|
||||
<!--<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>-->
|
||||
<script src="library/jquery.js"></script>
|
||||
<script src="library/three.js"></script>
|
||||
|
||||
<script src="src/utils.js"></script>
|
||||
<script src="src/box.js"></script>
|
||||
<script src="src/printer.js"></script>
|
||||
<script src="src/slicer.js"></script>
|
||||
|
||||
<script src="gcode/testgcode.js"></script>
|
||||
<script src="gcode/easterbunny.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var localIp = location.hash.substring(1);
|
||||
var doodleBox, drawing;
|
||||
|
||||
$(document).ready(function () {
|
||||
"use strict";
|
||||
|
||||
doodleBox = new D3D.Box(localIp);
|
||||
|
||||
CAL.Scene.setCanvas(document.getElementById("canvas"));
|
||||
|
||||
var shape = new CAL.Shape({
|
||||
shapeColor: false,
|
||||
closePath: false,
|
||||
points: [
|
||||
new CAL.Vector(20, 180),
|
||||
new CAL.Vector(180, 100),
|
||||
new CAL.Vector(20, 80),
|
||||
new CAL.Vector(180, 60)
|
||||
]
|
||||
});
|
||||
CAL.Scene.add(shape);
|
||||
|
||||
drawing = new Drawing(shape);
|
||||
CAL.Scene.add(drawing);
|
||||
});
|
||||
|
||||
|
||||
function Drawing (shape) {
|
||||
this.shape = shape;
|
||||
|
||||
this.active = true;
|
||||
this.mouse = false;
|
||||
}
|
||||
Drawing.prototype.mouseDown = function (mouse) {
|
||||
this.mouse = mouse;
|
||||
};
|
||||
Drawing.prototype.mouseUp = function (mouse) {
|
||||
this.mouse = false;
|
||||
};
|
||||
Drawing.prototype.generateGcode = function () {
|
||||
var gcode = doodleBox.printer.getStartCode();
|
||||
|
||||
var extruder = 0.0;
|
||||
var points = this.shape.points;
|
||||
|
||||
var normalSpeed = doodleBox.printer["printer.speed"] * 60;
|
||||
var bottomSpeed = doodleBox.printer["printer.bottomLayerSpeed"] * 60;
|
||||
var firstLayerSlow = doodleBox.printer["printer.firstLayerSlow"] * 60;
|
||||
var bottomFlowRate = doodleBox.printer["printer.bottomFlowRate"];
|
||||
var travelSpeed = doodleBox.printer["printer.travelSpeed"] * 60;
|
||||
var filamentThickness = doodleBox.printer["printer.filamentThickness"];
|
||||
var wallThickness = doodleBox.printer["printer.wallThickness"];
|
||||
var screenToMillimeterScale = doodleBox.printer["printer.screenToMillimeterScale"];
|
||||
var layerHeight = doodleBox.printer["printer.layerHeight"];
|
||||
var useSubLayers = doodleBox.printer["printer.useSubLayers"];
|
||||
var enableTraveling = doodleBox.printer["printer.enableTraveling"];
|
||||
var retractionEnabled = doodleBox.printer["printer.retraction.enabled"];
|
||||
var retractionspeed = doodleBox.printer["printer.retraction.speed"] * 60;
|
||||
var retractionminDistance = doodleBox.printer["printer.retraction.minDistance"];
|
||||
var retractionamount = doodleBox.printer["printer.retraction.amount"];
|
||||
|
||||
var speed = bottomSpeed.toFixed(3);
|
||||
|
||||
for (var layer = 0; layer < 10; layer ++) {
|
||||
var lastPoint;
|
||||
|
||||
//turn on fan on layer 2
|
||||
if (layer === 2) {
|
||||
gcode.push("M106");
|
||||
speed = normalSpeed.toFixed(3);
|
||||
}
|
||||
|
||||
for (var i = 0; i < points.length; i ++) {
|
||||
var point = points[i];
|
||||
|
||||
var x = point.x.toFixed(3);
|
||||
var y = point.y.toFixed(3);
|
||||
var z = ((layer + 1) * layerHeight).toFixed(3);
|
||||
|
||||
if (i === 0) {
|
||||
if (layer >= 2 && retractionEnabled) {
|
||||
gcode.push("G0 E" + (extruder - retractionamount).toFixed(3) + " F" + (retractionspeed * 60).toFixed(3));
|
||||
}
|
||||
|
||||
gcode.push("G0 X" + x + " Y" + y + " Z" + z + " F" + travelSpeed);
|
||||
|
||||
if (layer >= 2 && retractionEnabled) {
|
||||
gcode.push("G0 E" + extruder.toFixed(3) + " F" + (retractionspeed * 60).toFixed(3));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var distance = point.subtract(lastPoint).length();
|
||||
|
||||
var flowRate = (layer < 2) ? bottomFlowRate : 1;
|
||||
|
||||
var filamentSurfaceArea = Math.pow((filamentThickness/2), 2) * Math.PI;
|
||||
|
||||
//extruder code from gcodeGenerating.js
|
||||
extruder += distance * wallThickness * layerHeight / filamentSurfaceArea * flowRate;
|
||||
|
||||
gcode.push("G1 X" + x + " Y" + y + " Z" + z + " F" + speed + " E" + extruder.toFixed(3));
|
||||
}
|
||||
|
||||
lastPoint = point;
|
||||
}
|
||||
}
|
||||
|
||||
gcode = gcode.concat(doodleBox.printer.getEndCode());
|
||||
return gcode;
|
||||
};
|
||||
Drawing.prototype.step = function (dt, group) {
|
||||
if (this.mouse) {
|
||||
this.shape.addPoint(new CAL.Vector(this.mouse.x, this.mouse.y));
|
||||
|
||||
group.drawCanvas = true;
|
||||
group.clearCanvas = true;
|
||||
}
|
||||
};
|
||||
|
||||
(function loop () {
|
||||
requestAnimFrame(loop);
|
||||
CAL.Scene.cycle();
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<canvas id="canvas" width="200" height="200"></canvas>
|
||||
|
||||
</body>
|
||||
</html>
|
128
example/SlicerViewer.js
Normal file
128
example/SlicerViewer.js
Normal file
@ -0,0 +1,128 @@
|
||||
import React from 'react';
|
||||
import { PRECISION } from '../src/constants.js';
|
||||
|
||||
export default class SlicerViewer extends React.Component {
|
||||
state = {
|
||||
layer: 0,
|
||||
render: {
|
||||
renderIntersectionPoints: false,
|
||||
renderShape1: false,
|
||||
renderShape2: true,
|
||||
renderOuterLine: true,
|
||||
renderInnerLine: true,
|
||||
renderFill: true
|
||||
}
|
||||
};
|
||||
|
||||
changeSlider = (event) => {
|
||||
this.setState({
|
||||
layer: parseInt(event.target.value)
|
||||
});
|
||||
};
|
||||
|
||||
onControl = (event) => {
|
||||
const section = event.target.value;
|
||||
this.setState({
|
||||
render: {
|
||||
...this.state.render,
|
||||
[section]: !this.state.render[section]
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { layer, render } = this.state;
|
||||
const { layerIntersectionPoints, settings, layerShapes, slices } = this.props;
|
||||
|
||||
const numLayers = settings.dimensionsZ / settings.layerHeight;
|
||||
|
||||
const intersectionPoints = layerIntersectionPoints[layer + 1];
|
||||
const shape = layerShapes[layer];
|
||||
const slice = slices[layer];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<svg viewBox={`-20 -20 ${settings.dimensionsX + 40} ${settings.dimensionsX + 40}`}>
|
||||
<rect
|
||||
width={settings.dimensionsX}
|
||||
height={settings.dimensionsY}
|
||||
fill="lightGrey"
|
||||
/>
|
||||
{render.renderIntersectionPoints && intersectionPoints.map(({ x, y }, i) => (
|
||||
<circle key={i} cx={x} cy={y} r="0.3"/>
|
||||
))}
|
||||
{render.renderShape1 && shape && shape.closedShapes.map((closedShape, i) => (
|
||||
<polygon
|
||||
key={i}
|
||||
points={closedShape.map(({ x, y }) => `${x} ${y}`).join(' ')}
|
||||
fill="rgba(255, 0, 0, 0.5)"
|
||||
/>
|
||||
))}
|
||||
{slice && slice.parts.map((slicePart, i) => (
|
||||
<g key={i}>
|
||||
{render.renderShape2 && <ClipperShapeSVG
|
||||
shape={slicePart.shape}
|
||||
scale={PRECISION}
|
||||
color="rgba(0, 0, 0, 0.5)"
|
||||
fill
|
||||
/>}
|
||||
{render.renderOuterLine && <ClipperShapeSVG
|
||||
shape={slicePart.outerLine}
|
||||
scale={1.0}
|
||||
color="blue"
|
||||
strokeWidth={settings.nozzleDiameter * 0.9}
|
||||
/>}
|
||||
{render.renderInnerLine && slicePart.innerLines.map((innerLine, i) => (
|
||||
<ClipperShapeSVG
|
||||
key={i}
|
||||
shape={innerLine}
|
||||
scale={1.0}
|
||||
color="red"
|
||||
strokeWidth={settings.nozzleDiameter * 0.9}
|
||||
/>
|
||||
))}
|
||||
{render.renderFill && <ClipperShapeSVG
|
||||
shape={slicePart.fill}
|
||||
scale={1.0}
|
||||
color="yellow"
|
||||
strokeWidth={settings.nozzleDiameter * 0.9}
|
||||
/>}
|
||||
</g>
|
||||
))}
|
||||
</svg>
|
||||
<div id="controls">
|
||||
<input onChange={this.changeSlider} value={layer} type="range" min="0" max={numLayers} />
|
||||
<p>Layer: {layer}</p>
|
||||
<p><label><input type="checkbox" value="renderIntersectionPoints" onChange={this.onControl} checked={render.renderIntersectionPoints} />Render Intersection Points</label></p>
|
||||
<p><label><input type="checkbox" value="renderShape1" onChange={this.onControl} checked={render.renderShape1} />Render Shape 1</label></p>
|
||||
<p><label><input type="checkbox" value="renderShape2" onChange={this.onControl} checked={render.renderShape2} />Render Shape 2</label></p>
|
||||
<p><label><input type="checkbox" value="renderOuterLine" onChange={this.onControl} checked={render.renderOuterLine} />Render Out Line</label></p>
|
||||
<p><label><input type="checkbox" value="renderInnerLine" onChange={this.onControl} checked={render.renderInnerLine} />Render Inner Lines</label></p>
|
||||
<p><label><input type="checkbox" value="renderFill" onChange={this.onControl} checked={render.renderFill} />Render Fill</label></p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ClipperShapeSVG extends React.Component {
|
||||
render() {
|
||||
const { shape, color = 'black', strokeWidth, scale, fill } = this.props;
|
||||
|
||||
const data = shape.paths.map(path => {
|
||||
const pathData = path.map(({ X, Y }, i) => `${i === 0 ? 'M' : 'L '}${X * scale} ${Y * scale}`);
|
||||
if (shape.closed) pathData.push('Z');
|
||||
return pathData.join(' ');
|
||||
}).join(' ');
|
||||
|
||||
return (
|
||||
<path
|
||||
d={data}
|
||||
strokeWidth={typeof strokeWidth === 'number' ? strokeWidth : 1.0}
|
||||
vectorEffect={typeof strokeWidth === 'number' ? 'none' : 'non-scaling-stroke'}
|
||||
fill={fill ? color : 'none'}
|
||||
stroke={!fill ? color : 'none'}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
54
example/generateRawData.js
Normal file
54
example/generateRawData.js
Normal file
@ -0,0 +1,54 @@
|
||||
import calculateLayersIntersections from 'src/sliceActions/calculateLayersIntersections.js';
|
||||
import createLines from 'src/sliceActions/createLines.js';
|
||||
import generateInfills from 'src/sliceActions/generateInfills.js';
|
||||
import generateInnerLines from 'src/sliceActions/generateInnerLines.js';
|
||||
import generateSupport from 'src/sliceActions/generateSupport.js';
|
||||
import intersectionsToShapes from 'src/sliceActions/intersectionsToShapes.js';
|
||||
import addBrim from 'src/sliceActions/addBrim.js';
|
||||
import optimizePaths from 'src/sliceActions/optimizePaths.js';
|
||||
import shapesToSlices from 'src/sliceActions/shapesToSlices.js';
|
||||
import slicesToGCode from 'src/sliceActions/slicesToGCode.js';
|
||||
import applyPrecision from 'src/sliceActions/applyPrecision.js';
|
||||
import removePrecision from 'src/sliceActions/removePrecision.js';
|
||||
|
||||
export default function generateRawData(geometry, settings) {
|
||||
const rawData = {};
|
||||
|
||||
const lines = createLines(geometry, settings);
|
||||
|
||||
const {
|
||||
layerIntersectionIndexes,
|
||||
layerIntersectionPoints
|
||||
} = calculateLayersIntersections(lines, settings);
|
||||
|
||||
rawData.layerIntersectionPoints = layerIntersectionPoints
|
||||
.map(intersectionPoints => intersectionPoints.map(intersectionPoint => intersectionPoint.clone()));
|
||||
|
||||
const layerShapes = intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings);
|
||||
|
||||
rawData.layerShapes = layerShapes
|
||||
.map(({ closedShapes, openShapes }) => ({
|
||||
closedShapes: closedShapes.map(closedShape => closedShape.map(vector => vector.clone())),
|
||||
openShapes: openShapes.map(openShape => openShape.map(vector => vector.clone()))
|
||||
}));
|
||||
|
||||
|
||||
applyPrecision(layerShapes);
|
||||
|
||||
const slices = shapesToSlices(layerShapes, settings);
|
||||
|
||||
generateInnerLines(slices, settings);
|
||||
generateInfills(slices, settings);
|
||||
generateSupport(slices, settings);
|
||||
addBrim(slices, settings);
|
||||
optimizePaths(slices, settings);
|
||||
removePrecision(slices);
|
||||
|
||||
rawData.slices = slices;
|
||||
|
||||
const gcode = slicesToGCode(slices, settings);
|
||||
|
||||
rawData.gcode = gcode;
|
||||
|
||||
return rawData;
|
||||
}
|
11
example/index.html
Normal file
11
example/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doodle3D Slicer</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p><a href="./viewer.html">Viewer</a></p>
|
||||
<p><a href="./save.html">Save</a></p>
|
||||
</body>
|
||||
</html>
|
21
example/main.css
Normal file
21
example/main.css
Normal file
@ -0,0 +1,21 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#container, svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
svg, #controls {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
input[type=range] {
|
||||
width: 100%;
|
||||
}
|
1
example/models/airplane.json
Normal file
1
example/models/airplane.json
Normal file
File diff suppressed because one or more lines are too long
19
example/save.html
Normal file
19
example/save.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<title>Doodle3D Slicer - Save</title>
|
||||
|
||||
<script type="text/javascript" src="../jspm_packages/system.js"></script>
|
||||
<script type="text/javascript" src="../jspm.config.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
System.import('./save.js');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
27
example/save.js
Normal file
27
example/save.js
Normal file
@ -0,0 +1,27 @@
|
||||
import * as THREE from 'three';
|
||||
import { defaultSettings, Slicer } from 'src/index.js';
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
const settings = {
|
||||
...defaultSettings.base,
|
||||
...defaultSettings.material.pla,
|
||||
...defaultSettings.printer.ultimaker2go,
|
||||
...defaultSettings.quality.high
|
||||
};
|
||||
|
||||
const jsonLoader = new THREE.JSONLoader();
|
||||
jsonLoader.load('models/airplane.json', async geometry => {
|
||||
geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI / -2));
|
||||
geometry.applyMatrix(new THREE.Matrix4().setPosition(new THREE.Vector3(50, -0.1, 50)));
|
||||
geometry.computeFaceNormals();
|
||||
|
||||
const slicer = new Slicer().setGeometry(geometry);
|
||||
const gcode = await slicer.slice(settings)
|
||||
.progress(({ done, total, action }) => {
|
||||
const percentage = `${(done / total * 100).toFixed()}%`
|
||||
document.write(`<p>${action}, ${percentage}</p>`);
|
||||
});
|
||||
|
||||
const file = new File([gcode], 'gcode.gcode', { type: 'text/plain' });
|
||||
saveAs(file);
|
||||
});
|
55582
example/stl/Airplane.stl
Normal file
55582
example/stl/Airplane.stl
Normal file
File diff suppressed because it is too large
Load Diff
94222
example/stl/Rocket.stl
Normal file
94222
example/stl/Rocket.stl
Normal file
File diff suppressed because it is too large
Load Diff
BIN
example/stl/castle.stl
Normal file
BIN
example/stl/castle.stl
Normal file
Binary file not shown.
36906
example/stl/traktor.stl
Normal file
36906
example/stl/traktor.stl
Normal file
File diff suppressed because it is too large
Load Diff
29
example/viewer.html
Normal file
29
example/viewer.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<title>Doodle3D Slicer - Viewer</title>
|
||||
|
||||
<style>
|
||||
#gcode {
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript" src="../jspm_packages/system.js"></script>
|
||||
<script type="text/javascript" src="../jspm.config.js"></script>
|
||||
|
||||
<link href="main.css" rel="stylesheet"/>
|
||||
|
||||
<script type="text/javascript">
|
||||
System.import('example/viewer.js');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="container"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
35
example/viewer.js
Normal file
35
example/viewer.js
Normal file
@ -0,0 +1,35 @@
|
||||
import 'three.js';
|
||||
import 'three.js/loaders/STLLoader';
|
||||
import React from 'react';
|
||||
import ReactDOM, { render } from 'react-dom';
|
||||
import * as SLICER from 'src/index.js';
|
||||
import generateRawData from './generateRawData.js';
|
||||
import SlicerViewer from './SlicerViewer.js';
|
||||
|
||||
const settings = new SLICER.Settings({
|
||||
...SLICER.printerSettings['ultimaker2go'],
|
||||
...SLICER.userSettings
|
||||
});
|
||||
|
||||
const stlLoader = new THREE.STLLoader();
|
||||
stlLoader.load('stl/Airplane.stl', (geometry) => {
|
||||
geometry = new THREE.Geometry().fromBufferGeometry(geometry);
|
||||
|
||||
geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI / -2));
|
||||
geometry.applyMatrix(new THREE.Matrix4().setPosition(new THREE.Vector3(50, -0.1, 50)));
|
||||
// geometry.applyMatrix(new THREE.Matrix4().scale(0.8));
|
||||
geometry.mergeVertices();
|
||||
geometry.computeFaceNormals();
|
||||
|
||||
const rawData = generateRawData(geometry, settings);
|
||||
|
||||
render(
|
||||
<SlicerViewer
|
||||
layerIntersectionPoints={rawData.layerIntersectionPoints}
|
||||
layerShapes={rawData.layerShapes}
|
||||
slices={rawData.slices}
|
||||
settings={settings}
|
||||
/>,
|
||||
document.getElementById('container')
|
||||
);
|
||||
});
|
172520
gcode/easterbunny.js
172520
gcode/easterbunny.js
File diff suppressed because it is too large
Load Diff
78309
gcode/testgcode.js
78309
gcode/testgcode.js
File diff suppressed because it is too large
Load Diff
83
index.html
83
index.html
@ -1,83 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Doedel Drie Dee</title>
|
||||
<script src="library/jquery.js"></script>
|
||||
<script src="library/three.js"></script>
|
||||
<script src="src/utils.js"></script>
|
||||
<script src="src/box.js"></script>
|
||||
<script src="src/printer.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var api = "http://connect.doodle3d.com/api/";
|
||||
var printers = [];
|
||||
|
||||
$(document).ready(function () {
|
||||
"use strict";
|
||||
|
||||
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({
|
||||
name: "wired box",
|
||||
d3dbox: new D3D.Box("192.168.5.1")
|
||||
});
|
||||
*/
|
||||
|
||||
getAPI(api + "list.php", function (boxes) {
|
||||
for (var i = 0; i < boxes.length; i ++) {
|
||||
var box = boxes[i];
|
||||
|
||||
/*
|
||||
printers.push({
|
||||
name: box.wifiboxid,
|
||||
d3dbox: new D3D.Box(box.localip)
|
||||
});
|
||||
*/
|
||||
|
||||
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>");
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Doodle</p>
|
||||
<ul id="printers-doodle"></ul>
|
||||
|
||||
<p>Slice Test</p>
|
||||
<ul id="printers-slicetest"></ul>
|
||||
|
||||
<p>Webworkers</p>
|
||||
<ul id="printers-webworker"></ul>
|
||||
|
||||
<!--
|
||||
<table>
|
||||
<tr>
|
||||
<th>localip</th>
|
||||
<th>wifiboxid</th>
|
||||
<th>date</th>
|
||||
</tr>
|
||||
<tr style="display: none">
|
||||
<td>localip</td>
|
||||
<td>wifiboxid</td>
|
||||
<td>date</td>
|
||||
</tr>
|
||||
</table>
|
||||
-->
|
||||
</body>
|
||||
</html>
|
479
jspm.config.js
Normal file
479
jspm.config.js
Normal file
@ -0,0 +1,479 @@
|
||||
SystemJS.config({
|
||||
paths: {
|
||||
"github:": "jspm_packages/github/",
|
||||
"npm:": "jspm_packages/npm/",
|
||||
"example/": "example/",
|
||||
"slicer/": "src/"
|
||||
},
|
||||
browserConfig: {
|
||||
"baseURL": "/"
|
||||
},
|
||||
devConfig: {
|
||||
"map": {
|
||||
"babel-runtime": "npm:babel-runtime@5.8.38",
|
||||
"core-js": "npm:core-js@1.2.7",
|
||||
"plugin-babel": "npm:systemjs-plugin-babel@0.0.12",
|
||||
"react": "npm:react@15.3.2",
|
||||
"domain": "github:jspm/nodelibs-domain@0.2.0-alpha",
|
||||
"zlib": "github:jspm/nodelibs-zlib@0.2.0-alpha",
|
||||
"https": "github:jspm/nodelibs-https@0.2.0-alpha",
|
||||
"react-dom": "npm:react-dom@15.3.2",
|
||||
"babel-plugin-transform-react-jsx": "npm:babel-plugin-transform-react-jsx@6.8.0",
|
||||
"file-saver": "npm:file-saver@1.3.3"
|
||||
},
|
||||
"packages": {
|
||||
"npm:babel-runtime@5.8.38": {
|
||||
"map": {}
|
||||
},
|
||||
"npm:react@15.3.2": {
|
||||
"map": {
|
||||
"object-assign": "npm:object-assign@4.1.0",
|
||||
"loose-envify": "npm:loose-envify@1.2.0",
|
||||
"fbjs": "npm:fbjs@0.8.5"
|
||||
}
|
||||
},
|
||||
"npm:fbjs@0.8.5": {
|
||||
"map": {
|
||||
"loose-envify": "npm:loose-envify@1.2.0",
|
||||
"object-assign": "npm:object-assign@4.1.0",
|
||||
"promise": "npm:promise@7.1.1",
|
||||
"isomorphic-fetch": "npm:isomorphic-fetch@2.2.1",
|
||||
"ua-parser-js": "npm:ua-parser-js@0.7.10",
|
||||
"immutable": "npm:immutable@3.8.1",
|
||||
"core-js": "npm:core-js@1.2.7"
|
||||
}
|
||||
},
|
||||
"npm:loose-envify@1.2.0": {
|
||||
"map": {
|
||||
"js-tokens": "npm:js-tokens@1.0.3"
|
||||
}
|
||||
},
|
||||
"npm:promise@7.1.1": {
|
||||
"map": {
|
||||
"asap": "npm:asap@2.0.5"
|
||||
}
|
||||
},
|
||||
"npm:isomorphic-fetch@2.2.1": {
|
||||
"map": {
|
||||
"whatwg-fetch": "npm:whatwg-fetch@1.0.0",
|
||||
"node-fetch": "npm:node-fetch@1.6.3"
|
||||
}
|
||||
},
|
||||
"npm:node-fetch@1.6.3": {
|
||||
"map": {
|
||||
"encoding": "npm:encoding@0.1.12",
|
||||
"is-stream": "npm:is-stream@1.1.0"
|
||||
}
|
||||
},
|
||||
"npm:encoding@0.1.12": {
|
||||
"map": {
|
||||
"iconv-lite": "npm:iconv-lite@0.4.13"
|
||||
}
|
||||
},
|
||||
"npm:browserify-zlib@0.1.4": {
|
||||
"map": {
|
||||
"readable-stream": "npm:readable-stream@2.1.5",
|
||||
"pako": "npm:pako@0.2.9"
|
||||
}
|
||||
},
|
||||
"npm:babel-plugin-transform-react-jsx@6.8.0": {
|
||||
"map": {
|
||||
"babel-helper-builder-react-jsx": "npm:babel-helper-builder-react-jsx@6.9.0",
|
||||
"babel-plugin-syntax-jsx": "npm:babel-plugin-syntax-jsx@6.13.0",
|
||||
"babel-runtime": "npm:babel-runtime@6.11.6"
|
||||
}
|
||||
},
|
||||
"npm:babel-helper-builder-react-jsx@6.9.0": {
|
||||
"map": {
|
||||
"babel-runtime": "npm:babel-runtime@6.11.6",
|
||||
"esutils": "npm:esutils@2.0.2",
|
||||
"babel-types": "npm:babel-types@6.16.0",
|
||||
"lodash": "npm:lodash@4.16.4"
|
||||
}
|
||||
},
|
||||
"npm:babel-runtime@6.11.6": {
|
||||
"map": {
|
||||
"core-js": "npm:core-js@2.4.1",
|
||||
"regenerator-runtime": "npm:regenerator-runtime@0.9.5"
|
||||
}
|
||||
},
|
||||
"npm:babel-types@6.16.0": {
|
||||
"map": {
|
||||
"lodash": "npm:lodash@4.16.4",
|
||||
"babel-runtime": "npm:babel-runtime@6.11.6",
|
||||
"esutils": "npm:esutils@2.0.2",
|
||||
"to-fast-properties": "npm:to-fast-properties@1.0.2"
|
||||
}
|
||||
},
|
||||
"github:jspm/nodelibs-zlib@0.2.0-alpha": {
|
||||
"map": {
|
||||
"zlib-browserify": "npm:browserify-zlib@0.1.4"
|
||||
}
|
||||
},
|
||||
"github:jspm/nodelibs-domain@0.2.0-alpha": {
|
||||
"map": {
|
||||
"domain-browserify": "npm:domain-browser@1.1.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
transpiler: "plugin-babel",
|
||||
packages: {
|
||||
"slicer": {
|
||||
"main": "index.js"
|
||||
},
|
||||
"example": {
|
||||
"main": "example/index.js",
|
||||
"format": "esm",
|
||||
"meta": {
|
||||
"*.js": {
|
||||
"loader": "plugin-babel",
|
||||
"babelOptions": {
|
||||
"stage1": true,
|
||||
"plugins": [
|
||||
"babel-plugin-transform-react-jsx"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
map: {
|
||||
"babel": "npm:babel-core@5.8.38"
|
||||
}
|
||||
});
|
||||
|
||||
SystemJS.config({
|
||||
packageConfigPaths: [
|
||||
"npm:@*/*.json",
|
||||
"npm:*.json",
|
||||
"github:*/*.json"
|
||||
],
|
||||
map: {
|
||||
"three": "npm:three@0.83.0",
|
||||
"progress-promise": "npm:progress-promise@0.0.6",
|
||||
"text": "github:systemjs/plugin-text@0.0.11",
|
||||
"js-yaml": "npm:js-yaml@3.9.0",
|
||||
"clipper-js": "github:Doodle3D/clipper-js@1.0.2",
|
||||
"assert": "github:jspm/nodelibs-assert@0.2.0-alpha",
|
||||
"buffer": "github:jspm/nodelibs-buffer@0.2.0-alpha",
|
||||
"child_process": "github:jspm/nodelibs-child_process@0.2.0-alpha",
|
||||
"constants": "github:jspm/nodelibs-constants@0.2.0-alpha",
|
||||
"crypto": "github:jspm/nodelibs-crypto@0.2.0-alpha",
|
||||
"events": "github:jspm/nodelibs-events@0.2.2",
|
||||
"fs": "github:jspm/nodelibs-fs@0.2.0-alpha",
|
||||
"http": "github:jspm/nodelibs-http@0.2.0-alpha",
|
||||
"json": "github:systemjs/plugin-json@0.1.2",
|
||||
"Doodle3D/clipper-js": "github:Doodle3D/clipper-js@master",
|
||||
"module": "npm:jspm-nodelibs-module@0.2.0",
|
||||
"os": "github:jspm/nodelibs-os@0.2.2",
|
||||
"path": "github:jspm/nodelibs-path@0.2.3",
|
||||
"process": "github:jspm/nodelibs-process@0.2.0-alpha",
|
||||
"stream": "github:jspm/nodelibs-stream@0.2.0-alpha",
|
||||
"string_decoder": "github:jspm/nodelibs-string_decoder@0.2.0-alpha",
|
||||
"tty": "npm:jspm-nodelibs-tty@0.2.0",
|
||||
"url": "github:jspm/nodelibs-url@0.2.0-alpha",
|
||||
"util": "github:jspm/nodelibs-util@0.2.0-alpha",
|
||||
"vm": "github:jspm/nodelibs-vm@0.2.0-alpha",
|
||||
"worker": "github:casperlamboo/plugin-worker@master"
|
||||
},
|
||||
packages: {
|
||||
"github:Doodle3D/clipper-js@master": {
|
||||
"map": {
|
||||
"clipper-lib": "npm:clipper-lib@1.0.0"
|
||||
}
|
||||
},
|
||||
"npm:clipper-lib@1.0.0": {
|
||||
"map": {}
|
||||
},
|
||||
"npm:stream-browserify@2.0.1": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"readable-stream": "npm:readable-stream@2.3.3"
|
||||
}
|
||||
},
|
||||
"npm:buffer@4.9.1": {
|
||||
"map": {
|
||||
"base64-js": "npm:base64-js@1.2.1",
|
||||
"isarray": "npm:isarray@1.0.0",
|
||||
"ieee754": "npm:ieee754@1.1.8"
|
||||
}
|
||||
},
|
||||
"npm:url@0.11.0": {
|
||||
"map": {
|
||||
"querystring": "npm:querystring@0.2.0",
|
||||
"punycode": "npm:punycode@1.3.2"
|
||||
}
|
||||
},
|
||||
"npm:readable-stream@2.1.5": {
|
||||
"map": {
|
||||
"string_decoder": "npm:string_decoder@0.10.31",
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"isarray": "npm:isarray@1.0.0",
|
||||
"buffer-shims": "npm:buffer-shims@1.0.0",
|
||||
"core-util-is": "npm:core-util-is@1.0.2",
|
||||
"process-nextick-args": "npm:process-nextick-args@1.0.7",
|
||||
"util-deprecate": "npm:util-deprecate@1.0.2"
|
||||
}
|
||||
},
|
||||
"npm:public-encrypt@4.0.0": {
|
||||
"map": {
|
||||
"randombytes": "npm:randombytes@2.0.5",
|
||||
"create-hash": "npm:create-hash@1.1.3",
|
||||
"parse-asn1": "npm:parse-asn1@5.1.0",
|
||||
"bn.js": "npm:bn.js@4.11.7",
|
||||
"browserify-rsa": "npm:browserify-rsa@4.0.1"
|
||||
}
|
||||
},
|
||||
"npm:diffie-hellman@5.0.2": {
|
||||
"map": {
|
||||
"randombytes": "npm:randombytes@2.0.5",
|
||||
"bn.js": "npm:bn.js@4.11.7",
|
||||
"miller-rabin": "npm:miller-rabin@4.0.0"
|
||||
}
|
||||
},
|
||||
"npm:browserify-cipher@1.0.0": {
|
||||
"map": {
|
||||
"browserify-des": "npm:browserify-des@1.0.0",
|
||||
"evp_bytestokey": "npm:evp_bytestokey@1.0.0",
|
||||
"browserify-aes": "npm:browserify-aes@1.0.6"
|
||||
}
|
||||
},
|
||||
"npm:create-ecdh@4.0.0": {
|
||||
"map": {
|
||||
"elliptic": "npm:elliptic@6.4.0",
|
||||
"bn.js": "npm:bn.js@4.11.7"
|
||||
}
|
||||
},
|
||||
"npm:browserify-des@1.0.0": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"cipher-base": "npm:cipher-base@1.0.4",
|
||||
"des.js": "npm:des.js@1.0.0"
|
||||
}
|
||||
},
|
||||
"npm:evp_bytestokey@1.0.0": {
|
||||
"map": {
|
||||
"create-hash": "npm:create-hash@1.1.3"
|
||||
}
|
||||
},
|
||||
"npm:browserify-aes@1.0.6": {
|
||||
"map": {
|
||||
"create-hash": "npm:create-hash@1.1.3",
|
||||
"evp_bytestokey": "npm:evp_bytestokey@1.0.0",
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"cipher-base": "npm:cipher-base@1.0.4",
|
||||
"buffer-xor": "npm:buffer-xor@1.0.3"
|
||||
}
|
||||
},
|
||||
"npm:browserify-rsa@4.0.1": {
|
||||
"map": {
|
||||
"bn.js": "npm:bn.js@4.11.7",
|
||||
"randombytes": "npm:randombytes@2.0.5"
|
||||
}
|
||||
},
|
||||
"npm:miller-rabin@4.0.0": {
|
||||
"map": {
|
||||
"bn.js": "npm:bn.js@4.11.7",
|
||||
"brorand": "npm:brorand@1.1.0"
|
||||
}
|
||||
},
|
||||
"npm:des.js@1.0.0": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"minimalistic-assert": "npm:minimalistic-assert@1.0.0"
|
||||
}
|
||||
},
|
||||
"npm:stream-http@2.4.0": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"readable-stream": "npm:readable-stream@2.1.5",
|
||||
"to-arraybuffer": "npm:to-arraybuffer@1.0.1",
|
||||
"builtin-status-codes": "npm:builtin-status-codes@2.0.0",
|
||||
"xtend": "npm:xtend@4.0.1"
|
||||
}
|
||||
},
|
||||
"github:Doodle3D/clipper-js@1.0.2": {
|
||||
"map": {
|
||||
"Breush/clipper-lib": "github:Breush/clipper-lib@patch-1",
|
||||
"clipper-lib": "npm:clipper-lib@6.2.1"
|
||||
}
|
||||
},
|
||||
"npm:js-yaml@3.9.0": {
|
||||
"map": {
|
||||
"argparse": "npm:argparse@1.0.9",
|
||||
"esprima": "npm:esprima@4.0.0"
|
||||
}
|
||||
},
|
||||
"npm:argparse@1.0.9": {
|
||||
"map": {
|
||||
"sprintf-js": "npm:sprintf-js@1.0.3"
|
||||
}
|
||||
},
|
||||
"github:jspm/nodelibs-buffer@0.2.0-alpha": {
|
||||
"map": {
|
||||
"buffer-browserify": "npm:buffer@4.9.1"
|
||||
}
|
||||
},
|
||||
"github:jspm/nodelibs-crypto@0.2.0-alpha": {
|
||||
"map": {
|
||||
"crypto-browserify": "npm:crypto-browserify@3.11.1"
|
||||
}
|
||||
},
|
||||
"npm:crypto-browserify@3.11.1": {
|
||||
"map": {
|
||||
"browserify-cipher": "npm:browserify-cipher@1.0.0",
|
||||
"browserify-sign": "npm:browserify-sign@4.0.4",
|
||||
"create-ecdh": "npm:create-ecdh@4.0.0",
|
||||
"create-hash": "npm:create-hash@1.1.3",
|
||||
"create-hmac": "npm:create-hmac@1.1.6",
|
||||
"diffie-hellman": "npm:diffie-hellman@5.0.2",
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"pbkdf2": "npm:pbkdf2@3.0.12",
|
||||
"public-encrypt": "npm:public-encrypt@4.0.0",
|
||||
"randombytes": "npm:randombytes@2.0.5"
|
||||
}
|
||||
},
|
||||
"npm:browserify-sign@4.0.4": {
|
||||
"map": {
|
||||
"create-hash": "npm:create-hash@1.1.3",
|
||||
"create-hmac": "npm:create-hmac@1.1.6",
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"elliptic": "npm:elliptic@6.4.0",
|
||||
"bn.js": "npm:bn.js@4.11.7",
|
||||
"parse-asn1": "npm:parse-asn1@5.1.0",
|
||||
"browserify-rsa": "npm:browserify-rsa@4.0.1"
|
||||
}
|
||||
},
|
||||
"npm:create-hash@1.1.3": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"ripemd160": "npm:ripemd160@2.0.1",
|
||||
"sha.js": "npm:sha.js@2.4.8",
|
||||
"cipher-base": "npm:cipher-base@1.0.4"
|
||||
}
|
||||
},
|
||||
"npm:create-hmac@1.1.6": {
|
||||
"map": {
|
||||
"create-hash": "npm:create-hash@1.1.3",
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"ripemd160": "npm:ripemd160@2.0.1",
|
||||
"safe-buffer": "npm:safe-buffer@5.1.1",
|
||||
"sha.js": "npm:sha.js@2.4.8",
|
||||
"cipher-base": "npm:cipher-base@1.0.4"
|
||||
}
|
||||
},
|
||||
"npm:randombytes@2.0.5": {
|
||||
"map": {
|
||||
"safe-buffer": "npm:safe-buffer@5.1.1"
|
||||
}
|
||||
},
|
||||
"npm:pbkdf2@3.0.12": {
|
||||
"map": {
|
||||
"create-hmac": "npm:create-hmac@1.1.6",
|
||||
"ripemd160": "npm:ripemd160@2.0.1",
|
||||
"safe-buffer": "npm:safe-buffer@5.1.1",
|
||||
"sha.js": "npm:sha.js@2.4.8",
|
||||
"create-hash": "npm:create-hash@1.1.3"
|
||||
}
|
||||
},
|
||||
"npm:ripemd160@2.0.1": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"hash-base": "npm:hash-base@2.0.2"
|
||||
}
|
||||
},
|
||||
"npm:sha.js@2.4.8": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3"
|
||||
}
|
||||
},
|
||||
"npm:elliptic@6.4.0": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"bn.js": "npm:bn.js@4.11.7",
|
||||
"hmac-drbg": "npm:hmac-drbg@1.0.1",
|
||||
"hash.js": "npm:hash.js@1.1.3",
|
||||
"brorand": "npm:brorand@1.1.0",
|
||||
"minimalistic-crypto-utils": "npm:minimalistic-crypto-utils@1.0.1",
|
||||
"minimalistic-assert": "npm:minimalistic-assert@1.0.0"
|
||||
}
|
||||
},
|
||||
"npm:parse-asn1@5.1.0": {
|
||||
"map": {
|
||||
"browserify-aes": "npm:browserify-aes@1.0.6",
|
||||
"create-hash": "npm:create-hash@1.1.3",
|
||||
"evp_bytestokey": "npm:evp_bytestokey@1.0.0",
|
||||
"pbkdf2": "npm:pbkdf2@3.0.12",
|
||||
"asn1.js": "npm:asn1.js@4.9.1"
|
||||
}
|
||||
},
|
||||
"npm:cipher-base@1.0.4": {
|
||||
"map": {
|
||||
"safe-buffer": "npm:safe-buffer@5.1.1",
|
||||
"inherits": "npm:inherits@2.0.3"
|
||||
}
|
||||
},
|
||||
"npm:hash-base@2.0.2": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3"
|
||||
}
|
||||
},
|
||||
"npm:hmac-drbg@1.0.1": {
|
||||
"map": {
|
||||
"hash.js": "npm:hash.js@1.1.3",
|
||||
"minimalistic-assert": "npm:minimalistic-assert@1.0.0",
|
||||
"minimalistic-crypto-utils": "npm:minimalistic-crypto-utils@1.0.1"
|
||||
}
|
||||
},
|
||||
"npm:hash.js@1.1.3": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"minimalistic-assert": "npm:minimalistic-assert@1.0.0"
|
||||
}
|
||||
},
|
||||
"npm:asn1.js@4.9.1": {
|
||||
"map": {
|
||||
"bn.js": "npm:bn.js@4.11.7",
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"minimalistic-assert": "npm:minimalistic-assert@1.0.0"
|
||||
}
|
||||
},
|
||||
"github:jspm/nodelibs-stream@0.2.0-alpha": {
|
||||
"map": {
|
||||
"stream-browserify": "npm:stream-browserify@2.0.1"
|
||||
}
|
||||
},
|
||||
"npm:readable-stream@2.3.3": {
|
||||
"map": {
|
||||
"inherits": "npm:inherits@2.0.3",
|
||||
"isarray": "npm:isarray@1.0.0",
|
||||
"safe-buffer": "npm:safe-buffer@5.1.1",
|
||||
"string_decoder": "npm:string_decoder@1.0.3",
|
||||
"util-deprecate": "npm:util-deprecate@1.0.2",
|
||||
"process-nextick-args": "npm:process-nextick-args@1.0.7",
|
||||
"core-util-is": "npm:core-util-is@1.0.2"
|
||||
}
|
||||
},
|
||||
"npm:string_decoder@1.0.3": {
|
||||
"map": {
|
||||
"safe-buffer": "npm:safe-buffer@5.1.1"
|
||||
}
|
||||
},
|
||||
"github:jspm/nodelibs-string_decoder@0.2.0-alpha": {
|
||||
"map": {
|
||||
"string_decoder-browserify": "npm:string_decoder@0.10.31"
|
||||
}
|
||||
},
|
||||
"github:jspm/nodelibs-http@0.2.0-alpha": {
|
||||
"map": {
|
||||
"http-browserify": "npm:stream-http@2.4.0"
|
||||
}
|
||||
},
|
||||
"github:jspm/nodelibs-url@0.2.0-alpha": {
|
||||
"map": {
|
||||
"url-browserify": "npm:url@0.11.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
3919
library/benchmark.js
3919
library/benchmark.js
File diff suppressed because it is too large
Load Diff
2329
library/cal.js
2329
library/cal.js
File diff suppressed because it is too large
Load Diff
6985
library/clipper.js
6985
library/clipper.js
File diff suppressed because it is too large
Load Diff
4
library/jquery.js
vendored
4
library/jquery.js
vendored
File diff suppressed because one or more lines are too long
@ -1,433 +0,0 @@
|
||||
/**
|
||||
* @author aleeper / http://adamleeper.com/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author gero3 / https://github.com/gero3
|
||||
*
|
||||
* Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs.
|
||||
*
|
||||
* Supports both binary and ASCII encoded files, with automatic detection of type.
|
||||
*
|
||||
* Limitations:
|
||||
* Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL).
|
||||
* There is perhaps some question as to how valid it is to always assume little-endian-ness.
|
||||
* ASCII decoding assumes file is UTF-8. Seems to work for the examples...
|
||||
*
|
||||
* Usage:
|
||||
* var loader = new THREE.STLLoader();
|
||||
* loader.load( './models/stl/slotted_disk.stl', function ( geometry ) {
|
||||
* scene.add( new THREE.Mesh( geometry ) );
|
||||
* });
|
||||
*
|
||||
* For binary STLs geometry might contain colors for vertices. To use it:
|
||||
* // use the same code to load STL as above
|
||||
* if (geometry.hasColors) {
|
||||
* material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: THREE.VertexColors });
|
||||
* } else { .... }
|
||||
* var mesh = new THREE.Mesh( geometry, material );
|
||||
*/
|
||||
|
||||
|
||||
THREE.STLLoader = function ( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
|
||||
|
||||
};
|
||||
|
||||
THREE.STLLoader.prototype = {
|
||||
|
||||
constructor: THREE.STLLoader,
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new THREE.XHRLoader( scope.manager );
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
loader.setResponseType('arraybuffer');
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( text ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
parse: function ( data ) {
|
||||
|
||||
var isBinary = function () {
|
||||
|
||||
var expect, face_size, n_faces, reader;
|
||||
reader = new DataView( binData );
|
||||
face_size = (32 / 8 * 3) + ((32 / 8 * 3) * 3) + (16 / 8);
|
||||
n_faces = reader.getUint32(80, true);
|
||||
expect = 80 + (32 / 8) + (n_faces * face_size);
|
||||
|
||||
if ( expect === reader.byteLength ) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// some binary files will have different size from expected,
|
||||
// checking characters higher than ASCII to confirm is binary
|
||||
var fileLength = reader.byteLength;
|
||||
for ( var index = 0; index < fileLength; index ++ ) {
|
||||
|
||||
if ( reader.getUint8(index, false) > 127 ) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
var binData = this.ensureBinary( data );
|
||||
|
||||
return isBinary()
|
||||
? this.parseBinary( binData )
|
||||
: this.parseASCII( this.ensureString( data ) );
|
||||
|
||||
},
|
||||
|
||||
parseBinary: function ( data ) {
|
||||
|
||||
var reader = new DataView( data );
|
||||
var faces = reader.getUint32( 80, true );
|
||||
|
||||
var r, g, b, hasColors = false, colors;
|
||||
var defaultR, defaultG, defaultB, alpha;
|
||||
|
||||
// process STL header
|
||||
// check for default color in header ("COLOR=rgba" sequence).
|
||||
|
||||
for ( var index = 0; index < 80 - 10; index ++ ) {
|
||||
|
||||
if ((reader.getUint32(index, false) == 0x434F4C4F /*COLO*/) &&
|
||||
(reader.getUint8(index + 4) == 0x52 /*'R'*/) &&
|
||||
(reader.getUint8(index + 5) == 0x3D /*'='*/)) {
|
||||
|
||||
hasColors = true;
|
||||
colors = new Float32Array( faces * 3 * 3);
|
||||
|
||||
defaultR = reader.getUint8(index + 6) / 255;
|
||||
defaultG = reader.getUint8(index + 7) / 255;
|
||||
defaultB = reader.getUint8(index + 8) / 255;
|
||||
alpha = reader.getUint8(index + 9) / 255;
|
||||
}
|
||||
}
|
||||
|
||||
var dataOffset = 84;
|
||||
var faceLength = 12 * 4 + 2;
|
||||
|
||||
var offset = 0;
|
||||
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
|
||||
var vertices = new Float32Array( faces * 3 * 3 );
|
||||
var normals = new Float32Array( faces * 3 * 3 );
|
||||
|
||||
for ( var face = 0; face < faces; face ++ ) {
|
||||
|
||||
var start = dataOffset + face * faceLength;
|
||||
var normalX = reader.getFloat32(start, true);
|
||||
var normalY = reader.getFloat32(start + 4, true);
|
||||
var normalZ = reader.getFloat32(start + 8, true);
|
||||
|
||||
if (hasColors) {
|
||||
|
||||
var packedColor = reader.getUint16(start + 48, true);
|
||||
|
||||
if ((packedColor & 0x8000) === 0) { // facet has its own unique color
|
||||
|
||||
r = (packedColor & 0x1F) / 31;
|
||||
g = ((packedColor >> 5) & 0x1F) / 31;
|
||||
b = ((packedColor >> 10) & 0x1F) / 31;
|
||||
} else {
|
||||
|
||||
r = defaultR;
|
||||
g = defaultG;
|
||||
b = defaultB;
|
||||
}
|
||||
}
|
||||
|
||||
for ( var i = 1; i <= 3; i ++ ) {
|
||||
|
||||
var vertexstart = start + i * 12;
|
||||
|
||||
vertices[ offset ] = reader.getFloat32( vertexstart, true );
|
||||
vertices[ offset + 1 ] = reader.getFloat32( vertexstart + 4, true );
|
||||
vertices[ offset + 2 ] = reader.getFloat32( vertexstart + 8, true );
|
||||
|
||||
normals[ offset ] = normalX;
|
||||
normals[ offset + 1 ] = normalY;
|
||||
normals[ offset + 2 ] = normalZ;
|
||||
|
||||
if (hasColors) {
|
||||
colors[ offset ] = r;
|
||||
colors[ offset + 1 ] = g;
|
||||
colors[ offset + 2 ] = b;
|
||||
}
|
||||
|
||||
offset += 3;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
|
||||
geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
|
||||
|
||||
if (hasColors) {
|
||||
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
|
||||
geometry.hasColors = true;
|
||||
geometry.alpha = alpha;
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
||||
},
|
||||
|
||||
parseASCII: function ( data ) {
|
||||
|
||||
var geometry, length, normal, patternFace, patternNormal, patternVertex, result, text;
|
||||
geometry = new THREE.Geometry();
|
||||
patternFace = /facet([\s\S]*?)endfacet/g;
|
||||
|
||||
while ( ( result = patternFace.exec( data ) ) !== null ) {
|
||||
|
||||
text = result[0];
|
||||
patternNormal = /normal[\s]+([\-+]?[0-9]+\.?[0-9]*([eE][\-+]?[0-9]+)?)+[\s]+([\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?)+[\s]+([\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?)+/g;
|
||||
|
||||
while ( ( result = patternNormal.exec( text ) ) !== null ) {
|
||||
|
||||
normal = new THREE.Vector3( parseFloat( result[ 1 ] ), parseFloat( result[ 3 ] ), parseFloat( result[ 5 ] ) );
|
||||
|
||||
}
|
||||
|
||||
patternVertex = /vertex[\s]+([\-+]?[0-9]+\.?[0-9]*([eE][\-+]?[0-9]+)?)+[\s]+([\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?)+[\s]+([\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?)+/g;
|
||||
|
||||
while ( ( result = patternVertex.exec( text ) ) !== null ) {
|
||||
|
||||
geometry.vertices.push( new THREE.Vector3( parseFloat( result[ 1 ] ), parseFloat( result[ 3 ] ), parseFloat( result[ 5 ] ) ) );
|
||||
|
||||
}
|
||||
|
||||
length = geometry.vertices.length;
|
||||
|
||||
geometry.faces.push( new THREE.Face3( length - 3, length - 2, length - 1, normal ) );
|
||||
|
||||
}
|
||||
|
||||
geometry.computeBoundingBox();
|
||||
geometry.computeBoundingSphere();
|
||||
|
||||
return geometry;
|
||||
|
||||
},
|
||||
|
||||
ensureString: function ( buf ) {
|
||||
|
||||
if (typeof buf !== "string") {
|
||||
var array_buffer = new Uint8Array(buf);
|
||||
var str = '';
|
||||
for (var i = 0; i < buf.byteLength; i ++) {
|
||||
str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian
|
||||
}
|
||||
return str;
|
||||
} else {
|
||||
return buf;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
ensureBinary: function ( buf ) {
|
||||
|
||||
if (typeof buf === "string") {
|
||||
var array_buffer = new Uint8Array(buf.length);
|
||||
for (var i = 0; i < buf.length; i ++) {
|
||||
array_buffer[i] = buf.charCodeAt(i) & 0xff; // implicitly assumes little-endian
|
||||
}
|
||||
return array_buffer.buffer || array_buffer;
|
||||
} else {
|
||||
return buf;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if ( typeof DataView === 'undefined') {
|
||||
|
||||
DataView = function(buffer, byteOffset, byteLength) {
|
||||
|
||||
this.buffer = buffer;
|
||||
this.byteOffset = byteOffset || 0;
|
||||
this.byteLength = byteLength || buffer.byteLength || buffer.length;
|
||||
this._isString = typeof buffer === "string";
|
||||
|
||||
}
|
||||
|
||||
DataView.prototype = {
|
||||
|
||||
_getCharCodes:function(buffer,start,length) {
|
||||
start = start || 0;
|
||||
length = length || buffer.length;
|
||||
var end = start + length;
|
||||
var codes = [];
|
||||
for (var i = start; i < end; i ++) {
|
||||
codes.push(buffer.charCodeAt(i) & 0xff);
|
||||
}
|
||||
return codes;
|
||||
},
|
||||
|
||||
_getBytes: function (length, byteOffset, littleEndian) {
|
||||
|
||||
var result;
|
||||
|
||||
// Handle the lack of endianness
|
||||
if (littleEndian === undefined) {
|
||||
|
||||
littleEndian = this._littleEndian;
|
||||
|
||||
}
|
||||
|
||||
// Handle the lack of byteOffset
|
||||
if (byteOffset === undefined) {
|
||||
|
||||
byteOffset = this.byteOffset;
|
||||
|
||||
} else {
|
||||
|
||||
byteOffset = this.byteOffset + byteOffset;
|
||||
|
||||
}
|
||||
|
||||
if (length === undefined) {
|
||||
|
||||
length = this.byteLength - byteOffset;
|
||||
|
||||
}
|
||||
|
||||
// Error Checking
|
||||
if (typeof byteOffset !== 'number') {
|
||||
|
||||
throw new TypeError('DataView byteOffset is not a number');
|
||||
|
||||
}
|
||||
|
||||
if (length < 0 || byteOffset + length > this.byteLength) {
|
||||
|
||||
throw new Error('DataView length or (byteOffset+length) value is out of bounds');
|
||||
|
||||
}
|
||||
|
||||
if (this.isString) {
|
||||
|
||||
result = this._getCharCodes(this.buffer, byteOffset, byteOffset + length);
|
||||
|
||||
} else {
|
||||
|
||||
result = this.buffer.slice(byteOffset, byteOffset + length);
|
||||
|
||||
}
|
||||
|
||||
if (!littleEndian && length > 1) {
|
||||
|
||||
if (!(result instanceof Array)) {
|
||||
|
||||
result = Array.prototype.slice.call(result);
|
||||
|
||||
}
|
||||
|
||||
result.reverse();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
},
|
||||
|
||||
// Compatibility functions on a String Buffer
|
||||
|
||||
getFloat64: function (byteOffset, littleEndian) {
|
||||
|
||||
var b = this._getBytes(8, byteOffset, littleEndian),
|
||||
|
||||
sign = 1 - (2 * (b[7] >> 7)),
|
||||
exponent = ((((b[7] << 1) & 0xff) << 3) | (b[6] >> 4)) - ((1 << 10) - 1),
|
||||
|
||||
// Binary operators such as | and << operate on 32 bit values, using + and Math.pow(2) instead
|
||||
mantissa = ((b[6] & 0x0f) * Math.pow(2, 48)) + (b[5] * Math.pow(2, 40)) + (b[4] * Math.pow(2, 32)) +
|
||||
(b[3] * Math.pow(2, 24)) + (b[2] * Math.pow(2, 16)) + (b[1] * Math.pow(2, 8)) + b[0];
|
||||
|
||||
if (exponent === 1024) {
|
||||
if (mantissa !== 0) {
|
||||
return NaN;
|
||||
} else {
|
||||
return sign * Infinity;
|
||||
}
|
||||
}
|
||||
|
||||
if (exponent === -1023) { // Denormalized
|
||||
return sign * mantissa * Math.pow(2, -1022 - 52);
|
||||
}
|
||||
|
||||
return sign * (1 + mantissa * Math.pow(2, -52)) * Math.pow(2, exponent);
|
||||
|
||||
},
|
||||
|
||||
getFloat32: function (byteOffset, littleEndian) {
|
||||
|
||||
var b = this._getBytes(4, byteOffset, littleEndian),
|
||||
|
||||
sign = 1 - (2 * (b[3] >> 7)),
|
||||
exponent = (((b[3] << 1) & 0xff) | (b[2] >> 7)) - 127,
|
||||
mantissa = ((b[2] & 0x7f) << 16) | (b[1] << 8) | b[0];
|
||||
|
||||
if (exponent === 128) {
|
||||
if (mantissa !== 0) {
|
||||
return NaN;
|
||||
} else {
|
||||
return sign * Infinity;
|
||||
}
|
||||
}
|
||||
|
||||
if (exponent === -127) { // Denormalized
|
||||
return sign * mantissa * Math.pow(2, -126 - 23);
|
||||
}
|
||||
|
||||
return sign * (1 + mantissa * Math.pow(2, -23)) * Math.pow(2, exponent);
|
||||
},
|
||||
|
||||
getInt32: function (byteOffset, littleEndian) {
|
||||
var b = this._getBytes(4, byteOffset, littleEndian);
|
||||
return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
|
||||
},
|
||||
|
||||
getUint32: function (byteOffset, littleEndian) {
|
||||
return this.getInt32(byteOffset, littleEndian) >>> 0;
|
||||
},
|
||||
|
||||
getInt16: function (byteOffset, littleEndian) {
|
||||
return (this.getUint16(byteOffset, littleEndian) << 16) >> 16;
|
||||
},
|
||||
|
||||
getUint16: function (byteOffset, littleEndian) {
|
||||
var b = this._getBytes(2, byteOffset, littleEndian);
|
||||
return (b[1] << 8) | b[0];
|
||||
},
|
||||
|
||||
getInt8: function (byteOffset) {
|
||||
return (this.getUint8(byteOffset) << 24) >> 24;
|
||||
},
|
||||
|
||||
getUint8: function (byteOffset) {
|
||||
return this._getBytes(1, byteOffset)[0];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
34572
library/three.js
34572
library/three.js
File diff suppressed because one or more lines are too long
BIN
models/cube.stl
BIN
models/cube.stl
Binary file not shown.
BIN
models/cubes.stl
BIN
models/cubes.stl
Binary file not shown.
BIN
models/d20.stl
BIN
models/d20.stl
Binary file not shown.
@ -1,506 +0,0 @@
|
||||
solid OpenSCAD_Model
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 24 0 45.03
|
||||
vertex 12 0 54.03
|
||||
vertex 20.7846 -12 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 8.48528 8.48528 54.03
|
||||
vertex 12 0 54.03
|
||||
vertex 20.7846 12 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 -20.7846 45.03
|
||||
vertex -20.7846 -12 45
|
||||
vertex -12 -20.7846 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 1.46953e-015 54.03
|
||||
vertex 8.48528 8.48528 54.03
|
||||
vertex 7.34764e-016 12 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 0 54.03
|
||||
vertex -8.48528 -8.48528 54.03
|
||||
vertex 8.48528 -8.48528 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 0 54.03
|
||||
vertex 8.48528 -8.48528 54.03
|
||||
vertex 20.7846 -12 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 0 54.03
|
||||
vertex 8.48528 8.48528 54.03
|
||||
vertex -8.48528 -8.48528 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 7.34764e-016 12 54.03
|
||||
vertex 1.46953e-015 24 45.03
|
||||
vertex -12 20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 20.7846 45.03
|
||||
vertex 20.7846 12 45
|
||||
vertex 12 20.7846 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 7.34764e-016 12 54.03
|
||||
vertex 8.48528 8.48528 54.03
|
||||
vertex 12 20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -0.15 -0.259808 15
|
||||
vertex 0.15 0.259808 15
|
||||
vertex 0.15 -0.259808 15
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 20.7846 -12 45.03
|
||||
vertex 12 -20.7846 45
|
||||
vertex 20.7846 -12 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 1.46953e-015 54.03
|
||||
vertex -20.7846 12 45.03
|
||||
vertex -24 2.93906e-015 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -24 2.93906e-015 45.03
|
||||
vertex -20.7846 -12 45
|
||||
vertex -20.7846 -12 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 8.48528 8.48528 54.03
|
||||
vertex 20.7846 12 45.03
|
||||
vertex 12 20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -20.7846 -12 45
|
||||
vertex -12 -20.7846 45.03
|
||||
vertex -20.7846 -12 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -0.15 0.259808 15
|
||||
vertex -12 20.7846 45
|
||||
vertex 1.46953e-015 24 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 0.15 0.259808 15
|
||||
vertex 20.7846 12 45
|
||||
vertex 0.3 0 15
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -2.20429e-015 -12 54.03
|
||||
vertex -4.40858e-015 -24 45.03
|
||||
vertex 12 -20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -2.20429e-015 -12 54.03
|
||||
vertex -8.48528 -8.48528 54.03
|
||||
vertex -12 -20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -24 2.93906e-015 45
|
||||
vertex -20.7846 12 45.03
|
||||
vertex -20.7846 12 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -0.15 0.259808 15
|
||||
vertex -0.15 -0.259808 15
|
||||
vertex -0.3 3.67382e-017 15
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 20.7846 12 45
|
||||
vertex 20.7846 12 45.03
|
||||
vertex 24 0 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 20.7846 12 45.03
|
||||
vertex 12 0 54.03
|
||||
vertex 24 0 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -8.48528 -8.48528 54.03
|
||||
vertex 8.48528 8.48528 54.03
|
||||
vertex -12 1.46953e-015 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 20.7846 12 45.03
|
||||
vertex 20.7846 12 45
|
||||
vertex 12 20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 1.46953e-015 24 45.03
|
||||
vertex -12 20.7846 45
|
||||
vertex -12 20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 7.34764e-016 12 54.03
|
||||
vertex -12 20.7846 45.03
|
||||
vertex -8.48528 8.48528 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 20.7846 12 45
|
||||
vertex 0.15 0.259808 15
|
||||
vertex 12 20.7846 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 1.46953e-015 24 45.03
|
||||
vertex 7.34764e-016 12 54.03
|
||||
vertex 12 20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -4.40858e-015 -24 45.03
|
||||
vertex 12 -20.7846 45
|
||||
vertex 12 -20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 8.48528 -8.48528 54.03
|
||||
vertex -8.48528 -8.48528 54.03
|
||||
vertex -2.20429e-015 -12 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 20.7846 45
|
||||
vertex 1.46953e-015 24 45.03
|
||||
vertex 1.46953e-015 24 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -4.40858e-015 -24 45.03
|
||||
vertex -2.20429e-015 -12 54.03
|
||||
vertex -12 -20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -0.15 -0.259808 15
|
||||
vertex -20.7846 -12 45
|
||||
vertex -0.3 3.67382e-017 15
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -0.15 0.259808 15
|
||||
vertex 0.15 0.259808 15
|
||||
vertex -0.15 -0.259808 15
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 0.15 -0.259808 15
|
||||
vertex 0.3 0 15
|
||||
vertex 20.7846 -12 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -20.7846 -12 45
|
||||
vertex -0.15 -0.259808 15
|
||||
vertex -12 -20.7846 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 -20.7846 45
|
||||
vertex 20.7846 -12 45.03
|
||||
vertex 12 -20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 0.15 -0.259808 15
|
||||
vertex 0.15 0.259808 15
|
||||
vertex 0.3 0 15
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -24 2.93906e-015 45.03
|
||||
vertex -20.7846 12 45.03
|
||||
vertex -24 2.93906e-015 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 1.46953e-015 54.03
|
||||
vertex -24 2.93906e-015 45.03
|
||||
vertex -20.7846 -12 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 20.7846 45
|
||||
vertex -20.7846 12 45.03
|
||||
vertex -12 20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 1.46953e-015 54.03
|
||||
vertex 7.34764e-016 12 54.03
|
||||
vertex -8.48528 8.48528 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 1.46953e-015 24 45.03
|
||||
vertex 12 20.7846 45
|
||||
vertex 1.46953e-015 24 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 1.46953e-015 24 45.03
|
||||
vertex 12 20.7846 45.03
|
||||
vertex 12 20.7846 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 20.7846 -12 45.03
|
||||
vertex 8.48528 -8.48528 54.03
|
||||
vertex 12 -20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 8.48528 -8.48528 54.03
|
||||
vertex -2.20429e-015 -12 54.03
|
||||
vertex 12 -20.7846 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 20.7846 45
|
||||
vertex 0.15 0.259808 15
|
||||
vertex 1.46953e-015 24 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 0.15 0.259808 15
|
||||
vertex -0.15 0.259808 15
|
||||
vertex 1.46953e-015 24 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 -20.7846 45
|
||||
vertex -4.40858e-015 -24 45.03
|
||||
vertex -4.40858e-015 -24 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -4.40858e-015 -24 45.03
|
||||
vertex -12 -20.7846 45.03
|
||||
vertex -12 -20.7846 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -4.40858e-015 -24 45.03
|
||||
vertex -12 -20.7846 45
|
||||
vertex -4.40858e-015 -24 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 -20.7846 45
|
||||
vertex -0.15 -0.259808 15
|
||||
vertex -4.40858e-015 -24 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 -20.7846 45
|
||||
vertex -4.40858e-015 -24 45
|
||||
vertex 0.15 -0.259808 15
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -4.40858e-015 -24 45
|
||||
vertex -0.15 -0.259808 15
|
||||
vertex 0.15 -0.259808 15
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -0.15 0.259808 15
|
||||
vertex -0.3 3.67382e-017 15
|
||||
vertex -20.7846 12 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -0.3 3.67382e-017 15
|
||||
vertex -24 2.93906e-015 45
|
||||
vertex -20.7846 12 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 -20.7846 45.03
|
||||
vertex -8.48528 -8.48528 54.03
|
||||
vertex -20.7846 -12 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -8.48528 -8.48528 54.03
|
||||
vertex -12 1.46953e-015 54.03
|
||||
vertex -20.7846 -12 45.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 20.7846 45.03
|
||||
vertex -20.7846 12 45.03
|
||||
vertex -8.48528 8.48528 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -20.7846 12 45.03
|
||||
vertex -12 1.46953e-015 54.03
|
||||
vertex -8.48528 8.48528 54.03
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 0.3 0 15
|
||||
vertex 20.7846 12 45
|
||||
vertex 24 0 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 12 -20.7846 45
|
||||
vertex 0.15 -0.259808 15
|
||||
vertex 20.7846 -12 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -0.3 3.67382e-017 15
|
||||
vertex -20.7846 -12 45
|
||||
vertex -24 2.93906e-015 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -20.7846 -12 45
|
||||
vertex -24 2.93906e-015 45.03
|
||||
vertex -24 2.93906e-015 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 20.7846 12 45
|
||||
vertex 24 0 45.03
|
||||
vertex 24 0 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 24 0 45.03
|
||||
vertex 20.7846 -12 45.03
|
||||
vertex 20.7846 -12 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 24 0 45.03
|
||||
vertex 20.7846 -12 45
|
||||
vertex 24 0 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex 20.7846 -12 45
|
||||
vertex 0.3 0 15
|
||||
vertex 24 0 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -20.7846 12 45.03
|
||||
vertex -12 20.7846 45
|
||||
vertex -20.7846 12 45
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 0 0
|
||||
outer loop
|
||||
vertex -12 20.7846 45
|
||||
vertex -0.15 0.259808 15
|
||||
vertex -20.7846 12 45
|
||||
endloop
|
||||
endfacet
|
||||
endsolid OpenSCAD_Model
|
BIN
models/dom.stl
BIN
models/dom.stl
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
153932
models/robot.stl
153932
models/robot.stl
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
92
package.json
Normal file
92
package.json
Normal file
@ -0,0 +1,92 @@
|
||||
{
|
||||
"jspm": {
|
||||
"name": "slicer",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"lib": "src"
|
||||
},
|
||||
"dependencies": {
|
||||
"Doodle3D/clipper-js": "github:Doodle3D/clipper-js@master",
|
||||
"clipper-js": "github:Doodle3D/clipper-js@1.0.2",
|
||||
"js-yaml": "npm:js-yaml@^3.9.0",
|
||||
"json": "github:systemjs/plugin-json@^0.1.2",
|
||||
"progress-promise": "npm:progress-promise@^0.0.6",
|
||||
"text": "github:systemjs/plugin-text@^0.0.11",
|
||||
"three": "npm:three@0.83.0",
|
||||
"worker": "github:casperlamboo/plugin-worker@master"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-plugin-transform-react-jsx": "npm:babel-plugin-transform-react-jsx@^6.8.0",
|
||||
"babel-runtime": "npm:babel-runtime@^5.1.13",
|
||||
"core-js": "npm:core-js@^1.2.0",
|
||||
"file-saver": "npm:file-saver@^1.3.3",
|
||||
"domain": "github:jspm/nodelibs-domain@^0.2.0-alpha",
|
||||
"https": "github:jspm/nodelibs-https@^0.2.0-alpha",
|
||||
"plugin-babel": "npm:systemjs-plugin-babel@^0.0.12",
|
||||
"react": "npm:react@^15.3.2",
|
||||
"react-dom": "npm:react-dom@^15.3.2",
|
||||
"zlib": "github:jspm/nodelibs-zlib@^0.2.0-alpha"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"assert": "github:jspm/nodelibs-assert@^0.2.0-alpha",
|
||||
"buffer": "github:jspm/nodelibs-buffer@^0.2.0-alpha",
|
||||
"child_process": "github:jspm/nodelibs-child_process@^0.2.0-alpha",
|
||||
"constants": "github:jspm/nodelibs-constants@^0.2.0-alpha",
|
||||
"crypto": "github:jspm/nodelibs-crypto@^0.2.0-alpha",
|
||||
"events": "github:jspm/nodelibs-events@^0.2.0-alpha",
|
||||
"fs": "github:jspm/nodelibs-fs@^0.2.0-alpha",
|
||||
"http": "github:jspm/nodelibs-http@^0.2.0-alpha",
|
||||
"module": "npm:jspm-nodelibs-module@^0.2.0",
|
||||
"os": "github:jspm/nodelibs-os@^0.2.0-alpha",
|
||||
"path": "github:jspm/nodelibs-path@^0.2.0-alpha",
|
||||
"process": "github:jspm/nodelibs-process@^0.2.0-alpha",
|
||||
"stream": "github:jspm/nodelibs-stream@^0.2.0-alpha",
|
||||
"string_decoder": "github:jspm/nodelibs-string_decoder@^0.2.0-alpha",
|
||||
"tty": "npm:jspm-nodelibs-tty@^0.2.0",
|
||||
"url": "github:jspm/nodelibs-url@^0.2.0-alpha",
|
||||
"util": "github:jspm/nodelibs-util@^0.2.0-alpha",
|
||||
"vm": "github:jspm/nodelibs-vm@^0.2.0-alpha"
|
||||
},
|
||||
"overrides": {
|
||||
"npm:babel-runtime@5.8.38": {
|
||||
"main": false,
|
||||
"dependencies": {},
|
||||
"optionalDependencies": {
|
||||
"core-js": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"npm:browserify-zlib@0.1.4": {
|
||||
"dependencies": {
|
||||
"readable-stream": "^2.0.2",
|
||||
"pako": "~0.2.0"
|
||||
},
|
||||
"map": {
|
||||
"_stream_transform": "readable-stream/transform"
|
||||
}
|
||||
},
|
||||
"npm:inherits@2.0.3": {
|
||||
"ignore": [
|
||||
"test.js"
|
||||
]
|
||||
},
|
||||
"npm:lodash@4.16.4": {
|
||||
"map": {
|
||||
"buffer": "@empty",
|
||||
"process": "@empty"
|
||||
}
|
||||
},
|
||||
"npm:pbkdf2@3.0.12": {
|
||||
"main": "browser.js"
|
||||
},
|
||||
"npm:safe-buffer@5.1.1": {
|
||||
"browser": "index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"js-yaml": "^3.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jspm": "^0.17.0-beta.28"
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
{
|
||||
"ultimaker": {
|
||||
"printer.baudrate": "115200",
|
||||
"printer.dimensions.x": 200,
|
||||
"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.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 (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,24 +0,0 @@
|
||||
{
|
||||
"printer.normalFlowRate": 1.0,
|
||||
"printer.bottomFlowRate": 2.0,
|
||||
"printer.bottomLayerSpeed": 35.0,
|
||||
"printer.bottomThickness": 0.4,
|
||||
"printer.fillSize": 5.0,
|
||||
"printer.firstLayerSlow": true,
|
||||
"printer.layerHeight": 0.2,
|
||||
"printer.retraction.amount": 3.0,
|
||||
"printer.retraction.enabled": true,
|
||||
"printer.retraction.speed": 50,
|
||||
"printer.retraction.minDistance": 5.0,
|
||||
"printer.shellThickness": 0.4,
|
||||
"printer.speed": 50.0,
|
||||
"printer.temperature": 210.0,
|
||||
"printer.topThickness": 0.8,
|
||||
"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
|
||||
}
|
15
simpleExample/index.html
Normal file
15
simpleExample/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doodle3D Slicer - Simple example</title>
|
||||
<script type="text/javascript" src="../jspm_packages/system.js"></script>
|
||||
<script type="text/javascript" src="../jspm.config.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
System.import('simpleExample/index.js');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="gcode"></div>
|
||||
</body>
|
||||
</html>
|
16
simpleExample/index.js
Normal file
16
simpleExample/index.js
Normal file
@ -0,0 +1,16 @@
|
||||
import 'three.js';
|
||||
import * as SLICER from 'src/index.js';
|
||||
|
||||
const settings = new SLICER.Settings({
|
||||
...SLICER.printerSettings['ultimaker2go'],
|
||||
...SLICER.userSettings.low
|
||||
});
|
||||
|
||||
const geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone();
|
||||
|
||||
const slicer = new SLICER.Slicer();
|
||||
|
||||
slicer.setGeometry(geometry);
|
||||
slicer.slice(settings, false).then(gcode => {
|
||||
document.getElementById('gcode').innerHTML = gcode.replace(/(?:\r\n|\r|\n)/g, '<br />');
|
||||
});
|
182
slice_test.html
182
slice_test.html
@ -1,182 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Doedel Drie Dee || Slice Test</title>
|
||||
<!--<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>-->
|
||||
<script src="library/jquery.js"></script>
|
||||
<script src="library/three.js"></script>
|
||||
<script src="library/stl_loader.js"></script>
|
||||
<script src="library/clipper.js"></script>
|
||||
|
||||
<script src="src/utils.js"></script>
|
||||
<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>
|
||||
|
||||
<style>
|
||||
canvas {border: 1px solid black;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="3d-preview" height="400" width="400"></canvas>
|
||||
<canvas id="canvas" width="400" height="400"></canvas>
|
||||
|
||||
<script>
|
||||
var USER_SETTINGS, PRINTER_SETTINGS, doodleBox, gcode;
|
||||
|
||||
function init () {
|
||||
"use strict";
|
||||
var scene = createScene();
|
||||
|
||||
var localIp = location.hash.substring(1);
|
||||
//doodleBox = new D3D.Box(localIp);
|
||||
|
||||
var printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS["ultimaker"]);
|
||||
|
||||
var loader = new THREE.STLLoader();
|
||||
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);
|
||||
/*
|
||||
var geometry = (function () {
|
||||
"use strict";
|
||||
|
||||
var circle = new THREE.Shape();
|
||||
circle.absarc(0, 0, 10, 0, Math.PI*2, false);
|
||||
|
||||
var hole = new THREE.Path();
|
||||
hole.absarc(0, 0, 5, 0, Math.PI*2, true );
|
||||
|
||||
circle.holes.push(hole);
|
||||
|
||||
var matrix = new THREE.Matrix4();
|
||||
matrix.makeRotationX(Math.PI*1.5);
|
||||
|
||||
var geometry = new THREE.ExtrudeGeometry(circle, {
|
||||
amount: 10,
|
||||
bevelEnabled: false,
|
||||
steps: 1
|
||||
});
|
||||
geometry.applyMatrix(matrix);
|
||||
|
||||
return geometry;
|
||||
})();
|
||||
*/
|
||||
var material = new THREE.MeshPhongMaterial({color: 0x00ff00, wireframe: false});
|
||||
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;
|
||||
|
||||
mesh.updateMatrix();
|
||||
|
||||
scene.add(mesh);
|
||||
|
||||
var slicer = new D3D.Slicer().setMesh(mesh.geometry, mesh.matrix);
|
||||
|
||||
//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);
|
||||
});
|
||||
}
|
||||
|
||||
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(100, 0, 100), 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;
|
||||
}
|
||||
|
||||
//loadSettings;
|
||||
(function () {
|
||||
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>
|
182
src/GCode.js
Normal file
182
src/GCode.js
Normal file
@ -0,0 +1,182 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
const MOVE = 'G';
|
||||
const M_COMMAND = 'M';
|
||||
const FAN_SPEED = 'S';
|
||||
const SPEED = 'F';
|
||||
const EXTRUDER = 'E';
|
||||
const POSITION_X = 'X';
|
||||
const POSITION_Y = 'Y';
|
||||
const POSITION_Z = 'Z';
|
||||
|
||||
export default class {
|
||||
constructor(settings) {
|
||||
this._gcode = '';
|
||||
this._currentValues = {};
|
||||
this._settings = settings;
|
||||
this._nozzlePosition = new THREE.Vector2(0, 0);
|
||||
this._extruder = 0.0;
|
||||
this._isRetracted = false;
|
||||
this._isFanOn = false;
|
||||
|
||||
this.bottom = true;
|
||||
}
|
||||
|
||||
_addGCode(command) {
|
||||
let str = '';
|
||||
|
||||
let first = true;
|
||||
for (const action in command) {
|
||||
const value = command[action];
|
||||
const currentValue = this._currentValues[action];
|
||||
if (first) {
|
||||
str = action + value;
|
||||
|
||||
first = false;
|
||||
} else if (currentValue !== value) {
|
||||
str += ` ${action}${value}`;
|
||||
|
||||
this._currentValues[action] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this._gcode += `${str}\n`;
|
||||
}
|
||||
|
||||
turnFanOn(fanSpeed) {
|
||||
this._isFanOn = true;
|
||||
|
||||
const gcode = { [M_COMMAND]: 106 }
|
||||
if (typeof fanSpeed !== 'undefined') gcode[FAN_SPEED] = fanSpeed;
|
||||
|
||||
this._addGCode(gcode);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
turnFanOff() {
|
||||
this._isFanOn = false;
|
||||
|
||||
this._addGCode({ [M_COMMAND]: 107 });
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
moveTo(x, y, layer) {
|
||||
const {
|
||||
layerHeight,
|
||||
travelSpeed
|
||||
} = this._settings;
|
||||
|
||||
const z = layer * layerHeight + 0.2;
|
||||
const speed = travelSpeed * 60;
|
||||
|
||||
this._addGCode({
|
||||
[MOVE]: 0,
|
||||
[POSITION_X]: x.toFixed(3),
|
||||
[POSITION_Y]: y.toFixed(3),
|
||||
[POSITION_Z]: z.toFixed(3),
|
||||
[SPEED]: speed.toFixed(3)
|
||||
});
|
||||
|
||||
this._nozzlePosition.set(x, y);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
lineTo(x, y, layer, type) {
|
||||
const newNozzlePosition = new THREE.Vector2(x, y);
|
||||
|
||||
const {
|
||||
layerHeight,
|
||||
nozzleDiameter,
|
||||
filamentThickness,
|
||||
travelSpeed
|
||||
} = this._settings;
|
||||
|
||||
const profile = this._settings[(this.bottom ? 'bottom' : type)];
|
||||
|
||||
let {
|
||||
speed,
|
||||
flowRate
|
||||
} = profile;
|
||||
|
||||
speed *= 60;
|
||||
const z = layer * layerHeight + 0.2;
|
||||
|
||||
const lineLength = this._nozzlePosition.distanceTo(newNozzlePosition);
|
||||
|
||||
const filamentSurfaceArea = Math.pow((filamentThickness / 2), 2) * Math.PI;
|
||||
this._extruder += lineLength * nozzleDiameter * layerHeight / filamentSurfaceArea * flowRate;
|
||||
|
||||
this._addGCode({
|
||||
[MOVE]: 1,
|
||||
[POSITION_X]: x.toFixed(3),
|
||||
[POSITION_Y]: y.toFixed(3),
|
||||
[POSITION_Z]: z.toFixed(3),
|
||||
[SPEED]: speed.toFixed(3),
|
||||
[EXTRUDER]: this._extruder.toFixed(3)
|
||||
});
|
||||
|
||||
this._nozzlePosition.copy(newNozzlePosition);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
unRetract() {
|
||||
const {
|
||||
retraction: {
|
||||
enabled: retractionEnabled,
|
||||
minDistance: retractionMinDistance,
|
||||
speed: retractionSpeed
|
||||
}
|
||||
} = this._settings;
|
||||
|
||||
if (this._isRetracted && retractionEnabled) {
|
||||
this._isRetracted = false;
|
||||
|
||||
const speed = retractionSpeed * 60;
|
||||
|
||||
if (this._extruder > retractionMinDistance) {
|
||||
this._addGCode({
|
||||
[MOVE]: 0,
|
||||
[EXTRUDER]: this._extruder.toFixed(3),
|
||||
[SPEED]: speed.toFixed(3)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
retract() {
|
||||
const {
|
||||
retraction: {
|
||||
amount: retractionAmount,
|
||||
enabled: retractionEnabled,
|
||||
minDistance: retractionMinDistance,
|
||||
speed: retractionSpeed
|
||||
}
|
||||
} = this._settings;
|
||||
|
||||
if (!this._isRetracted && retractionEnabled) {
|
||||
this._isRetracted = true;
|
||||
|
||||
const speed = retractionSpeed * 60;
|
||||
|
||||
if (this._extruder > retractionMinDistance && retractionEnabled) {
|
||||
this._addGCode({
|
||||
[MOVE]: 0,
|
||||
[EXTRUDER]: (this._extruder - retractionAmount).toFixed(3),
|
||||
[SPEED]: speed.toFixed(3)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
getGCode() {
|
||||
return this._gcode;
|
||||
}
|
||||
}
|
24
src/Slice.js
Normal file
24
src/Slice.js
Normal file
@ -0,0 +1,24 @@
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
|
||||
export default class {
|
||||
constructor() {
|
||||
this.parts = [];
|
||||
}
|
||||
getOutline() {
|
||||
return this.parts.reduce((shape, part) => {
|
||||
if (part.outerLine) shape.join(part.outerLine);
|
||||
return shape;
|
||||
}, new Shape([], true));
|
||||
}
|
||||
add(shape) {
|
||||
const part = { shape };
|
||||
|
||||
if (shape.closed) {
|
||||
part.innerLines = [];
|
||||
part.outerLine = new Shape([], true);
|
||||
part.fill = new Shape([], false);
|
||||
}
|
||||
|
||||
this.parts.push(part);
|
||||
}
|
||||
}
|
63
src/Slicer.js
Normal file
63
src/Slicer.js
Normal file
@ -0,0 +1,63 @@
|
||||
import * as THREE from 'three';
|
||||
import slice from './sliceActions/slice.js';
|
||||
import SlicerWorker from './slicerWorker.js!worker';
|
||||
import ProgressPromise from 'progress-promise';
|
||||
|
||||
export default class {
|
||||
setMesh(mesh) {
|
||||
mesh.updateMatrix();
|
||||
|
||||
this.setGeometry(mesh.geometry, mesh.matrix);
|
||||
|
||||
return this;
|
||||
}
|
||||
setGeometry(geometry, matrix) {
|
||||
if (geometry.isBufferGeometry) {
|
||||
geometry = new THREE.Geometry().fromBufferGeometry(geometry);
|
||||
} else if (geometry.isGeometry) {
|
||||
geometry = geometry.clone();
|
||||
} else {
|
||||
throw new Error('Geometry is not an instance of BufferGeometry or Geometry');
|
||||
}
|
||||
|
||||
if (matrix) {
|
||||
geometry.applyMatrix(matrix);
|
||||
}
|
||||
|
||||
this.geometry = geometry;
|
||||
|
||||
return this;
|
||||
}
|
||||
sliceSync(settings, onprogress) {
|
||||
return slice(this.geometry, settings, onprogress);
|
||||
}
|
||||
slice(settings) {
|
||||
const slicerWorker = new SlicerWorker();
|
||||
|
||||
const geometry = this.geometry.toJSON();
|
||||
|
||||
return new ProgressPromise((resolve, reject, progress) => {
|
||||
slicerWorker.onerror = reject;
|
||||
|
||||
slicerWorker.addEventListener('message', (event) => {
|
||||
const { message, data } = event.data;
|
||||
switch (message) {
|
||||
case 'SLICE': {
|
||||
slicerWorker.terminate();
|
||||
resolve(data.gcode);
|
||||
break;
|
||||
}
|
||||
case 'PROGRESS': {
|
||||
progress(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
slicerWorker.postMessage({
|
||||
message: 'SLICE',
|
||||
data: { geometry, settings }
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
387
src/box.js
387
src/box.js
@ -1,387 +0,0 @@
|
||||
/******************************************************
|
||||
*
|
||||
* Box
|
||||
* Representation of de Doodle3DBox
|
||||
* Handles all communication with the doodle box
|
||||
* JavaScript shell for api communication
|
||||
* Check http://www.doodle3d.com/help/api-documentation
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
//TODO
|
||||
//Als meerdere clients met box zouden verbinden zal de api te veel requests krijgen waardoor hij crasht
|
||||
//implimentatie van het veranderen van onder andere naam, netwerkverbinding etc
|
||||
|
||||
D3D.Box = function (localIp) {
|
||||
"use strict";
|
||||
var scope = this;
|
||||
|
||||
this.batchSize = 512;
|
||||
this.maxBufferedLines = 4096;
|
||||
|
||||
this.localIp = localIp;
|
||||
this.api = "http://" + localIp + "/d3dapi/";
|
||||
|
||||
this.config = {};
|
||||
this.status = {};
|
||||
|
||||
this.printBatches = [];
|
||||
this.currentBatch = 0;
|
||||
|
||||
this.loaded = false;
|
||||
|
||||
this.getConfigAll(function (data) {
|
||||
scope.updateConfig(data);
|
||||
|
||||
scope.update();
|
||||
|
||||
scope.loaded = true;
|
||||
if (scope.onload !== undefined) {
|
||||
scope.onload();
|
||||
}
|
||||
});
|
||||
};
|
||||
D3D.Box.prototype.updateConfig = function (config) {
|
||||
"use strict";
|
||||
|
||||
for (var i in config) {
|
||||
this.config[i] = config[i];
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
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
|
||||
//Als DoodleBox ontkoppeld wordt komt er een error in de loop waardoor pagina breekt en ververst moet worden
|
||||
|
||||
if (this.printBatches.length > 0 && (this.status["buffered_lines"] + this.batchSize) <= this.maxBufferedLines) {
|
||||
//if (this.printBatches.length > 0 ) {
|
||||
this.printBatch();
|
||||
}
|
||||
else {
|
||||
setTimeout(function () {
|
||||
scope.updateState();
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
D3D.Box.prototype.updateState = function () {
|
||||
//que api calls so they don't overload the d3d box
|
||||
"use strict";
|
||||
var scope = this;
|
||||
|
||||
this.getInfoStatus(function (data) {
|
||||
scope.status = data;
|
||||
|
||||
if (scope.onupdate !== undefined) {
|
||||
scope.onupdate(data);
|
||||
}
|
||||
|
||||
scope.update();
|
||||
});
|
||||
};
|
||||
D3D.Box.prototype.print = function (gcode) {
|
||||
"use strict";
|
||||
|
||||
this.currentBatch = 0;
|
||||
|
||||
//clone gcode to remove array links
|
||||
gcode = gcode.clone();
|
||||
|
||||
//gcode split in batches
|
||||
while (gcode.length > 0) {
|
||||
var gcodeBatch = gcode.splice(0, Math.min(this.batchSize, gcode.length));
|
||||
this.printBatches.push(gcodeBatch);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.printBatch = function () {
|
||||
"use strict";
|
||||
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"),
|
||||
"last": ((this.printBatches.length === 0) ? true : false) //only for debug purposes
|
||||
}, function (data) {
|
||||
console.log("batch sent: " + scope.currentBatch, data);
|
||||
|
||||
if (scope.printBatches.length > 0) {
|
||||
//sent new batch
|
||||
scope.currentBatch ++;
|
||||
}
|
||||
else {
|
||||
//finish sending
|
||||
}
|
||||
|
||||
scope.updateState();
|
||||
});
|
||||
};
|
||||
D3D.Box.prototype.stopPrint = function (printer) {
|
||||
"use strict";
|
||||
|
||||
this.printBatches = [];
|
||||
this.currentBatch = 0;
|
||||
|
||||
this.setPrinterStop({
|
||||
"gcode": printer.getEndCode().join("\n")
|
||||
}, function (data) {
|
||||
console.log("Printer stop command sent");
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//COMMUNICATION SHELL
|
||||
//see http://www.doodle3d.com/help/api-documentation
|
||||
D3D.Box.prototype.getConfig = function (keys, callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "config/?" + keys.join("=&") + "=", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getConfigAll = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "config/all", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setConfig = function (data, callback) {
|
||||
"use strict";
|
||||
var scope = this;
|
||||
|
||||
sendAPI(this.api + "config", data, function (response) {
|
||||
for (var i in response.validation) {
|
||||
if (response.validation[i] === "ok") {
|
||||
scope[i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (callback !== undefined) {
|
||||
callback(response);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getInfo = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "info", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getInfoStatus = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "info/status", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.downloadInfoLogFiles = function () {
|
||||
//works in google chrome... not tested in other browsers
|
||||
//some browsers may redirect using this code
|
||||
"use strict";
|
||||
|
||||
window.location = this.api + "info/logfiles";
|
||||
};
|
||||
D3D.Box.prototype.getInfoAcces = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "info/access", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getNetworkScan = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "network/scan", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getNetworkKnown = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "network/known", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getNetworkStatus = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "network/status", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setNetworkAssosiate = function (data, callback) {
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "network/associate", data, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setNetworkDisassosiate = function (callback) {
|
||||
//not tested
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "network/disassociate", {}, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setNetworkOpenAP = function (callback) {
|
||||
//not tested
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "network/openap", {}, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setNetworkRemove = function (ssid, callback) {
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "network/remove", {
|
||||
"ssid": ssid
|
||||
}, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getNetworkSignin = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "network/signin", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getNetworkAlive = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "network/alive", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getPrinterTemperature = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "printer/temperature", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getPrinterProgress = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "printer/progress", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getPrinterState = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "printer/state", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getPrinterListAll = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "printer/listall", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setPrinterHeatup = function (callback) {
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "printer/heatup", {}, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setPrinterPrint = function (data, callback) {
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "printer/print", data, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setPrinterStop = function (data, callback) {
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "printer/stop", data, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getSketch = function (id, callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "sketch/?id=" + id, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setSketch = function (data, callback) {
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "sketch", {
|
||||
"data": data
|
||||
}, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getSketchStatus = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "sketch/status", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setSketchClear = function (callback) {
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "sketch/clear", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getSystemVersions = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "system/fwversions", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.getUpdateStatus = function (callback) {
|
||||
"use strict";
|
||||
|
||||
getAPI(this.api + "update/status", callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setUpdateDownload = function (callback) {
|
||||
//not tested
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "update/download", {}, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setUpdateInstall = function (callback) {
|
||||
//not tested
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "update/install", {}, callback);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Box.prototype.setUpdateClear = function (callback) {
|
||||
//not tested
|
||||
"use strict";
|
||||
|
||||
sendAPI(this.api + "update/clear", {}, callback);
|
||||
|
||||
return this;
|
||||
};
|
2
src/constants.js
Normal file
2
src/constants.js
Normal file
@ -0,0 +1,2 @@
|
||||
export const CLEAN_DELTA = 0.05;
|
||||
export const PRECISION = 0.01;
|
184
src/gcode.js
184
src/gcode.js
@ -1,184 +0,0 @@
|
||||
/******************************************************
|
||||
*
|
||||
* 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());
|
||||
};
|
18
src/index.js
Normal file
18
src/index.js
Normal file
@ -0,0 +1,18 @@
|
||||
import Slicer from './Slicer.js';
|
||||
import baseSettings from './settings/default.yml!text';
|
||||
import printerSettings from './settings/printer.yml!text';
|
||||
import materialSettings from './settings/material.yml!text';
|
||||
import qualitySettings from './settings/quality.yml!text';
|
||||
import yaml from 'js-yaml';
|
||||
|
||||
const defaultSettings = {
|
||||
base: yaml.safeLoad(baseSettings),
|
||||
printer: yaml.safeLoad(printerSettings),
|
||||
material: yaml.safeLoad(materialSettings),
|
||||
quality: yaml.safeLoad(qualitySettings)
|
||||
};
|
||||
|
||||
export {
|
||||
Slicer,
|
||||
defaultSettings
|
||||
};
|
242
src/paths.js
242
src/paths.js
@ -1,242 +0,0 @@
|
||||
/******************************************************
|
||||
*
|
||||
* Path
|
||||
*
|
||||
* Abstraction layer for annoying clipper js
|
||||
* ! inherrits from Array !
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
D3D.Paths = function (paths, closed) {
|
||||
"use strict";
|
||||
|
||||
Array.call(this);
|
||||
|
||||
this.setPaths(paths || []);
|
||||
|
||||
this.closed = (closed !== undefined) ? closed : true;
|
||||
};
|
||||
D3D.Paths.prototype = Object.create(Array.prototype);
|
||||
D3D.Paths.prototype.setPaths = function (paths) {
|
||||
"use strict";
|
||||
|
||||
for (var i = 0; i < paths.length; i ++) {
|
||||
var path = paths[i];
|
||||
if (path.length > 0) {
|
||||
this.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Paths.prototype.clip = function (path, type) {
|
||||
"use strict";
|
||||
|
||||
var solution = new ClipperLib.Paths();
|
||||
|
||||
var clipper = new ClipperLib.Clipper();
|
||||
clipper.AddPaths(this, ClipperLib.PolyType.ptSubject, this.closed);
|
||||
clipper.AddPaths(path, ClipperLib.PolyType.ptClip, path.closed);
|
||||
clipper.Execute(type, solution);
|
||||
|
||||
return new D3D.Paths(solution, this.closed);
|
||||
};
|
||||
D3D.Paths.prototype.union = function (path) {
|
||||
"use strict";
|
||||
|
||||
return this.clip(path, ClipperLib.ClipType.ctUnion);
|
||||
};
|
||||
D3D.Paths.prototype.difference = function (path) {
|
||||
"use strict";
|
||||
|
||||
return this.clip(path, ClipperLib.ClipType.ctDifference);
|
||||
};
|
||||
D3D.Paths.prototype.intersect = function (path) {
|
||||
"use strict";
|
||||
|
||||
return this.clip(path, ClipperLib.ClipType.ctIntersection);
|
||||
};
|
||||
D3D.Paths.prototype.xor = function () {
|
||||
"use strict";
|
||||
|
||||
return this.clip(path, ClipperLib.ClipType.ctXor);
|
||||
};
|
||||
D3D.Paths.prototype.offset = function (offset) {
|
||||
"use strict";
|
||||
|
||||
var solution = new ClipperLib.Paths();
|
||||
var co = new ClipperLib.ClipperOffset(1, 1);
|
||||
co.AddPaths(this, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon);
|
||||
co.Execute(solution, offset);
|
||||
|
||||
return new D3D.Paths(solution);
|
||||
};
|
||||
D3D.Paths.prototype.scaleUp = function (factor) {
|
||||
"use strict";
|
||||
|
||||
var path = ClipperLib.JS.ScaleUpPaths(this, factor);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Paths.prototype.scaleDown = function (factor) {
|
||||
"use strict";
|
||||
|
||||
var path = ClipperLib.JS.ScaleDownPaths(this, factor);
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Paths.prototype.lastPoint = function () {
|
||||
"use strict";
|
||||
|
||||
var lastPath = this[this.length - 1];
|
||||
var lastPoint = this.closed ? lastPath[0] : lastPath[lastPath.length - 1];
|
||||
return new THREE.Vector2(lastPoint.X, lastPoint.Y);
|
||||
};
|
||||
D3D.Paths.prototype.optimizePath = function (start) {
|
||||
"use strict";
|
||||
|
||||
var optimizedPaths = new D3D.Paths([], this.closed);
|
||||
var donePaths = [];
|
||||
|
||||
while (optimizedPaths.length !== this.length) {
|
||||
var minLength = false;
|
||||
var reverse;
|
||||
var minPath;
|
||||
var offset;
|
||||
var pathIndex;
|
||||
|
||||
for (var i = 0; i < this.length; i ++) {
|
||||
var path = this[i];
|
||||
|
||||
if (donePaths.indexOf(i) === -1) {
|
||||
|
||||
if (this.closed) {
|
||||
for (var j = 0; j < path.length; j ++) {
|
||||
var point = new THREE.Vector2(path[j].X, path[j].Y);
|
||||
var length = point.sub(start).length();
|
||||
if (minLength === false || length < minLength) {
|
||||
minPath = path;
|
||||
minLength = length;
|
||||
offset = j;
|
||||
pathIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var startPoint = new THREE.Vector2(path[0].X, path[0].Y);
|
||||
var length = startPoint.sub(start).length();
|
||||
if (minLength === false || length < minLength) {
|
||||
minPath = path;
|
||||
minLength = length;
|
||||
reverse = false;
|
||||
pathIndex = i;
|
||||
}
|
||||
var endPoint = new THREE.Vector2(path[path.length - 1].X, path[path.length - 1].Y);
|
||||
var length = endPoint.sub(start).length();
|
||||
if (length < minLength) {
|
||||
minPath = path;
|
||||
minLength = length;
|
||||
reverse = true;
|
||||
pathIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.closed) {
|
||||
minPath = minPath.concat(minPath.splice(0, offset));
|
||||
var point = minPath[0];
|
||||
}
|
||||
else {
|
||||
if (reverse) {
|
||||
minPath.reverse();
|
||||
}
|
||||
var point = minPath[minPath.length - 1];
|
||||
}
|
||||
donePaths.push(pathIndex);
|
||||
start = new THREE.Vector2(point.X, point.Y);
|
||||
optimizedPaths.push(minPath);
|
||||
}
|
||||
|
||||
return optimizedPaths;
|
||||
};
|
||||
D3D.Paths.prototype.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";
|
||||
|
||||
for (var i = 0; i < this.length; i ++) {
|
||||
var shape = this[i];
|
||||
|
||||
var area = ClipperLib.Clipper.Area(shape);
|
||||
|
||||
if (area < minArea) {
|
||||
this.splice(i, 1);
|
||||
i --;
|
||||
}
|
||||
}
|
||||
|
||||
return areas;
|
||||
};
|
||||
D3D.Paths.prototype.join = function (path) {
|
||||
"use strict";
|
||||
|
||||
for (var i = 0; i < path.length; i ++) {
|
||||
this.push(path[i]);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Paths.prototype.clone = function () {
|
||||
"use strict";
|
||||
|
||||
return new D3D.Paths(ClipperLib.JS.Clone(this), this.closed);
|
||||
};
|
||||
D3D.Paths.prototype.bounds = function () {
|
||||
"use strict";
|
||||
|
||||
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";
|
||||
|
||||
context.strokeStyle = color;
|
||||
for (var i = 0; i < this.length; i ++) {
|
||||
var shape = this[i];
|
||||
|
||||
//var point = shape[0];
|
||||
//context.fillText(i, point.X*2, point.Y*2);
|
||||
|
||||
context.beginPath();
|
||||
var length = this.closed ? (shape.length + 1) : shape.length;
|
||||
for (var j = 0; j < length; j ++) {
|
||||
var point = shape[j % shape.length];
|
||||
|
||||
context.lineTo(point.X*2, point.Y*2);
|
||||
}
|
||||
context.stroke();
|
||||
}
|
||||
};
|
@ -1,68 +0,0 @@
|
||||
/******************************************************
|
||||
*
|
||||
* Printer
|
||||
* Representation of the connected printer
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
D3D.Printer = function () {
|
||||
"use strict";
|
||||
|
||||
this.config = {};
|
||||
};
|
||||
D3D.Printer.prototype.updateConfig = function (config) {
|
||||
"use strict";
|
||||
|
||||
for (var i in config) {
|
||||
if (i.indexOf("printer") === 0) {
|
||||
this.config[i] = config[i];
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
D3D.Printer.prototype.getStartCode = function () {
|
||||
"use strict";
|
||||
|
||||
var gcode = this.config["printer.startcode"];
|
||||
gcode = this.subsituteVariables(gcode);
|
||||
|
||||
return gcode.split("\n");
|
||||
};
|
||||
D3D.Printer.prototype.getEndCode = function () {
|
||||
"use strict";
|
||||
|
||||
var gcode = this.config["printer.endcode"];
|
||||
|
||||
gcode = this.subsituteVariables(gcode);
|
||||
|
||||
return gcode.split("\n");
|
||||
};
|
||||
D3D.Printer.prototype.subsituteVariables = function (gcode) {
|
||||
"use strict";
|
||||
|
||||
var temperature = this.config["printer.temperature"];
|
||||
var bedTemperature = this.config["printer.bed.temperature"];
|
||||
var preheatTemperature = this.config["printer.heatup.temperature"];
|
||||
var preheatBedTemperature = this.config["printer.heatup.bed.temperature"];
|
||||
var printerType = this.config["printer.type"];
|
||||
var heatedbed = this.config["printer.heatedbed"];
|
||||
|
||||
switch (printerType) {
|
||||
case "makerbot_replicator2": printerType = "r2"; break;
|
||||
case "makerbot_replicator2x": printerType = "r2x"; break;
|
||||
case "makerbot_thingomatic": printerType = "t6"; break;
|
||||
case "makerbot_generic": printerType = "r2"; break;
|
||||
case "_3Dison_plus": printerType = "r2"; break;
|
||||
}
|
||||
var heatedBedReplacement = heatedbed ? "" : ";";
|
||||
|
||||
gcode = gcode.replace(/{printingTemp}/gi, temperature);
|
||||
gcode = gcode.replace(/{printingBedTemp}/gi, bedTemperature);
|
||||
gcode = gcode.replace(/{preheatTemp}/gi, preheatTemperature);
|
||||
gcode = gcode.replace(/{preheatBedTemp}/gi, preheatBedTemperature);
|
||||
gcode = gcode.replace(/{printerType}/gi, printerType);
|
||||
gcode = gcode.replace(/{if heatedBed}/gi, heatedBedReplacement);
|
||||
|
||||
return gcode;
|
||||
};
|
51
src/settings/default.yml
Normal file
51
src/settings/default.yml
Normal file
@ -0,0 +1,51 @@
|
||||
dimensions:
|
||||
x: 200
|
||||
y: 200
|
||||
z: 200
|
||||
temperature: 210
|
||||
bedTemperature: 70
|
||||
# heatBedTemperature: 20
|
||||
# heatTemperature: 20
|
||||
# heatupEnabled: true
|
||||
travelSpeed: 200.0
|
||||
layerHeight: 0.15
|
||||
heatedBed: false
|
||||
nozzleDiameter: 0.4
|
||||
filamentThickness: 2.85
|
||||
retraction:
|
||||
amount: 3.0
|
||||
enabled: true
|
||||
speed: 50.0
|
||||
minDistance: 0.0
|
||||
support:
|
||||
acceptanceMargin: 1.5
|
||||
distanceY: 0.4
|
||||
enabled: false
|
||||
gridSize: 6.0
|
||||
margin: 2.0
|
||||
plateSize: 4.0
|
||||
flowRate: 0.8
|
||||
speed: 40.0
|
||||
outerLine:
|
||||
flowRate: 1.0
|
||||
speed: 40.0
|
||||
innerLine:
|
||||
flowRate: 1.0
|
||||
speed: 50.0
|
||||
fill:
|
||||
flowRate: 1.0
|
||||
speed: 50.0
|
||||
overlap: 0.0
|
||||
gridSize: 5.0
|
||||
brim:
|
||||
flowRate: 1.0
|
||||
speed: 40.0
|
||||
offset: 4.0
|
||||
top:
|
||||
thickness: 1.2
|
||||
bottom:
|
||||
flowRate: 1.2
|
||||
speed: 40.0
|
||||
thickness: 0.4
|
||||
shell:
|
||||
thickness: 0.4
|
6
src/settings/material.yml
Normal file
6
src/settings/material.yml
Normal file
@ -0,0 +1,6 @@
|
||||
pla:
|
||||
title: PLA
|
||||
temperature: 210
|
||||
abs:
|
||||
title: ABS
|
||||
temperature: 240
|
171
src/settings/printer.yml
Normal file
171
src/settings/printer.yml
Normal file
@ -0,0 +1,171 @@
|
||||
_3Dison_plus:
|
||||
title: 3Dison plus
|
||||
dimensions:
|
||||
x: 227
|
||||
y: 147
|
||||
z: 150
|
||||
bigbuilder3d:
|
||||
title: Big Builder 3D
|
||||
builder3d:
|
||||
title: Builder 3D
|
||||
bukobot:
|
||||
title: Bukobot
|
||||
cartesio:
|
||||
title: Cartesio
|
||||
colido_2_0_plus:
|
||||
title: ColiDo 2.0 Plus
|
||||
heatedBed: true
|
||||
dimensions:
|
||||
x: 230
|
||||
y: 150
|
||||
z: 140
|
||||
colido_compact:
|
||||
title: ColiDo Compact
|
||||
dimensions:
|
||||
x: 130
|
||||
y: 130
|
||||
z: 115
|
||||
colido_diy:
|
||||
title: ColiDo DIY
|
||||
dimensions:
|
||||
z: 170
|
||||
colido_m2020:
|
||||
title: ColiDo M2020
|
||||
heatedBed: true
|
||||
colido_x3045:
|
||||
title: ColiDo X3045
|
||||
heatedBed: true
|
||||
dimensions:
|
||||
x: 300
|
||||
y: 300
|
||||
z: 450
|
||||
craftbot_plus:
|
||||
title: CraftBot PLUS
|
||||
heatedBed: true
|
||||
filamentThickness: 1.75
|
||||
dimensions:
|
||||
x: 250
|
||||
cyrus:
|
||||
title: Cyrus
|
||||
delta_rostockmax:
|
||||
title: Delta RostockMax
|
||||
dimensions:
|
||||
x: 0
|
||||
y: 0
|
||||
deltamaker:
|
||||
title: Deltamaker
|
||||
dimensions:
|
||||
x: 0
|
||||
y: 0
|
||||
doodle_dream:
|
||||
title: Doodle Dream
|
||||
filamentThickness: 1.75
|
||||
dimensions:
|
||||
x: 120
|
||||
y: 120
|
||||
z: 80
|
||||
eventorbot:
|
||||
title: EventorBot
|
||||
felix:
|
||||
title: Felix
|
||||
gigabot:
|
||||
title: Gigabot
|
||||
kossel:
|
||||
title: Kossel
|
||||
dimensions:
|
||||
x: 0
|
||||
y: 0
|
||||
leapfrog_creatr:
|
||||
title: LeapFrog Creatr
|
||||
lulzbot_aO_101:
|
||||
title: LulzBot AO-101
|
||||
lulzbot_taz_4:
|
||||
title: LulzBot TAZ 4
|
||||
dimensions:
|
||||
x: 298
|
||||
y: 275
|
||||
z: 250
|
||||
heatedBed: true
|
||||
makerbot_generic:
|
||||
title: Generic Makerbot Printer
|
||||
makerbot_replicator2:
|
||||
title: MakerBot Replicator2
|
||||
makerbot_replicator2x:
|
||||
title: MakerBot Replicator2x
|
||||
heatedBed: true
|
||||
makerbot_thingomatic:
|
||||
title: MakerBot Thing-o-matic
|
||||
makergear_m2:
|
||||
title: MakerGear M2
|
||||
makergear_prusa:
|
||||
title: MakerGear Prusa
|
||||
makibox:
|
||||
title: Makibox
|
||||
mamba3d:
|
||||
title: Mamba3D
|
||||
marlin_generic:
|
||||
title: Generic Marlin Printer
|
||||
minifactory:
|
||||
title: miniFactory
|
||||
dimensions:
|
||||
x: 150
|
||||
y: 150
|
||||
z: 155
|
||||
heatedBed: true
|
||||
orca_0_3:
|
||||
title: Orca 0.3
|
||||
ord_bot_hadron:
|
||||
title: ORD Bot Hadron
|
||||
printrbot:
|
||||
title: Printrbot
|
||||
printxel_3d:
|
||||
title: Printxel 3D
|
||||
prusa_i3:
|
||||
title: Prusa I3
|
||||
prusa_iteration_2:
|
||||
title: Prusa Iteration 2
|
||||
rapman:
|
||||
title: RapMan
|
||||
renkforce_rf100:
|
||||
title: Renkforce RF100
|
||||
filamentThickness: 1.75
|
||||
dimensions:
|
||||
x: 100
|
||||
y: 100
|
||||
z: 100
|
||||
reprappro_huxley:
|
||||
title: RepRapPro Huxley
|
||||
reprappro_mendel:
|
||||
title: RepRapPro Mendel
|
||||
rigidbot:
|
||||
title: Rigidbot
|
||||
robo_3d_printer:
|
||||
title: RoBo 3D Printer
|
||||
shapercube:
|
||||
title: ShaperCube
|
||||
tantillus:
|
||||
title: Tantillus
|
||||
ultimaker:
|
||||
title: Ultimaker Original
|
||||
ultimaker2:
|
||||
title: Ultimaker 2
|
||||
heatedBed: true
|
||||
ultimaker2go:
|
||||
title: Ultimaker 2 Go
|
||||
dimensions:
|
||||
x: 120
|
||||
y: 120
|
||||
z: 112
|
||||
ultimaker_original_plus:
|
||||
title: Ultimaker Original Plus
|
||||
heatedBed: true
|
||||
vision_3d_printer:
|
||||
title: Vision 3D Printer
|
||||
wanhao_duplicator4:
|
||||
title: Wanhao Duplicator 4
|
||||
filamentThickness: 1.75
|
||||
heatedBed: true
|
||||
dimensions:
|
||||
x: 210
|
||||
y: 140
|
||||
z: 140
|
11
src/settings/quality.yml
Normal file
11
src/settings/quality.yml
Normal file
@ -0,0 +1,11 @@
|
||||
low:
|
||||
title: "Low"
|
||||
layerHeight: .2
|
||||
fill:
|
||||
gridSize: 15.0
|
||||
medium:
|
||||
title: "Medium"
|
||||
layerHeight: .15
|
||||
high:
|
||||
title: "High"
|
||||
layerHeight: .1
|
23
src/sliceActions/addBrim.js
Normal file
23
src/sliceActions/addBrim.js
Normal file
@ -0,0 +1,23 @@
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
import { PRECISION } from '../constants.js';
|
||||
|
||||
const offsetOptions = {
|
||||
jointType: 'jtRound',
|
||||
miterLimit: 2.0,
|
||||
roundPrecision: 0.25
|
||||
};
|
||||
|
||||
export default function addBrim(slices, settings) {
|
||||
let { brim: { offset: brimOffset } } = settings;
|
||||
brimOffset /= PRECISION;
|
||||
|
||||
const [firstLayer] = slices;
|
||||
|
||||
firstLayer.brim = firstLayer.parts.reduce((brim, { shape }) => {
|
||||
brim.join(shape.offset(brimOffset, {
|
||||
...offsetOptions,
|
||||
endType: shape.closed ? 'etClosedPolygon' : 'etOpenRound'
|
||||
}));
|
||||
return brim;
|
||||
}, new Shape([], true)).simplify('pftNonZero');
|
||||
}
|
22
src/sliceActions/applyPrecision.js
Normal file
22
src/sliceActions/applyPrecision.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { PRECISION } from '../constants.js'
|
||||
|
||||
export default function applyPrecision(shapes) {
|
||||
for (let i = 0; i < shapes.length; i ++) {
|
||||
const { closedShapes, openShapes } = shapes[i];
|
||||
|
||||
scaleUpShape(closedShapes);
|
||||
scaleUpShape(openShapes);
|
||||
}
|
||||
}
|
||||
|
||||
function scaleUpShape(shape) {
|
||||
for (let i = 0; i < shape.length; i ++) {
|
||||
const path = shape[i];
|
||||
|
||||
for (let i = 0; i < path.length; i ++) {
|
||||
const point = path[i];
|
||||
|
||||
point.copy(point.divideScalar(PRECISION));
|
||||
}
|
||||
}
|
||||
}
|
43
src/sliceActions/calculateLayersIntersections.js
Normal file
43
src/sliceActions/calculateLayersIntersections.js
Normal file
@ -0,0 +1,43 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
export default function calculateLayersIntersections(lines, settings) {
|
||||
const { layerHeight, dimensions: { z: dimensionsZ } } = settings;
|
||||
|
||||
const numLayers = Math.floor(dimensionsZ / layerHeight);
|
||||
|
||||
const layerIntersectionIndexes = Array.from(Array(numLayers)).map(() => []);
|
||||
const layerIntersectionPoints = Array.from(Array(numLayers)).map(() => []);
|
||||
|
||||
for (let lineIndex = 0; lineIndex < lines.length; lineIndex ++) {
|
||||
const line = lines[lineIndex].line;
|
||||
|
||||
if (line.isFlat) continue;
|
||||
|
||||
const min = Math.ceil(Math.min(line.start.y, line.end.y) / layerHeight);
|
||||
const max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight);
|
||||
|
||||
for (let layerIndex = min; layerIndex <= max; layerIndex ++) {
|
||||
if (layerIndex >= 0 && layerIndex < numLayers) {
|
||||
|
||||
layerIntersectionIndexes[layerIndex].push(lineIndex);
|
||||
|
||||
const y = layerIndex * layerHeight;
|
||||
|
||||
let x, z;
|
||||
if (line.start.y === line.end.y) {
|
||||
x = line.start.x;
|
||||
z = line.start.z;
|
||||
} else {
|
||||
const alpha = (y - line.start.y) / (line.end.y - line.start.y);
|
||||
const alpha1 = 1 - alpha;
|
||||
x = line.end.x * alpha + line.start.x * alpha1;
|
||||
z = line.end.z * alpha + line.start.z * alpha1;
|
||||
}
|
||||
|
||||
layerIntersectionPoints[layerIndex][lineIndex] = new THREE.Vector2(z, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { layerIntersectionIndexes, layerIntersectionPoints };
|
||||
}
|
48
src/sliceActions/createLines.js
Normal file
48
src/sliceActions/createLines.js
Normal file
@ -0,0 +1,48 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
function addLine(geometry, lineLookup, lines, a, b, isFlat) {
|
||||
const index = lines.length;
|
||||
lineLookup[`${a}_${b}`] = index;
|
||||
|
||||
lines.push({
|
||||
line: new THREE.Line3(geometry.vertices[a], geometry.vertices[b]),
|
||||
connects: [],
|
||||
normals: [],
|
||||
isFlat
|
||||
});
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
export default function createLines(geometry, settings) {
|
||||
const lines = [];
|
||||
const lineLookup = {};
|
||||
|
||||
for (let i = 0; i < geometry.faces.length; i ++) {
|
||||
const face = geometry.faces[i];
|
||||
|
||||
const lookupA = lineLookup[`${face.b}_${face.a}`];
|
||||
const lookupB = lineLookup[`${face.c}_${face.b}`];
|
||||
const lookupC = lineLookup[`${face.a}_${face.c}`];
|
||||
|
||||
const isFlat = face.normal.y !== 1 && face.normal.y !== -1;
|
||||
|
||||
// only add unique lines
|
||||
// returns index of said line
|
||||
const lineIndexA = typeof lookupA !== 'undefined' ? lookupA : addLine(geometry, lineLookup, lines, face.a, face.b, isFlat);
|
||||
const lineIndexB = typeof lookupB !== 'undefined' ? lookupB : addLine(geometry, lineLookup, lines, face.b, face.c, isFlat);
|
||||
const lineIndexC = typeof lookupC !== 'undefined' ? lookupC : addLine(geometry, lineLookup, lines, face.c, face.a, isFlat);
|
||||
|
||||
// set connecting lines (based on face)
|
||||
lines[lineIndexA].connects.push(lineIndexB, lineIndexC);
|
||||
lines[lineIndexB].connects.push(lineIndexC, lineIndexA);
|
||||
lines[lineIndexC].connects.push(lineIndexA, lineIndexB);
|
||||
|
||||
const normal = new THREE.Vector2(face.normal.z, face.normal.x).normalize();
|
||||
lines[lineIndexA].normals.push(normal);
|
||||
lines[lineIndexB].normals.push(normal);
|
||||
lines[lineIndexC].normals.push(normal);
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
61
src/sliceActions/detectOpenClosed.js
Normal file
61
src/sliceActions/detectOpenClosed.js
Normal file
@ -0,0 +1,61 @@
|
||||
export default function detectOpenClosed(lines) {
|
||||
const pools = getPools(lines);
|
||||
const openLines = lines.map(line => line.connects.length === 2);
|
||||
|
||||
for (let i = 0; i < pools.length; i ++) {
|
||||
const pool = pools[i];
|
||||
|
||||
const isOpenGeometry = pool.some(lineIndex => openLines[lineIndex]);
|
||||
|
||||
for (let j = 0; j < pool.length; j ++) {
|
||||
const lineIndex = pool[j];
|
||||
const line = lines[lineIndex];
|
||||
line.openGeometry = isOpenGeometry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function findPool(pools, lines, lineIndex) {
|
||||
const { connects } = lines[lineIndex];
|
||||
for (let i = 0; i < pools.length; i ++) {
|
||||
const pool = pools[i];
|
||||
|
||||
if (pool.find(lineIndex => connects.includes(lineIndex))) {
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
|
||||
// no pool found
|
||||
// create new pool
|
||||
const pool = [];
|
||||
pools.push(pool);
|
||||
return pool;
|
||||
}
|
||||
|
||||
function getPools(lines) {
|
||||
const pools = [];
|
||||
|
||||
for (let lineIndex = 0; lineIndex < lines.length; lineIndex ++) {
|
||||
const pool = findPool(pools, lines, lineIndex);
|
||||
pool.push(lineIndex);
|
||||
}
|
||||
|
||||
for (let i = 0; i < pools.length; i ++) {
|
||||
const poolA = pools[i];
|
||||
|
||||
for (let j = i + 1; j < pools.length; j ++) {
|
||||
const poolB = pools[j];
|
||||
|
||||
for (let k = 0; k < poolA.length; k ++) {
|
||||
const { connects } = lines[poolA[k]];
|
||||
|
||||
if (poolB.find(lineIndex => connects.includes(lineIndex))) {
|
||||
poolA.splice(poolA.length, 0, ...poolB);
|
||||
poolB.splice(0, poolB.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pools.filter(pool => pool.length > 0);
|
||||
}
|
79
src/sliceActions/generateInfills.js
Normal file
79
src/sliceActions/generateInfills.js
Normal file
@ -0,0 +1,79 @@
|
||||
import { PRECISION } from '../constants.js'
|
||||
import getFillTemplate from './getFillTemplate.js';
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
|
||||
export default function generateInfills(slices, settings) {
|
||||
let {
|
||||
layerHeight,
|
||||
fill: { gridSize: fillGridSize },
|
||||
bottom: { thickness: bottomThickness },
|
||||
top: { thickness: topThickness },
|
||||
nozzleDiameter,
|
||||
fill: { overlap: infillOverlap }
|
||||
} = settings;
|
||||
|
||||
fillGridSize /= PRECISION;
|
||||
nozzleDiameter /= PRECISION;
|
||||
infillOverlap /= PRECISION;
|
||||
|
||||
const bottomSkinCount = Math.ceil(bottomThickness/layerHeight);
|
||||
const topSkinCount = Math.ceil(topThickness/layerHeight);
|
||||
const nozzleRadius = nozzleDiameter / 2;
|
||||
const hightemplateSize = Math.sqrt(2 * Math.pow(nozzleDiameter, 2));
|
||||
|
||||
for (let layer = 0; layer < slices.length; layer ++) {
|
||||
const slice = slices[layer];
|
||||
|
||||
let surroundingLayer;
|
||||
if (layer - bottomSkinCount >= 0 && layer + topSkinCount < slices.length) {
|
||||
const downSkin = slices[layer - bottomSkinCount].getOutline();
|
||||
const upSkin = slices[layer + topSkinCount].getOutline();
|
||||
surroundingLayer = upSkin.intersect(downSkin);
|
||||
}
|
||||
|
||||
for (let i = 0; i < slice.parts.length; i ++) {
|
||||
const part = slice.parts[i];
|
||||
|
||||
if (!part.shape.closed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const outerLine = part.outerLine;
|
||||
|
||||
if (outerLine.paths.length > 0) {
|
||||
const inset = (part.innerLines.length > 0) ? part.innerLines[part.innerLines.length - 1] : outerLine;
|
||||
|
||||
const fillArea = inset.offset(-nozzleRadius);
|
||||
let lowFillArea;
|
||||
let highFillArea;
|
||||
if (surroundingLayer) {
|
||||
highFillArea = fillArea.difference(surroundingLayer);
|
||||
|
||||
if (infillOverlap > 0) {
|
||||
highFillArea = highFillArea.offset(infillOverlap);
|
||||
}
|
||||
|
||||
highFillArea = highFillArea.intersect(fillArea);
|
||||
lowFillArea = fillArea.difference(highFillArea);
|
||||
} else {
|
||||
highFillArea = fillArea;
|
||||
}
|
||||
|
||||
if (lowFillArea && lowFillArea.paths.length > 0) {
|
||||
const bounds = lowFillArea.shapeBounds();
|
||||
const lowFillTemplate = getFillTemplate(bounds, fillGridSize, true, true);
|
||||
|
||||
part.fill.join(lowFillTemplate.intersect(lowFillArea));
|
||||
}
|
||||
|
||||
if (highFillArea.paths.length > 0) {
|
||||
const bounds = highFillArea.shapeBounds();
|
||||
const even = (layer % 2 === 0);
|
||||
const highFillTemplate = getFillTemplate(bounds, hightemplateSize, even, !even);
|
||||
|
||||
part.fill.join(highFillTemplate.intersect(highFillArea));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
src/sliceActions/generateInnerLines.js
Normal file
45
src/sliceActions/generateInnerLines.js
Normal file
@ -0,0 +1,45 @@
|
||||
import { PRECISION } from '../constants.js'
|
||||
|
||||
const offsetOptions = {
|
||||
jointType: 'jtSquare',
|
||||
endType: 'etClosedPolygon',
|
||||
miterLimit: 2.0,
|
||||
roundPrecision: 0.25
|
||||
};
|
||||
|
||||
export default function generateInnerLines(slices, settings) {
|
||||
// need to scale up everything because of clipper rounding errors
|
||||
let { layerHeight, nozzleDiameter, shell: { thickness: shellThickness } } = settings;
|
||||
nozzleDiameter /= PRECISION;
|
||||
shellThickness /= PRECISION;
|
||||
const nozzleRadius = nozzleDiameter / 2;
|
||||
const shells = Math.round(shellThickness / nozzleDiameter);
|
||||
|
||||
for (let layer = 0; layer < slices.length; layer ++) {
|
||||
const slice = slices[layer];
|
||||
|
||||
for (let i = 0; i < slice.parts.length; i ++) {
|
||||
const part = slice.parts[i];
|
||||
|
||||
if (!part.shape.closed) continue;
|
||||
|
||||
const outerLine = part.shape.offset(-nozzleRadius, offsetOptions);
|
||||
|
||||
if (outerLine.paths.length > 0) {
|
||||
part.outerLine.join(outerLine);
|
||||
|
||||
for (let shell = 1; shell < shells; shell += 1) {
|
||||
const offset = shell * nozzleDiameter;
|
||||
|
||||
const innerLine = outerLine.offset(-offset, offsetOptions);
|
||||
|
||||
if (innerLine.paths.length > 0) {
|
||||
part.innerLines.push(innerLine);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
src/sliceActions/generateSupport.js
Normal file
76
src/sliceActions/generateSupport.js
Normal file
@ -0,0 +1,76 @@
|
||||
import getFillTemplate from './getFillTemplate.js';
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
import { PRECISION } from '../constants.js';
|
||||
|
||||
export default function generateSupport(slices, settings) {
|
||||
if (!settings.support.enabled) return;
|
||||
|
||||
let {
|
||||
layerHeight,
|
||||
support: {
|
||||
gridSize: supportGridSize,
|
||||
margin: AcceptanceMargin,
|
||||
plateSize: plateSize,
|
||||
distanceY: DistanceY
|
||||
},
|
||||
nozzleDiameter
|
||||
} = settings;
|
||||
|
||||
supportGridSize /= PRECISION;
|
||||
supportMargin /= PRECISION;
|
||||
plateSize /= PRECISION;
|
||||
nozzleDiameter /= PRECISION;
|
||||
var supportDistanceLayers = Math.max(Math.ceil(supportDistanceY / layerHeight), 1);
|
||||
|
||||
var supportAreas = new Shape([], true);
|
||||
|
||||
for (var layer = slices.length - 1 - supportDistanceLayers; layer >= 0; layer --) {
|
||||
var currentSlice = slices[layer];
|
||||
|
||||
if (supportAreas.length > 0) {
|
||||
|
||||
if (layer >= supportDistanceLayers) {
|
||||
var sliceSkin = slices[layer - supportDistanceLayers].getOutline();
|
||||
sliceSkin = sliceSkin;
|
||||
|
||||
var supportAreasSlimmed = supportAreas.difference(sliceSkin.offset(supportMargin));
|
||||
if (supportAreasSlimmed.area() < 100.0) {
|
||||
supportAreas = supportAreas.difference(sliceSkin);
|
||||
}
|
||||
else {
|
||||
supportAreas = supportAreasSlimmed;
|
||||
}
|
||||
}
|
||||
|
||||
var supportTemplate = getFillTemplate(supportAreas.bounds(), supportGridSize, true, true);
|
||||
var supportFill = supportTemplate.intersect(supportAreas);
|
||||
if (supportFill.length === 0) {
|
||||
currentSlice.support = supportAreas.clone();
|
||||
}
|
||||
else {
|
||||
currentSlice.support = supportFill;
|
||||
}
|
||||
}
|
||||
|
||||
var supportSkin = slices[layer + supportDistanceLayers - 1].getOutline();
|
||||
|
||||
var slice = slices[layer + supportDistanceLayers];
|
||||
for (var i = 0; i < slice.parts.length; i ++) {
|
||||
var slicePart = slice.parts[i];
|
||||
|
||||
if (slicePart.intersect.closed) {
|
||||
var outerLine = slicePart.outerLine;
|
||||
}
|
||||
else {
|
||||
var outerLine = slicePart.intersect.offset(supportAcceptanceMargin);
|
||||
}
|
||||
|
||||
var overlap = supportSkin.offset(supportAcceptanceMargin).intersect(outerLine);
|
||||
var overhang = outerLine.difference(overlap);
|
||||
|
||||
if (overlap.length === 0 || overhang.length > 0) {
|
||||
supportAreas = supportAreas.join(overhang);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
src/sliceActions/getFillTemplate.js
Normal file
31
src/sliceActions/getFillTemplate.js
Normal file
@ -0,0 +1,31 @@
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
|
||||
export default function getFillTemplate(bounds, size, even, uneven) {
|
||||
const paths = [];
|
||||
|
||||
const left = Math.floor(bounds.left / size) * size;
|
||||
const right = Math.ceil(bounds.right / size) * size;
|
||||
const top = Math.floor(bounds.top / size) * size;
|
||||
const bottom = Math.ceil(bounds.bottom / size) * size;
|
||||
|
||||
const width = right - left;
|
||||
|
||||
if (even) {
|
||||
for (let y = top; y <= bottom + width; y += size) {
|
||||
paths.push([
|
||||
{ x: left, y },
|
||||
{ x: right, y: y - width }
|
||||
]);
|
||||
}
|
||||
}
|
||||
if (uneven) {
|
||||
for (let y = top - width; y <= bottom; y += size) {
|
||||
paths.push([
|
||||
{ x: left, y },
|
||||
{ x: right, y: y + width }
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return new Shape(paths, false, true, true);
|
||||
}
|
121
src/sliceActions/intersectionsToShapes.js
Normal file
121
src/sliceActions/intersectionsToShapes.js
Normal file
@ -0,0 +1,121 @@
|
||||
import * as THREE from 'three';
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
|
||||
export default function intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings) {
|
||||
const layers = [];
|
||||
|
||||
for (let layer = 1; layer < layerIntersectionIndexes.length; layer ++) {
|
||||
const intersectionIndexes = layerIntersectionIndexes[layer];
|
||||
const intersectionPoints = layerIntersectionPoints[layer];
|
||||
|
||||
if (intersectionIndexes.length === 0) continue;
|
||||
|
||||
const closedShapes = [];
|
||||
const openShapes = [];
|
||||
for (let i = 0; i < intersectionIndexes.length; i ++) {
|
||||
let index = intersectionIndexes[i];
|
||||
|
||||
if (typeof intersectionPoints[index] === 'undefined') continue;
|
||||
|
||||
const shape = [];
|
||||
|
||||
const firstPoints = [index];
|
||||
const { openGeometry } = lines[index];
|
||||
let isFirstPoint = true;
|
||||
let openShape = true;
|
||||
|
||||
while (index !== -1) {
|
||||
const intersection = intersectionPoints[index];
|
||||
// uppercase X and Y because clipper vector
|
||||
shape.push(intersection);
|
||||
|
||||
delete intersectionPoints[index];
|
||||
|
||||
const connects = lines[index].connects;
|
||||
const faceNormals = lines[index].normals;
|
||||
|
||||
for (let i = 0; i < connects.length; i ++) {
|
||||
index = connects[i];
|
||||
|
||||
if (firstPoints.includes(index) && shape.length > 2) {
|
||||
openShape = false;
|
||||
index = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if index has an intersection or is already used
|
||||
if (typeof intersectionPoints[index] !== 'undefined') {
|
||||
const faceNormal = faceNormals[Math.floor(i / 2)];
|
||||
|
||||
const a = new THREE.Vector2(intersection.x, intersection.y);
|
||||
const b = new THREE.Vector2(intersectionPoints[index].x, intersectionPoints[index].y);
|
||||
|
||||
// can't calculate normal between points if distance is smaller as 0.0001
|
||||
if ((faceNormal.x === 0 && faceNormal.y === 0) || a.distanceTo(b) < 0.0001) {
|
||||
if (isFirstPoint) {
|
||||
firstPoints.push(index);
|
||||
}
|
||||
|
||||
delete intersectionPoints[index];
|
||||
|
||||
connects.push(...lines[index].connects);
|
||||
faceNormals.push(...lines[index].normals);
|
||||
index = -1;
|
||||
} else {
|
||||
// make sure the path goes the right direction
|
||||
// THREE.Vector2.normal is not yet implimented
|
||||
// const normal = a.sub(b).normal().normalize();
|
||||
const normal = a.sub(b);
|
||||
normal.set(-normal.y, normal.x).normalize();
|
||||
|
||||
if (normal.dot(faceNormal) > 0) {
|
||||
break;
|
||||
} else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
isFirstPoint = false;
|
||||
}
|
||||
|
||||
if (openShape) {
|
||||
index = firstPoints[0];
|
||||
|
||||
while (index !== -1) {
|
||||
if (!firstPoints.includes(index)) {
|
||||
const intersection = intersectionPoints[index];
|
||||
shape.unshift(intersection);
|
||||
|
||||
delete intersectionPoints[index];
|
||||
}
|
||||
|
||||
const connects = lines[index].connects;
|
||||
|
||||
for (let i = 0; i < connects.length; i ++) {
|
||||
index = connects[i];
|
||||
|
||||
if (typeof intersectionPoints[index] !== 'undefined') {
|
||||
break;
|
||||
} else {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (openGeometry) {
|
||||
if (!openShape) shape.push(shape[0].clone());
|
||||
openShapes.push(shape);
|
||||
} else {
|
||||
closedShapes.push(shape);
|
||||
}
|
||||
}
|
||||
|
||||
layers.push({ closedShapes, openShapes });
|
||||
}
|
||||
|
||||
return layers;
|
||||
}
|
150
src/sliceActions/optimizePaths.js
Normal file
150
src/sliceActions/optimizePaths.js
Normal file
@ -0,0 +1,150 @@
|
||||
import * as THREE from 'three';
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
|
||||
export default function optimizePaths(slices, settings) {
|
||||
const start = new THREE.Vector2(0, 0);
|
||||
|
||||
for (let layer = 0; layer < slices.length; layer ++) {
|
||||
const slice = slices[layer];
|
||||
|
||||
if (typeof slice.brim !== 'undefined' && slice.brim.paths.length > 0) {
|
||||
slice.brim = optimizeShape(slice.brim, start);
|
||||
start.copy(slice.brim.lastPoint(true));
|
||||
}
|
||||
|
||||
const parts = [];
|
||||
|
||||
while (slice.parts.length > 0) {
|
||||
let closestDistance = Infinity;
|
||||
let closestPart;
|
||||
|
||||
for (let i = 0; i < slice.parts.length; i ++) {
|
||||
const part = slice.parts[i];
|
||||
|
||||
let bounds;
|
||||
if (part.shape.closed) {
|
||||
bounds = part.outerLine.shapeBounds();
|
||||
} else {
|
||||
bounds = part.shape.shapeBounds();
|
||||
}
|
||||
|
||||
const top = bounds.top - start.y;
|
||||
const bottom = start.y - bounds.bottom;
|
||||
const left = bounds.left - start.x;
|
||||
const right = start.x - bounds.right;
|
||||
|
||||
const distance = Math.max(top, bottom, left, right);
|
||||
|
||||
if (distance < closestDistance) {
|
||||
closestDistance = distance;
|
||||
closestPart = i;
|
||||
}
|
||||
}
|
||||
|
||||
const part = slice.parts.splice(closestPart, 1)[0];
|
||||
parts.push(part);
|
||||
|
||||
if (part.shape.closed) {
|
||||
if (part.outerLine.paths.length > 0) {
|
||||
part.outerLine = optimizeShape(part.outerLine, start);
|
||||
start.copy(part.outerLine.lastPoint(true));
|
||||
}
|
||||
|
||||
for (let i = 0; i < part.innerLines.length; i ++) {
|
||||
const innerLine = part.innerLines[i];
|
||||
|
||||
if (innerLine.paths.length > 0) {
|
||||
part.innerLines[i] = optimizeShape(innerLine, start);
|
||||
start.copy(part.innerLines[i].lastPoint(true));
|
||||
}
|
||||
}
|
||||
|
||||
if (part.fill.paths.length > 0) {
|
||||
part.fill = optimizeShape(part.fill, start);
|
||||
start.copy(part.fill.lastPoint(true));
|
||||
}
|
||||
} else {
|
||||
part.shape = optimizeShape(part.shape, start);
|
||||
start.copy(part.shape.lastPoint(true));
|
||||
}
|
||||
}
|
||||
|
||||
slice.parts = parts;
|
||||
|
||||
if (typeof slice.support !== 'undefined' && slice.support.length > 0) {
|
||||
slice.support = optimizeShape(slice.support, start);
|
||||
start.copy(slice.support.lastPoint(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function optimizeShape(shape, start) {
|
||||
start = start.clone();
|
||||
|
||||
const inputPaths = shape.mapToLower();
|
||||
const optimizedPaths = [];
|
||||
const donePaths = [];
|
||||
|
||||
while (optimizedPaths.length !== inputPaths.length) {
|
||||
let minLength = false;
|
||||
let reverse;
|
||||
let minPath;
|
||||
let offset;
|
||||
let pathIndex;
|
||||
|
||||
for (let i = 0; i < inputPaths.length; i ++) {
|
||||
if (donePaths.includes(i)) continue;
|
||||
|
||||
const path = inputPaths[i];
|
||||
|
||||
if (shape.closed) {
|
||||
for (let j = 0; j < path.length; j += 1) {
|
||||
const point = new THREE.Vector2().copy(path[j]);
|
||||
const length = point.sub(start).length();
|
||||
if (minLength === false || length < minLength) {
|
||||
minPath = path;
|
||||
minLength = length;
|
||||
offset = j;
|
||||
pathIndex = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const startPoint = new THREE.Vector2().copy(path[0]);
|
||||
const lengthToStart = startPoint.sub(start).length();
|
||||
if (minLength === false || lengthToStart < minLength) {
|
||||
minPath = path;
|
||||
minLength = lengthToStart;
|
||||
reverse = false;
|
||||
pathIndex = i;
|
||||
}
|
||||
|
||||
const endPoint = new THREE.Vector2().copy(path[path.length - 1]);
|
||||
const lengthToEnd = endPoint.sub(start).length();
|
||||
if (lengthToEnd < minLength) {
|
||||
minPath = path;
|
||||
minLength = lengthToEnd;
|
||||
reverse = true;
|
||||
pathIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let point;
|
||||
if (shape.closed) {
|
||||
minPath = minPath.concat(minPath.splice(0, offset));
|
||||
point = minPath[0];
|
||||
} else {
|
||||
if (reverse) {
|
||||
minPath.reverse();
|
||||
}
|
||||
point = minPath[minPath.length - 1];
|
||||
}
|
||||
|
||||
donePaths.push(pathIndex);
|
||||
start.copy(point);
|
||||
|
||||
optimizedPaths.push(minPath);
|
||||
}
|
||||
|
||||
return new Shape(optimizedPaths, shape.closed, true, false);
|
||||
}
|
31
src/sliceActions/removePrecision.js
Normal file
31
src/sliceActions/removePrecision.js
Normal file
@ -0,0 +1,31 @@
|
||||
import { PRECISION } from '../constants.js';
|
||||
|
||||
const inversePrecision = 1 / PRECISION;
|
||||
|
||||
export default function removePrecision(slices) {
|
||||
for (let layer = 0; layer < slices.length; layer ++) {
|
||||
const slice = slices[layer];
|
||||
|
||||
for (let i = 0; i < slice.parts.length; i ++) {
|
||||
const part = slice.parts[i];
|
||||
|
||||
if (part.shape.closed) {
|
||||
part.outerLine.scaleDown(inversePrecision);
|
||||
for (let i = 0; i < part.innerLines.length; i ++) {
|
||||
const innerLine = part.innerLines[i];
|
||||
innerLine.scaleDown(inversePrecision);
|
||||
}
|
||||
part.fill.scaleDown(inversePrecision);
|
||||
} else {
|
||||
part.shape.scaleDown(inversePrecision);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof slice.support !== 'undefined') {
|
||||
slice.support.scaleDown(inversePrecision);
|
||||
}
|
||||
if (typeof slice.brim !== 'undefined') {
|
||||
slice.brim.scaleDown(inversePrecision);
|
||||
}
|
||||
}
|
||||
}
|
45
src/sliceActions/shapesToSlices.js
Normal file
45
src/sliceActions/shapesToSlices.js
Normal file
@ -0,0 +1,45 @@
|
||||
import Shape from 'Doodle3D/clipper-js';
|
||||
import Slice from '../Slice.js';
|
||||
|
||||
import { CLEAN_DELTA, PRECISION } from '../constants.js';
|
||||
|
||||
const cleanDelta = CLEAN_DELTA / PRECISION;
|
||||
|
||||
export default function shapesToSlices(shapes, settings) {
|
||||
const sliceLayers = [];
|
||||
|
||||
for (let layer = 0; layer < shapes.length; layer ++) {
|
||||
let { closedShapes, openShapes } = shapes[layer];
|
||||
|
||||
closedShapes = new Shape(closedShapes, true, true, true, true)
|
||||
.fixOrientation()
|
||||
.simplify('pftNonZero')
|
||||
.clean(cleanDelta)
|
||||
.seperateShapes();
|
||||
|
||||
openShapes = new Shape(openShapes, false, true, true, true);
|
||||
// .clean(cleanDelta);
|
||||
// TODO
|
||||
// Cleaning is actually wanted here but there is a bug in the clean function
|
||||
// https://sourceforge.net/p/jsclipper/tickets/16/
|
||||
|
||||
const slice = new Slice();
|
||||
|
||||
for (let i = 0; i < closedShapes.length; i ++) {
|
||||
const closedShape = closedShapes[i];
|
||||
slice.add(closedShape);
|
||||
|
||||
// if (openShapes.path.length > 0) {
|
||||
// openShapes = openShapes.difference(closedShape);
|
||||
// }
|
||||
}
|
||||
|
||||
if (openShapes.paths.length > 0) {
|
||||
slice.add(openShapes);
|
||||
}
|
||||
|
||||
sliceLayers.push(slice);
|
||||
}
|
||||
|
||||
return sliceLayers;
|
||||
}
|
65
src/sliceActions/slice.js
Normal file
65
src/sliceActions/slice.js
Normal file
@ -0,0 +1,65 @@
|
||||
import calculateLayersIntersections from './calculateLayersIntersections.js';
|
||||
import createLines from './createLines.js';
|
||||
import generateInfills from './generateInfills.js';
|
||||
import generateInnerLines from './generateInnerLines.js';
|
||||
import generateSupport from './generateSupport.js';
|
||||
import intersectionsToShapes from './intersectionsToShapes.js';
|
||||
import addBrim from './addBrim.js';
|
||||
import optimizePaths from './optimizePaths.js';
|
||||
import shapesToSlices from './shapesToSlices.js';
|
||||
import slicesToGCode from './slicesToGCode.js';
|
||||
import detectOpenClosed from './detectOpenClosed.js';
|
||||
import applyPrecision from './applyPrecision.js';
|
||||
import removePrecision from './removePrecision.js';
|
||||
|
||||
export default function(geometry, settings, onProgress) {
|
||||
const totalStages = 11;
|
||||
let current = -1;
|
||||
const updateProgress = (action) => {
|
||||
current ++;
|
||||
if (onProgress) onProgress({ done: current, total: totalStages, action });
|
||||
};
|
||||
|
||||
geometry.computeFaceNormals();
|
||||
|
||||
// get unique lines from geometry;
|
||||
updateProgress('Constructing unique lines from geometry');
|
||||
const lines = createLines(geometry, settings);
|
||||
|
||||
updateProgress('Detecting open vs closed shapes');
|
||||
const openClosed = detectOpenClosed(lines);
|
||||
|
||||
updateProgress('Calculating layer intersections');
|
||||
const {
|
||||
layerIntersectionIndexes,
|
||||
layerIntersectionPoints
|
||||
} = calculateLayersIntersections(lines, settings);
|
||||
|
||||
updateProgress('Constructing shapes from intersections');
|
||||
const shapes = intersectionsToShapes(layerIntersectionIndexes, layerIntersectionPoints, lines, settings);
|
||||
|
||||
applyPrecision(shapes);
|
||||
|
||||
updateProgress('Constructing slices from shapes');
|
||||
const slices = shapesToSlices(shapes, settings);
|
||||
|
||||
updateProgress('Generating inner lines');
|
||||
generateInnerLines(slices, settings);
|
||||
updateProgress('Generating infills');
|
||||
generateInfills(slices, settings);
|
||||
updateProgress('Generating support');
|
||||
generateSupport(slices, settings);
|
||||
updateProgress('Adding brim');
|
||||
addBrim(slices, settings);
|
||||
updateProgress('Optimizing paths');
|
||||
optimizePaths(slices, settings);
|
||||
|
||||
removePrecision(slices);
|
||||
|
||||
updateProgress('Constructing gcode');
|
||||
const gcode = slicesToGCode(slices, settings);
|
||||
|
||||
updateProgress('Finished');
|
||||
|
||||
return gcode;
|
||||
}
|
72
src/sliceActions/slicesToGCode.js
Normal file
72
src/sliceActions/slicesToGCode.js
Normal file
@ -0,0 +1,72 @@
|
||||
import GCode from '../GCode.js';
|
||||
|
||||
export default function slicesToGCode(slices, settings) {
|
||||
const gcode = new GCode(settings);
|
||||
|
||||
for (let layer = 0; layer < slices.length; layer ++) {
|
||||
const slice = slices[layer];
|
||||
|
||||
if (layer === 1) {
|
||||
gcode.turnFanOn();
|
||||
gcode.bottom = false;
|
||||
}
|
||||
|
||||
if (typeof slice.brim !== 'undefined') {
|
||||
pathToGCode(gcode, slice.brim, true, true, layer, 'brim');
|
||||
}
|
||||
|
||||
for (let i = 0; i < slice.parts.length; i ++) {
|
||||
const part = slice.parts[i];
|
||||
|
||||
if (part.shape.closed) {
|
||||
pathToGCode(gcode, part.outerLine, false, true, layer, 'outerLine');
|
||||
|
||||
for (let i = 0; i < part.innerLines.length; i ++) {
|
||||
const innerLine = part.innerLines[i];
|
||||
pathToGCode(gcode, innerLine, false, false, layer, 'innerLine');
|
||||
}
|
||||
|
||||
pathToGCode(gcode, part.fill, true, false, layer, 'fill');
|
||||
} else {
|
||||
const retract = !(slice.parts.length === 1 && typeof slice.support === 'undefined');
|
||||
pathToGCode(gcode, part.shape, retract, retract, layer, 'outerLine');
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof slice.support !== 'undefined') {
|
||||
pathToGCode(gcode, slice.support, true, true, layer, 'support');
|
||||
}
|
||||
}
|
||||
|
||||
return gcode.getGCode();
|
||||
}
|
||||
|
||||
function pathToGCode(gcode, shape, retract, unRetract, layer, type) {
|
||||
const { closed } = shape;
|
||||
const paths = shape.mapToLower();
|
||||
|
||||
for (let i = 0; i < paths.length; i ++) {
|
||||
const line = paths[i];
|
||||
|
||||
const length = closed ? (line.length + 1) : line.length;
|
||||
for (let i = 0; i < length; i ++) {
|
||||
const point = line[i % line.length];
|
||||
|
||||
if (i === 0) {
|
||||
// TODO
|
||||
// moveTo should impliment combing
|
||||
gcode.moveTo(point.x, point.y, layer);
|
||||
|
||||
if (unRetract) {
|
||||
gcode.unRetract();
|
||||
}
|
||||
} else {
|
||||
gcode.lineTo(point.x, point.y, layer, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retract) {
|
||||
gcode.retract();
|
||||
}
|
||||
}
|
589
src/slicer.js
589
src/slicer.js
@ -1,589 +0,0 @@
|
||||
/******************************************************
|
||||
*
|
||||
* Slicer
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
D3D.Slicer = function () {
|
||||
"use strict";
|
||||
|
||||
this.progress = {
|
||||
totalFaces: 0,
|
||||
currentFace: 0,
|
||||
totalLayers: 0,
|
||||
sliceLayer: 0,
|
||||
dataLayer: 0,
|
||||
gcodeLayer: 0
|
||||
};
|
||||
};
|
||||
D3D.Slicer.prototype.setMesh = function (geometry, matrix) {
|
||||
"use strict";
|
||||
|
||||
//convert buffergeometry to geometry;
|
||||
if (geometry instanceof THREE.BufferGeometry) {
|
||||
geometry = new THREE.Geometry().fromBufferGeometry(geometry);
|
||||
}
|
||||
|
||||
//apply mesh matrix on geometry;
|
||||
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;
|
||||
this.createLines();
|
||||
|
||||
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) {
|
||||
var index = lineLookup[b + "_" + a];
|
||||
|
||||
if (index === undefined) {
|
||||
index = self.lines.length;
|
||||
lineLookup[a + "_" + b] = index;
|
||||
|
||||
self.lines.push({
|
||||
line: new THREE.Line3(self.geometry.vertices[a], self.geometry.vertices[b]),
|
||||
connects: [],
|
||||
normals: []
|
||||
});
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
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().set(face.normal.z, face.normal.x).normalize();
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
this.progress.currentFace = i;
|
||||
this.updateProgress();
|
||||
}
|
||||
};
|
||||
D3D.Slicer.prototype.slice = function (layerHeight, height) {
|
||||
"use strict";
|
||||
var numLayers = height / layerHeight;
|
||||
|
||||
var layersIntersections = [];
|
||||
|
||||
for (var lineIndex = 0; lineIndex < this.lines.length; lineIndex ++) {
|
||||
var line = this.lines[lineIndex].line;
|
||||
|
||||
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);
|
||||
|
||||
for (var layerIndex = min; layerIndex <= max; layerIndex ++) {
|
||||
if (layerIndex >= 0 && layerIndex < numLayers) {
|
||||
if (layersIntersections[layerIndex] === undefined) {
|
||||
layersIntersections[layerIndex] = [];
|
||||
}
|
||||
layersIntersections[layerIndex].push(lineIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var slices = [];
|
||||
|
||||
//still error in first layer, so remove first layer & last layer
|
||||
//see https://github.com/Doodle3D/Doodle3D-Slicer/issues/1
|
||||
for (var layer = 0; layer < layersIntersections.length; layer ++) {
|
||||
var layerIntersections = layersIntersections[layer];
|
||||
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;
|
||||
|
||||
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 = [];
|
||||
var slice = [];
|
||||
for (var i = 0; i < layerIntersections.length; i ++) {
|
||||
var index = layerIntersections[i];
|
||||
|
||||
if (done.indexOf(index) === -1) {
|
||||
var shape = [];
|
||||
|
||||
while (index !== -1) {
|
||||
var intersection = intersections[index];
|
||||
shape.push({X: intersection.x, Y: intersection.y});
|
||||
|
||||
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] !== undefined && done.indexOf(index) === -1) {
|
||||
done.push(index);
|
||||
|
||||
var a = new THREE.Vector2(intersection.x, intersection.y);
|
||||
var b = intersections[index];
|
||||
|
||||
if (a.distanceTo(b) === 0) {
|
||||
connects = connects.concat(this.lines[index].connects);
|
||||
faceNormals = faceNormals.concat(this.lines[index].normals);
|
||||
index = -1;
|
||||
}
|
||||
else {
|
||||
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 {
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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 --;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//think this check is not nescesary, always higher as 0
|
||||
if (shape.length > 0) {
|
||||
slice.push(new D3D.Paths([shape], true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var layerParts = [];
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
var layerPart1 = slice[i];
|
||||
var merge = false;
|
||||
|
||||
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);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
this.progress.sliceLayer = layer;
|
||||
this.updateProgress();
|
||||
}
|
||||
return slices;
|
||||
};
|
||||
D3D.Slicer.prototype.slicesToData = function (slices, printer) {
|
||||
"use strict";
|
||||
|
||||
var scale = 100;
|
||||
|
||||
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"];
|
||||
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 lowFillTemplate = 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
|
||||
}, 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);
|
||||
|
||||
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];
|
||||
|
||||
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);
|
||||
|
||||
var fill = new D3D.Paths([], false);
|
||||
|
||||
if (lowFillTemplate.length > 0) {
|
||||
fill.join(lowFillTemplate.intersect(lowFillArea));
|
||||
}
|
||||
|
||||
if (highFillArea.length > 0) {
|
||||
var bounds = highFillArea.bounds();
|
||||
var even = (layer % 2 === 0);
|
||||
var highFillTemplate = this.getFillTemplate(bounds, nozzleDiameter, even, !even);
|
||||
fill.join(highFillTemplate.intersect(highFillArea));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
currentSlice[0].support = supportTemplate.intersect(supportAreas).join(supportAreas.clone());
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
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;
|
||||
};
|
||||
D3D.Slicer.prototype.dataToGCode = function (data, printer) {
|
||||
"use strict";
|
||||
|
||||
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 length = path.closed ? (shape.length + 1) : shape.length;
|
||||
|
||||
for (var j = 0; j < length; j ++) {
|
||||
var point = shape[j % shape.length];
|
||||
|
||||
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) {
|
||||
gcode.turnFanOn();
|
||||
gcode.bottom = false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < slice.length; i ++) {
|
||||
var layerPart = slice[i];
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
return gcode.getGCode();
|
||||
};
|
||||
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);
|
||||
var end = new Date().getTime();
|
||||
console.log("Slicing: " + (end - start) + "ms");
|
||||
|
||||
start = new Date().getTime();
|
||||
var data = this.slicesToData(slices, printer);
|
||||
end = new Date().getTime();
|
||||
console.log("Data: " + (end - start) + "ms");
|
||||
|
||||
start = new Date().getTime();
|
||||
var gcode = this.dataToGCode(data, printer);
|
||||
end = new Date().getTime();
|
||||
console.log("Gcode: " + (end - start) + "ms");
|
||||
|
||||
return gcode;
|
||||
};
|
30
src/slicerWorker.js
Normal file
30
src/slicerWorker.js
Normal file
@ -0,0 +1,30 @@
|
||||
import slice from './sliceActions/slice.js';
|
||||
import * as THREE from 'three';
|
||||
|
||||
const loader = new THREE.JSONLoader();
|
||||
|
||||
const onProgress = progress => {
|
||||
self.postMessage({
|
||||
message: 'PROGRESS',
|
||||
data: progress
|
||||
});
|
||||
}
|
||||
|
||||
self.addEventListener('message', (event) => {
|
||||
const { message, data } = event.data;
|
||||
switch (message) {
|
||||
case 'SLICE': {
|
||||
const { geometry: JSONGeometry, settings } = data;
|
||||
|
||||
const { geometry } = new loader.parse(JSONGeometry.data);
|
||||
|
||||
const gcode = slice(geometry, settings, onProgress);
|
||||
|
||||
self.postMessage({
|
||||
message: 'SLICE',
|
||||
data: { gcode }
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, false);
|
@ -1,78 +0,0 @@
|
||||
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'
|
||||
});
|
||||
};
|
151
src/utils.js
151
src/utils.js
@ -1,151 +0,0 @@
|
||||
/******************************************************
|
||||
*
|
||||
* Utils
|
||||
* dependices Three.js
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
var D3D = {
|
||||
"version": "0.1",
|
||||
"website": "http://www.doodle3d.com/",
|
||||
"contact": "develop@doodle3d.com"
|
||||
};
|
||||
|
||||
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",
|
||||
data: data,
|
||||
dataType: "json",
|
||||
timeout: 10000,
|
||||
success: function (response) {
|
||||
if (response.status === "success") {
|
||||
if (callback !== undefined) {
|
||||
callback(response.data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.warn(response.msg);
|
||||
}
|
||||
}
|
||||
}).fail(function () {
|
||||
console.warn("Failed connecting to " + url);
|
||||
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",
|
||||
timeout: 5000,
|
||||
success: function (response) {
|
||||
if (response.status === "success") {
|
||||
if (callback !== undefined) {
|
||||
callback(response.data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.warn(response.msg);
|
||||
}
|
||||
}
|
||||
}).fail(function () {
|
||||
console.warn("Failed connecting to " + url);
|
||||
getAPI(url, callback);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function loadSettings (url, callback) {
|
||||
"use strict";
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
if (callback !== undefined) {
|
||||
callback(response);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function downloadFile (file, data) {
|
||||
"use strict";
|
||||
|
||||
var blob = new Blob([data], {type:'text/plain'});
|
||||
|
||||
var button = document.createElement("a");
|
||||
button.download = file;
|
||||
button.href = window.URL.createObjectURL(blob);
|
||||
button.click();
|
||||
}
|
||||
|
||||
Array.prototype.clone = function () {
|
||||
"use strict";
|
||||
var array = [];
|
||||
|
||||
for (var i = 0; i < this.length; i ++) {
|
||||
array[i] = this[i];
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
self.addEventListener("message", function (event) {
|
||||
"use strict";
|
||||
|
||||
//console.log(event.data);
|
||||
|
||||
if (event.data === "close") {
|
||||
self.close();
|
||||
}
|
||||
});
|
@ -1,57 +0,0 @@
|
||||
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;
|
||||
|
||||
}
|
||||
});
|
@ -1,74 +0,0 @@
|
||||
<!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>
|
@ -1,19 +0,0 @@
|
||||
----------- 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"
|
@ -1,207 +0,0 @@
|
||||
<!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