|
@@ -18,6 +18,8 @@ var settings = new SLAcer.Settings({ |
|
|
off: 500
|
|
|
},
|
|
|
zip: true,
|
|
|
+ svg: false,
|
|
|
+ png: true,
|
|
|
speed: false,
|
|
|
speedDelay: 10, // ms
|
|
|
panel: {
|
|
@@ -163,10 +165,6 @@ function getSlice(layerNumber) { |
|
|
shape = shapes[i];
|
|
|
slice = shape.clone();
|
|
|
|
|
|
- if (settings.get('slicer.mirror')) {
|
|
|
- slice.applyMatrix(new THREE.Matrix4().makeScale(-1, 1, 1));
|
|
|
- }
|
|
|
-
|
|
|
slice.material = slice.material.clone();
|
|
|
slice.material.color.setHex(0xffffff);
|
|
|
viewer2d.addObject(slice);
|
|
@@ -185,12 +183,93 @@ function getSlice(layerNumber) { |
|
|
viewer2d.screenshot(function(dataURL) {
|
|
|
sliceImage(dataURL);
|
|
|
|
|
|
- if (zipFolder) {
|
|
|
+ if (PNGExport) {
|
|
|
var fileName = layerNumber + '.png';
|
|
|
var imgData = dataURL.substr(dataURL.indexOf(',') + 1);
|
|
|
zipFolder.file(fileName, imgData, { base64: true });
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ // SVG export
|
|
|
+ if (SVGExport) {
|
|
|
+ // offset for positive coords
|
|
|
+ var xOffset = Math.abs(slicer.mesh.geometry.boundingBox.min.x);
|
|
|
+ var yOffset = Math.abs(slicer.mesh.geometry.boundingBox.min.y);
|
|
|
+
|
|
|
+ function SVGPath(actions, dir) {
|
|
|
+ var path = [];
|
|
|
+ var area = 0;
|
|
|
+ var a, b, c, x, y;
|
|
|
+
|
|
|
+ if (dir != 'ccw') {
|
|
|
+ dir = 'cw';
|
|
|
+ }
|
|
|
+
|
|
|
+ actions.push({ action: 'lineTo', args: actions[0].args });
|
|
|
+
|
|
|
+ for (var i = 0, il = actions.length; i < il; i++) {
|
|
|
+ a = actions[i];
|
|
|
+
|
|
|
+ if (i > 0) {
|
|
|
+ b = actions[i - 1];
|
|
|
+ area += a.args[0] * b.args[1];
|
|
|
+ area -= b.args[0] * a.args[1];
|
|
|
+ }
|
|
|
+
|
|
|
+ c = a.action == 'moveTo' ? 'M' : 'L';
|
|
|
+ x = (a.args[0] + xOffset);
|
|
|
+ y = (a.args[1] + yOffset);
|
|
|
+
|
|
|
+ path.push(c + x + ' ' + y);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dir == 'cw' && area < 0 || dir == 'ccw' && area > 0) {
|
|
|
+ path = path.reverse();
|
|
|
+ path[0] = path[0].replace(/^L/, 'M');
|
|
|
+ path[actions.length - 1] = path[actions.length - 1].replace(/^M/, 'L');
|
|
|
+ }
|
|
|
+
|
|
|
+ return path.join(' ') + ' Z ';
|
|
|
+ }
|
|
|
+
|
|
|
+ // svg start
|
|
|
+ var size = slicer.mesh.getSize();
|
|
|
+ var svg = '<svg version="1.1" width="' + size.x + '" height="' + size.y + '" baseProfile="full" xmlns="http://www.w3.org/2000/svg">\n';
|
|
|
+
|
|
|
+ // svg background
|
|
|
+ svg += '<rect x="0" y="0" width="100%" height="100%" style="fill:black; stroke:none"/>\n';
|
|
|
+
|
|
|
+ // fix coordinate system (rotate 180°)
|
|
|
+ svg += '<g transform="translate(0, ' + size.y + ') scale(1, -1)">\n';
|
|
|
+
|
|
|
+ // draw main paths
|
|
|
+ var actions;
|
|
|
+ for (var i = 0, il = faces.shapes.length; i < il; i++) {
|
|
|
+ actions = faces.shapes[i].actions;
|
|
|
+
|
|
|
+ // path start
|
|
|
+ svg += '<path d="';
|
|
|
+
|
|
|
+ // main paths
|
|
|
+ svg += SVGPath(actions, 'cw');
|
|
|
+
|
|
|
+ // holes paths
|
|
|
+ var holes = faces.shapes[i].holes;
|
|
|
+ for (var j = 0, jl = holes.length; j < jl; j++) {
|
|
|
+ svg += SVGPath(holes[j].actions, 'ccw');
|
|
|
+ }
|
|
|
+
|
|
|
+ // path end
|
|
|
+ svg += '" style="fill:white; stroke:none" />\n';
|
|
|
+ }
|
|
|
+
|
|
|
+ // svg end
|
|
|
+ svg += '</g>';
|
|
|
+ svg += '</svg>';
|
|
|
+
|
|
|
+ // add svg file to zip
|
|
|
+ zipFolder.file(layerNumber + '.svg', svg);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
@@ -392,6 +471,9 @@ var $slicerLiftingHeight = $slicerBody.find('#slicer-lifting-height'); |
|
|
var $slicerMirrorYes = $slicerBody.find('#slicer-mirror-yes');
|
|
|
var $slicerMirrorNo = $slicerBody.find('#slicer-mirror-no');
|
|
|
|
|
|
+var $slicerExportPNG = $slicerBody.find('#slicer-image-extension-png');
|
|
|
+var $slicerExportSVG = $slicerBody.find('#slicer-image-extension-svg');
|
|
|
+
|
|
|
var $slicerSpeedYes = $slicerBody.find('#slicer-speed-yes');
|
|
|
var $slicerSpeedNo = $slicerBody.find('#slicer-speed-no');
|
|
|
var $slicerSpeedDelay = $slicerBody.find('#slicer-speed-delay');
|
|
@@ -423,6 +505,9 @@ function updateSlicerSettings() { |
|
|
|
|
|
settings.set('slicer.mirror', $slicerMirrorYes[0].checked);
|
|
|
|
|
|
+ settings.set('slicer.png', $slicerExportPNG[0].checked);
|
|
|
+ settings.set('slicer.svg', $slicerExportSVG[0].checked);
|
|
|
+
|
|
|
settings.set('slicer.zip', $slicerMakeZipYes[0].checked);
|
|
|
settings.set('slicer.speed', $slicerSpeedYes[0].checked);
|
|
|
settings.set('slicer.speedDelay', $slicerSpeedDelay.val());
|
|
@@ -432,13 +517,24 @@ function updateSlicerSettings() { |
|
|
updateSliderUI();
|
|
|
}
|
|
|
|
|
|
+function flipGeometry() {
|
|
|
+ loadGeometry(slicer.mesh.geometry, true);
|
|
|
+ getSlice($sliderInput.slider('getValue'));
|
|
|
+}
|
|
|
+
|
|
|
+$slicerMirrorYes.on('change', flipGeometry);
|
|
|
+$slicerMirrorNo.on('change', flipGeometry);
|
|
|
+
|
|
|
var sliceInterval;
|
|
|
var expectedSliceInterval;
|
|
|
var currentSliceNumber;
|
|
|
var slicesNumber;
|
|
|
var zipFile;
|
|
|
var zipFolder;
|
|
|
|
|
|
+var SVGExport;
|
|
|
+var PNGExport;
|
|
|
+
|
|
|
var layerHeight;
|
|
|
var zPosition;
|
|
|
|
|
@@ -494,13 +590,15 @@ function startSlicing() { |
|
|
|
|
|
zipFile = null;
|
|
|
zipFolder = null;
|
|
|
+ SVGExport = null;
|
|
|
+ PNGExport = null;
|
|
|
|
|
|
if (settings.get('slicer.zip')) {
|
|
|
zipFile = new JSZip();
|
|
|
zipFolder = zipFile.folder('slices');
|
|
|
zipFile.file("README.txt", 'Generated by SLAcer.js\r\nhttp://lautr3k.github.io/SLAcer.js/\r\n');
|
|
|
zipFile.file("slacer.json", JSON.stringify({
|
|
|
- imageExtension: '.png',
|
|
|
+ imageExtension: settings.get('slicer.png') ? 'png' : 'svg',
|
|
|
imageDirectory: 'slices',
|
|
|
screenWidth : settings.get('screen.width'),
|
|
|
screenHeight : settings.get('screen.height'),
|
|
@@ -512,6 +610,8 @@ function startSlicing() { |
|
|
liftingSpeed : parseInt(settings.get('slicer.lifting.speed')), // mm/min
|
|
|
liftingHeight : parseInt(settings.get('slicer.lifting.height')) // mm
|
|
|
}, null, 2));
|
|
|
+ SVGExport = settings.get('slicer.svg');
|
|
|
+ PNGExport = settings.get('slicer.png');
|
|
|
}
|
|
|
|
|
|
slicesNumber && slice();
|
|
@@ -543,6 +643,7 @@ $abortButton.on('click', function(e) { |
|
|
endSlicing();
|
|
|
});
|
|
|
|
|
|
+$('#slicer-image-extension-' + (settings.get('slicer.png') ? 'png' : 'svg')).prop('checked', true);
|
|
|
$('#slicer-mirror-' + (settings.get('slicer.mirror') ? 'yes' : 'no')).prop('checked', true);
|
|
|
$('#slicer-make-zip-' + (settings.get('slicer.zip') ? 'yes' : 'no')).prop('checked', true);
|
|
|
$('#slicer-speed-' + (settings.get('slicer.speed') ? 'yes' : 'no')).prop('checked', true);
|
|
@@ -881,17 +982,22 @@ resizeUI(); |
|
|
var loader = new MeshesJS.STLLoader($main[0]); // drop target
|
|
|
|
|
|
// Load an geometry
|
|
|
-function loadGeometry(geometry) {
|
|
|
+function loadGeometry(geometry, mirror) {
|
|
|
try {
|
|
|
// remove old mesh and plane
|
|
|
slicer.mesh && viewer3d.removeObject(slicer.mesh);
|
|
|
|
|
|
// remove old shapes
|
|
|
removeShapes();
|
|
|
|
|
|
+ // flip geometry
|
|
|
+ if (mirror || settings.get('slicer.mirror')) {
|
|
|
+ geometry.applyMatrix(new THREE.Matrix4().makeScale(-1, 1, 1));
|
|
|
+ }
|
|
|
+
|
|
|
// load new mesh in slicer
|
|
|
slicer.loadMesh(new SLAcer.Mesh(geometry, new THREE.MeshPhongMaterial({
|
|
|
- color: hexToDec(settings.get('colors.mesh'))
|
|
|
+ color: hexToDec(settings.get('colors.mesh')), side: THREE.DoubleSide
|
|
|
})));
|
|
|
|
|
|
// add new mesh and render view
|
|
|
0 comments on commit
2c44d83