checkpoint sla work

This commit is contained in:
Stewart Allen 2020-04-14 15:57:34 -04:00
commit f9d650284c
6 changed files with 230 additions and 36 deletions

View file

@ -291,16 +291,22 @@ let gs_kiri_conf = exports;
bedWidth: 150,
bedDepth: 150,
bedHeight: 2.5,
maxHeight: 150,
originCenter: false
maxHeight: 150
},
// process defaults SLA:Process
p:{
processName: "default",
slaSlice: 0.05,
slaBottoms: 5,
slaSolids: 5,
slaTops: 5
slaShell: 1.00,
slaOpenTop: false,
slaOpenBase: false,
slaLayerOn: 8,
slaLayerOff: 1,
slaBaseLayers: 8,
slaBaseOn: 90,
slaPeelDist: 6,
slaPeelLift: 3,
slaPeelDrop: 3
}
},
cam:{

View file

@ -105,8 +105,19 @@ let gs_kiri_sla = exports;
layermax = Math.max(widget.slices.length);
});
function polyout(poly, ctx) {
poly.forEachPoint((p,i) => {
if (i === 0) {
ctx.moveTo(p.y * scaleY + height2, p.x * scaleX + width2);
} else {
ctx.lineTo(p.y * scaleY + height2, p.x * scaleX + width2);
}
}, true);
ctx.closePath();
}
for (let index=0; index < layermax; index++) {
let layer = new OffscreenCanvas(width,height);
let layer = new OffscreenCanvas(height,width);
let ctx = layer.getContext('2d');
ctx.fillStyle = 'rgb(200, 0, 0)';
let count = 0;
@ -115,25 +126,23 @@ let gs_kiri_sla = exports;
if (slice) {
slice.tops.map(top => top.poly).forEach(poly => {
ctx.beginPath();
poly.forEachPoint((p,i) => {
if (i === 0) {
ctx.moveTo(p.x * scaleX + width2, p.y * scaleY + height2);
} else {
ctx.lineTo(p.x * scaleX + width2, p.y * scaleY + height2);
}
}, true);
polyout(poly.setClockwise(), ctx);
if (poly.inner) {
poly.inner.forEach(inner => {
polyout(inner.setCounterClockwise(), ctx);
});
}
ctx.fill();
count++;
});
}
});
output.push(ctx.getImageData(0,0,width,height));
output.push(ctx.getImageData(0,0,height,width));
update(index / layermax);
if (count === 0) break;
}
// in theory sends back pre-gcode print preview data
update(1);
};
@ -154,8 +163,6 @@ let gs_kiri_sla = exports;
online(image.data, [image.data.buffer]);
});
// in theory converts print data from printSetup to gcode
// online("pex.line");
ondone({width:2560,height:1440});
};
@ -193,26 +200,24 @@ let gs_kiri_sla = exports;
}
// runs in browser main
function printDownload(API, lines, done) {
let filename = "print-"+(new Date().getTime().toString(36));
function printDownload(print) {
let { API, lines, done } = print.sla;
let filename = `print-${new Date().getTime().toString(36)}`;
API.ajax("/kiri/output-sla.html", html => {
API.ui.print.innerHTML = html;
$('print-filename').value = filename;
$('print-layers').value = lines.length;
$('print-close').onclick = API.modal.hide;
$('print-photons').onclick = download_photons;
$('print-photon').onclick = download_photon;
$('print-pws').onclick = download_pws;
$('print-photons').onclick = () => { download_photons(print) };
// $('print-photon').onclick = () => { download_photon(print) };
// $('print-pws').onclick = () => { download_pws(print) };
let canvas = $('print-canvas');
let ctx = canvas.getContext('2d');
let img = ctx.createImageData(done.width, done.height);
let img = ctx.createImageData(done.height, done.width);
let imgDV = new DataView(img.data.buffer);
// canvas.setAttribute('width', done.width/2);
// canvas.setAttribute('height', done.height/2);
let range = $('print-range');
range.value = 0;
range.min = 0;
@ -225,12 +230,180 @@ let gs_kiri_sla = exports;
ctx.putImageData(img,0,0);
};
range.oninput();
API.modal.show('print');
});
}
function download_photons() { }
function download_photon() { }
function download_pws() { }
function download_photons(print) {
let printset = print.settings,
process = printset.process,
device = printset.device,
width = print.sla.done.width,
height = print.sla.done.height,
layerCount = print.sla.lines.length,
layerBytes = width * height;
let converted = print.sla.lines.map((line, index) => {
let count = line.length / 4;
let bits = new Uint8Array(line.length / 4);
let bitsDV = new DataView(bits.buffer);
let lineDV = new DataView(line.buffer);
// reduce RGB to R
for (let i = 0; i < count; i++) {
// defeat anti-aliasing for the moment
bitsDV.setUint8(i, lineDV.getUint8(i * 4) > 0 ? 1 : 0);
}
return {
subs: [{
exposureTime: process.slaLayerOn,
data: bits
}]
};
});
let layers = encodeLayers(converted, "photons");
let filebuf = new ArrayBuffer(75366 + layers.length + 28 * layerCount);
let filedat = new DataView(filebuf);
let filePos = 0;
filedat.setUint32 (0, 2, false);
filedat.setUint32 (4, 3227560, false);
filedat.setUint32 (8, 824633720, false);
filedat.setUint16 (12, 10, false);
filedat.setFloat64(14, process.slaSlice, false);
filedat.setFloat64(22, process.slaLayerOn, false);
filedat.setFloat64(30, process.slaLayerOff, false);
filedat.setFloat64(38, process.slaBaseOn, false);
filedat.setUint32 (46, process.slaBaseLayers, false);
filedat.setFloat64(50, process.slaPeelDist, false);
filedat.setFloat64(58, process.slaPeelLift, false);
filedat.setFloat64(66, process.slaPeelDrop, false);
filedat.setFloat64(74, 69420, false);
filedat.setUint32 (82, 224, false);
filedat.setUint32 (86, 42, false);
filedat.setUint32 (90, 168, false);
filedat.setUint32 (94, 10, false);
filedat.setUint32 (75362, layerCount, false);
filePos = 75366;
for (let i = 0; i < layerCount; i++) {
let layer = layers.layers[i],
sublayer = layer.sublayers[0],
numbytes = sublayer.length;
filedat.setUint32 (filePos + 0, 69420, false);
filedat.setFloat64(filePos + 4, 0);
filedat.setUint32 (filePos + 12, height, false);
filedat.setUint32 (filePos + 16, width, false);
filedat.setUint32 (filePos + 20, numbytes * 8 + 32, false);
filedat.setUint32 (filePos + 24, 2684702720, false);
filePos += 28;
for (let j = 0; j < numbytes; j++) {
filedat.setUint8(filePos + j, sublayer[j]);
}
filePos += numbytes;
}
saveAs(
new Blob([filebuf], { type: "application/octet-stream" }),
$('print-filename').value + ".photons");
print.sla.API.modal.hide();
}
function download_photon() {
}
function download_pws() {
}
function encodeLayers(input, type) {
let layers = [],
length = 0;
for (let index = 0; index < input.length; index++) {
let subs = input[index].subs,
sublayers = [],
sublength = 0;
for (let subindex = 0; subindex < subs.length; subindex++) {
let data = subs[subindex].data;
let encoded = rleEncode(data, type);
sublength += encoded.length;
sublayers.push(encoded);
if (type == "photons") break;
}
length += sublength;
layers.push({
sublength,
sublayers
});
}
return {
length,
layers
};
}
function rleEncode(data, type) {
let maxlen = (type === 'photons') ? 128 : 125,
color = data[0],
runlen = 1,
output = [];
for (let index = 1; index < data.length; index++) {
let newColor = data[index];
if (newColor !== color) {
output.push(rleByte(color, runlen, type));
color = newColor;
runlen = 1;
} else {
if (runlen === maxlen) {
output.push(rleByte(color, runlen, type));
runlen = 1;
} else {
runlen++;
}
}
}
if (runlen > 0) {
output.push(rleByte(color, runlen, type));
}
return output;
}
function rleByte(color, length, type) {
switch (type) {
case 'pws':
case 'photon':
return length | (color * 128);
case 'photons':
length--;
return (length & 1 ? 128 : 0) |
(length & 2 ? 64 : 0) |
(length & 4 ? 32 : 0) |
(length & 8 ? 16 : 0) |
(length & 16 ? 8 : 0) |
(length & 32 ? 4 : 0) |
(length & 64 ? 2 : 0) | color;
}
}
function rleDecode(data) {
let bytes = [];
for (let i = 0; i < data.length; i++) {
let val = data[i],
col = val & 1,
count =
((val & 128 ? 1 : 0) |
(val & 64 ? 2 : 0) |
(val & 32 ? 4 : 0) |
(val & 16 ? 8 : 0) |
(val & 8 ? 16 : 0) |
(val & 4 ? 32 : 0) |
(val & 2 ? 64 : 0)) + 1;
for (let j = 0; j < count; j++) {
bytes.push(col);
}
}
return bytes;
}
})();

View file

@ -42,7 +42,8 @@ let gs_kiri_export = exports;
currentPrint.export(true, function(line) {
lines.push(line);
}, function(done) {
KIRI.driver.SLA.printDownload(API, lines, done);
currentPrint.sla = { lines, done, API };
KIRI.driver.SLA.printDownload(currentPrint);
});
} else {
API.function.print(exportPrintSLA);

View file

@ -1435,11 +1435,19 @@ var gs_kiri_init = exports;
outputLayerRetract: UC.newBoolean(LANG.ad_lret_s, onBooleanClick, {title:LANG.ad_lret_l, modes:FDM, expert:true}),
// SLA
slaProc: UC.newGroup('slaproc', null, {modes:SLA}),
slaSlice: UC.newInput('slice height', {title:'slice height', convert:UC.toFloat, modes:SLA}),
slaBottoms: UC.newInput('bottom layers', {title:'bottom layers', convert:UC.toInt, modes:SLA}),
slaSolids: UC.newInput('solid layers', {title:'solid layers', convert:UC.toInt, modes:SLA}),
slaTops: UC.newInput('top layers', {title:'bottom layers', convert:UC.toInt, modes:SLA}),
slaProc: UC.newGroup('sla slice', null, {modes:SLA}),
slaSlice: UC.newInput('layer height', {title:'slice height', convert:UC.toFloat, modes:SLA}),
slaShell: UC.newInput('hollow shell', {title:'shell thickness in mm\nuse multiple of layer height\nuse 0 for solid', convert:UC.toInt, modes:SLA}),
slaOpenTop: UC.newBoolean('open top', onBooleanClick, {title:'solid layers', modes:SLA}),
slaOpenBase: UC.newBoolean('open base', onBooleanClick, {title:'bottom layers', modes:SLA}),
slaOutput: UC.newGroup('sla output', null, {modes:SLA}),
slaLayerOn: UC.newInput('layer on', {title:'layer light on\ntime in seconds', convert:UC.toFloat, modes:SLA}),
slaLayerOff: UC.newInput('layer off', {title:'layer light off\ntime in seconds', convert:UC.toFloat, modes:SLA}),
slaBaseLayers: UC.newInput('base count', {title:'number of\bbase layers', convert:UC.toInt, modes:SLA}),
slaBaseOn: UC.newInput('base on', {title:'base layer light\non time in seconds', convert:UC.toFloat, modes:SLA}),
slaPeelDist: UC.newInput('peel dist', {title:'peel distance\nin millimeters', convert:UC.toFloat, modes:SLA}),
slaPeelLift: UC.newInput('peel lift', {title:'peel lift speed\nin mm/sec', convert:UC.toFloat, modes:SLA}),
slaPeelDrop: UC.newInput('peel drop', {title:'peel drop speed\nin mm/sec', convert:UC.toFloat, modes:SLA}),
});
if (!LOCAL) {

View file

@ -12,12 +12,14 @@
<div class="print-sel">
<table>
<tr><th><button id="print-photons">download as .photons</button></th></tr>
<!--
<tr><th><button id="print-photon">download as .photon</button></th></tr>
<tr><th><button id="print-pws">download as .pws</button></th></tr>
-->
</table>
</div>
<div class="print-sel">
<canvas id="print-canvas" width="2560" height="1440"></canvas>
<input id="print-range" type="range">
<canvas id="print-canvas" width="1440" height="2560"></canvas>
</div>

View file

@ -270,6 +270,10 @@ input[type=range]::-moz-focus-outer {
.print-sel th {
text-align: right !important;
}
#print-canvas {
width: 360px;
height: 640px;
}
#print-range {
width: 90%;
}