comments and tweaks on belt slicing

This commit is contained in:
Stewart Allen 2024-07-06 15:40:58 -04:00
commit 9aae90880c
6 changed files with 53 additions and 52 deletions

View file

@ -258,6 +258,7 @@ FDM.init = function(kiri, api) {
updateVisiblity(); updateVisiblity();
// synth support widget for each widget group // synth support widget for each widget group
// iow, create support meshes based on support widget annotation
let synth = []; let synth = [];
for (let group of kiri.Widget.Groups.list()) { for (let group of kiri.Widget.Groups.list()) {
let merge = group.filter(w => w.sups).map(w => Object.values(w.sups)).flat(); let merge = group.filter(w => w.sups).map(w => Object.values(w.sups)).flat();
@ -290,10 +291,9 @@ FDM.init = function(kiri, api) {
} }
}); });
api.event.on("key.esc", () => { api.event.on("key.esc", () => {
if (!isFdmMode) { if (isFdmMode) {
return; func.sdone()
} }
func.sdone()
}); });
api.event.on("selection.scale", () => { api.event.on("selection.scale", () => {
if (isFdmMode) { if (isFdmMode) {
@ -304,7 +304,6 @@ FDM.init = function(kiri, api) {
api.event.on("widget.delete", widget => { api.event.on("widget.delete", widget => {
if (isFdmMode) { if (isFdmMode) {
clearRanges(); clearRanges();
return;
} }
}); });
api.event.on("widget.duplicate", (widget, oldwidget) => { api.event.on("widget.duplicate", (widget, oldwidget) => {

View file

@ -13,9 +13,9 @@
// dep: kiri-mode.fdm.driver // dep: kiri-mode.fdm.driver
gapp.register("kiri-mode.fdm.prepare", [], (root, exports) => { gapp.register("kiri-mode.fdm.prepare", [], (root, exports) => {
const { base, kiri, noop } = root; const { base, kiri } = root;
const { consts, driver, newSlice, utils, render } = kiri; const { consts, driver, newSlice, render } = kiri;
const { config, polygons, paths, util, newPoint, newPolygon, Polygon } = base; const { polygons, paths, util, newPoint, newPolygon, Polygon } = base;
const { poly2polyEmit, tip2tipEmit } = paths; const { poly2polyEmit, tip2tipEmit } = paths;
const { numOrDefault } = util; const { numOrDefault } = util;
const { fillArea } = polygons; const { fillArea } = polygons;
@ -34,10 +34,10 @@ FDM.prepare = async function(widgets, settings, update) {
// filter ignored widgets // filter ignored widgets
widgets = widgets.filter(w => !w.track.ignore && !w.meta.disabled); widgets = widgets.filter(w => !w.track.ignore && !w.meta.disabled);
let { device, process, controller, bounds, mode } = settings, let { device, process, controller, bounds } = settings,
{ sliceHeight, firstSliceHeight, firstLayerRate, sliceSupportOutline } = process, { sliceHeight, firstSliceHeight, firstLayerRate } = process,
{ outputSeekrate, outputDraftShield, outputPurgeTower } = process, { outputSeekrate, outputDraftShield, outputPurgeTower } = process,
{ bedWidth, bedDepth, filamentSource } = device, { bedWidth, bedDepth } = device,
{ lineType } = controller, { lineType } = controller,
printPoint = newPoint(0,0,0), printPoint = newPoint(0,0,0),
print = self.worker.print = kiri.newPrint(settings, widgets), print = self.worker.print = kiri.newPrint(settings, widgets),
@ -45,7 +45,6 @@ FDM.prepare = async function(widgets, settings, update) {
isBelt = device.bedBelt, isBelt = device.bedBelt,
isThin = lineType === "line", isThin = lineType === "line",
isFlat = lineType === "flat", isFlat = lineType === "flat",
isPalette = filamentSource === 'palette3',
useRaft = process.outputRaft || false, useRaft = process.outputRaft || false,
firstLayerHeight = isBelt ? sliceHeight : firstSliceHeight || sliceHeight, firstLayerHeight = isBelt ? sliceHeight : firstSliceHeight || sliceHeight,
layerno = 0, layerno = 0,
@ -135,14 +134,14 @@ FDM.prepare = async function(widgets, settings, update) {
POLY.expand(brims, nozzle * 4, 0, null, 1) : brims; POLY.expand(brims, nozzle * 4, 0, null, 1) : brims;
function raft(height, angle, spacing, speed, extrude, outline) { function raft(height, angle, spacing, speed, extrude, outline) {
let slice = kiri.newSlice(zoff + height / 2); let slice = newSlice(zoff + height / 2);
for (let brim of rafts) { for (let brim of rafts) {
// use first point of first brim as start point // use first point of first brim as start point
if (printPoint === null) printPoint = brim.first(); if (printPoint === null) printPoint = brim.first();
let t = slice.addTop(brim); let t = slice.addTop(brim);
if (outline) t.traces = [ brim ]; if (outline) t.traces = [ brim ];
t.inner = POLY.expand([ brim ], nozzle * -0.8, 0, null, 1); t.inner = POLY.expand([ brim ], nozzle * -0.8, 0, null, 1);
t.fill_lines = POLY.fillArea(t.inner, angle, spacing, []); t.fill_lines = fillArea(t.inner, angle, spacing, []);
t.isRaft = true; t.isRaft = true;
} }
offset.z = slice.z; offset.z = slice.z;
@ -238,7 +237,7 @@ FDM.prepare = async function(widgets, settings, update) {
if (!slice.supports) { if (!slice.supports) {
continue; continue;
} }
let sslice = kiri.newSlice(slice.z); let sslice = newSlice(slice.z);
sslice.extruder = process.sliceSupportNozzle; sslice.extruder = process.sliceSupportNozzle;
sslice.supports = slice.supports.slice(); sslice.supports = slice.supports.slice();
sslice.height = slice.height; sslice.height = slice.height;
@ -315,10 +314,10 @@ FDM.prepare = async function(widgets, settings, update) {
noz = exi.extNozzle, noz = exi.extNozzle,
pos = {x:blokpos.x + walkpos.x * i, y:blokpos.y + walkpos.y * i, z:0}, pos = {x:blokpos.x + walkpos.x * i, y:blokpos.y + walkpos.y * i, z:0},
rect = newPolygon().centerRectangle(pos, blok.x, blok.y), rect = newPolygon().centerRectangle(pos, blok.x, blok.y),
full = linesToPoly(POLY.fillArea([ full = linesToPoly(fillArea([
newPolygon().centerRectangle(pos, blok.x - noz, blok.y - noz) newPolygon().centerRectangle(pos, blok.x - noz, blok.y - noz)
], angle, noz)), ], angle, noz)),
sparse = rect.area() > 10 ? linesToPoly(POLY.fillArea([ sparse = rect.area() > 10 ? linesToPoly(fillArea([
newPolygon().centerRectangle(pos, blok.x - noz, blok.y - noz) newPolygon().centerRectangle(pos, blok.x - noz, blok.y - noz)
], angle + 90, noz * thin)) : newPolygon(), ], angle + 90, noz * thin)) : newPolygon(),
rec = { rec = {

View file

@ -596,9 +596,12 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
} }
} }
} }
// experimental emboss text on a flat underside of an object
// in belt mode only
if (process.pooch && self.OffscreenCanvas) { if (process.pooch && self.OffscreenCanvas) {
const { length, width, height, text } = process.pooch; const { length, width, height, text } = process.pooch;
let firstZ, firstI, lastZ, lastI, minX = 0, maxX = 0, maxY = 0; let firstZ, firstI, lastZ, lastI, minX = 0, maxX = 0, maxY = 0;
// locate suitable flat spot
for (let slice of slices) { for (let slice of slices) {
let { belt } = slice; let { belt } = slice;
if (!belt.touch) { if (!belt.touch) {

View file

@ -271,13 +271,6 @@ kiri.worker = {
cache: wcache, cache: wcache,
decimate(data, send) {
let { vertices, options } = data;
vertices = new Float32Array(vertices),
vertices = base.pointsToVertices(base.verticesToPoints(vertices, options));
send.done(vertices);
},
snap(data, send) { snap(data, send) {
current.snap = data; current.snap = data;
send.done(); send.done();
@ -297,6 +290,7 @@ kiri.worker = {
} }
}, },
// purge all sync data
clear(data, send) { clear(data, send) {
// current.snap = null; // current.snap = null;
current.print = null; current.print = null;
@ -346,6 +340,7 @@ kiri.worker = {
send.done(data.id); send.done(data.id);
}, },
// belt mode rotate widgets 45 degrees on X axis before slicing
rotate(data, send) { rotate(data, send) {
let { settings } = data; let { settings } = data;
if (!settings.device.bedBelt) { if (!settings.device.bedBelt) {

View file

@ -137,15 +137,6 @@ const client = exports({
restarting = false; restarting = false;
}, },
decimate(vertices, options, callback) {
let alert = kiri.api.show.alert('processing model', 1000);
vertices = vertices.buffer.slice(0);
send("decimate", {vertices, options}, (output) => {
kiri.api.hide.alert(alert);
callback(output);
});
},
config(obj) { config(obj) {
send("config", obj, noop); send("config", obj, noop);
}, },
@ -171,27 +162,27 @@ const client = exports({
// send list of currently valid widgets // send list of currently valid widgets
send("sync", { valid: widgets.map(w => w.id) }, () => {}); send("sync", { valid: widgets.map(w => w.id) }, () => {});
// sync any widget that has changed // sync any widget that has changed
widgets.forEach(widget => { for (let widget of widgets.filter(w => w.modified || !syncd[w.id])) {
if (widget.modified || !syncd[widget.id]) { syncd[widget.id] = true;
syncd[widget.id] = true; let vertices = widget.getGeoVertices();
let vertices = widget.getGeoVertices(); send("sync", {
send("sync", { id: widget.id,
id: widget.id, meta: widget.meta,
meta: widget.meta, group: widget.group.id,
group: widget.group.id, track: widget.track,
track: widget.track, vertices: copy ? vertices.slice() : vertices,
vertices: copy ? vertices.slice() : vertices, position: widget.mesh.position,
position: widget.mesh.position, }, done => {
}, done => { widget.modified = false;
widget.modified = false; });
}); }
}
});
}, },
// for belt / angled printing
rotate(settings, callback) { rotate(settings, callback) {
send("rotate", { settings }, reply => { send("rotate", { settings }, reply => {
if (reply.group) { if (reply.group) {
// collect post-rotation data for slice/preview renders
for (let widget of kiri.Widget.Groups.forid(reply.group)) { for (let widget of kiri.Widget.Groups.forid(reply.group)) {
widget.belt = reply.belt; widget.belt = reply.belt;
} }
@ -201,6 +192,7 @@ const client = exports({
}); });
}, },
// called once for each widget
slice(settings, widget, callback) { slice(settings, widget, callback) {
send("slice", { send("slice", {
id: widget.id, id: widget.id,
@ -217,10 +209,13 @@ const client = exports({
}); });
}, },
// called once after each widget is sliced
// performs merged actions that consider all widget slice data
sliceAll(settings, callback) { sliceAll(settings, callback) {
send("sliceAll", { settings }, callback); send("sliceAll", { settings }, callback);
}, },
// turn widget slices into unified path output
prepare(settings, update, done) { prepare(settings, update, done) {
send("prepare", { settings }, reply => { send("prepare", { settings }, reply => {
if (reply.progress) { if (reply.progress) {
@ -235,6 +230,7 @@ const client = exports({
}); });
}, },
// convert path output to gcode or other target file output
export(settings, online, ondone) { export(settings, online, ondone) {
send("export", { settings }, reply => { send("export", { settings }, reply => {
if (reply.line) { if (reply.line) {

View file

@ -27,12 +27,15 @@ function prepareSlices(callback, scale = 1, offset = 0) {
const { stacks } = kiri; const { stacks } = kiri;
if (view.is_arrange()) { if (view.is_arrange()) {
// in arrange mode, create a screenshot at the start slicing
// this can be used later by exports and rendered on some devices
let snap = space.screenshot(); let snap = space.screenshot();
view.snapshot = snap.substring(snap.indexOf(",") + 1); view.snapshot = snap.substring(snap.indexOf(",") + 1);
client.snap(space.screenshot2({width: 640})); client.snap(space.screenshot2({width: 640}));
} }
if (mode.is_sla() && !callback) { if (mode.is_sla() && !callback) {
// in SLA mode, slice and preview are the same thing
callback = preparePreview; callback = preparePreview;
} }
@ -43,6 +46,7 @@ function prepareSlices(callback, scale = 1, offset = 0) {
const mark = Date.now(); const mark = Date.now();
// force layout in belt mode when widget exceeds bed length // force layout in belt mode when widget exceeds bed length
// which has the side-effect (intended) of increasing the bed size
if (widgets.length && isBelt) { if (widgets.length && isBelt) {
let doLayout = false; let doLayout = false;
for (let w of widgets) { for (let w of widgets) {
@ -115,18 +119,23 @@ function prepareSlices(callback, scale = 1, offset = 0) {
stacks.clear(); stacks.clear();
if (isBelt) { if (isBelt) {
// force re-sync in belt mode // clearing cache causes data to be re-sent to worker
client.clear(); client.clear();
// we send copies of vertices in belt mode only (possibly obsolete?)
client.sync(undefined, true);
// belt op required to rotate meshes for slicing
client.rotate(settings);
} else {
// send updated vertices if widget has been rotated/scaled
client.sync();
} }
client.sync(undefined, isBelt);
client.rotate(settings);
function sliceNext() { function sliceNext() {
if (toSlice.length) { if (toSlice.length) {
// while more widgets to slice // while more widgets to slice
sliceWidget(toSlice.shift()) sliceWidget(toSlice.shift())
} else { } else {
// once all slicing done, run sliceAll() once // once all slicing done, run sliceAll() once for all widgets
client.sliceAll(settings, sliceDone); client.sliceAll(settings, sliceDone);
} }
} }