From e10450a5ea048d3bac6523551c068ead5d80f575 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 8 Jul 2025 19:20:55 -0400 Subject: [PATCH] fixup cam minion slicing, api settings cross compatibility --- src/kiri-mode/cam/slicer.js | 39 ++---------------- src/kiri-run/minion.js | 79 ++++++++++++++++++++++++++----------- src/kiri-run/worker.js | 41 ++++++++++--------- src/kiri/settings.js | 36 ++++++++--------- src/moto/broker.js | 6 ++- 5 files changed, 102 insertions(+), 99 deletions(-) diff --git a/src/kiri-mode/cam/slicer.js b/src/kiri-mode/cam/slicer.js index 2a08bb42..7c749cd9 100644 --- a/src/kiri-mode/cam/slicer.js +++ b/src/kiri-mode/cam/slicer.js @@ -1,8 +1,7 @@ /** Copyright Stewart Allen -- All Rights Reserved */ import { base, util } from '../../geo/base.js'; -import { broker } from '../../moto/broker.js'; -import { decode, decodePointArray, encode, encodePointArray } from '../../kiri/codec.js'; +import { decode, decodePointArray } from '../../kiri/codec.js'; import { newLine, newOrderedLine } from '../../geo/line.js'; import { newPoint } from '../../geo/point.js'; import { newSlice } from '../../kiri/slice.js'; @@ -23,20 +22,17 @@ const end = function () { export class Slicer { constructor(widget, options = { zlist: true, zline: true, lines: false }) { - this.minions = self.kiri_worker.minions; + this.minions = self.kiri_worker?.minions; this.options = {}; this.setOptions(options); if (widget) { + this.threaded = widget.settings.controller.threaded; this.setPoints(widget.getGeoVertices({ unroll: true, translate: true })); this.computeFeatures(); } } - get threaded() { - return this.options.threaded; - } - // zList = generate list of z vertices // zline = generate list of z vertices with coplanar lines // trace = find z coplanar trace lines @@ -480,32 +476,3 @@ function makeZLine(phash, p1, p2, coplanar, edge) { Slicer.checkOverUnderOn = checkOverUnderOn; Slicer.intersectPoints = intersectPoints; - -broker.subscribe("minion.started", msg => { - const { funcs, cache, reply, log } = msg; - - funcs.cam_slice_init = () => { - cache.slicer = new Slicer(); - }; - - funcs.cam_slice_cleanup = () => { - delete cache.slicer; - }; - - funcs.cam_slice = (data, seq) => { - const { bucket, opt } = data; - // log({ slice: bucket, opt }); - cache.slicer.sliceBucket(bucket, opt, slice => { - // console.log({ slice }); - }).then(data => { - data.forEach(rec => { - rec.polys = encode(rec.polys); - if (rec.lines) { - const points = rec.lines.map(l => [l.p1, l.p2]).flat(); - rec.lines = encodePointArray(points); - } - }); - reply({ seq, slices: data }); - }); - }; -}); diff --git a/src/kiri-run/minion.js b/src/kiri-run/minion.js index f20135ad..f0a0fd0a 100644 --- a/src/kiri-run/minion.js +++ b/src/kiri-run/minion.js @@ -7,12 +7,12 @@ import '../add/class.js'; import '../add/three.js'; import { base } from '../geo/base.js'; +import { codec, encode } from '../kiri/codec.js'; +import { doTopShells } from '../kiri-mode/fdm/post.js'; import { newPoint } from '../geo/point.js'; import { polygons as POLY } from '../geo/polygons.js'; import { sliceZ } from '../geo/slicer.js'; -import { codec } from '../kiri/codec.js'; -import { broker } from '../moto/broker.js'; -import { doTopShells } from '../kiri-mode/fdm/post.js'; +import { Slicer as cam_slicer } from '../kiri-mode/cam/slicer.js'; import { wasm_ctrl } from '../geo/wasm.js'; const clib = self.ClipperLib; @@ -29,9 +29,14 @@ self.alert = function(o) { }; self.onmessage = function(msg) { - let data = msg.data; - let cmd = data.cmd; - (funcs[cmd] || funcs.bad)(data, data.seq, cmd); + let { data } = msg; + let { cmd } = data; + debug('MINION.onmessage', { cmd, data }); + try { + (funcs[cmd] || funcs.invalid)(data, data.seq, cmd); + } catch (error) { + log('MINION.dispatch.error', error); + } }; function reply(msg, direct) { @@ -42,12 +47,22 @@ function log() { console.log(`[${name}]`, ...arguments); } +function debug() { + // console.log(`[${name}]`, ...arguments); +} + const funcs = self.minion = { - label(data, seq) { - name = data.name; + invalid(data, seq, cmd) { + console.error({ invalid_minion_command: cmd, data }); + reply({ seq, error: `invalid command (${cmd})` }); }, - config: data => { + label(data, seq) { + name = data.name; + self.kiri_minion = { name, cache, log }; + }, + + config(data) { if (data.base) { Object.assign(base.config, data.base); } else { @@ -55,7 +70,7 @@ const funcs = self.minion = { } }, - union: (data, seq) => { + union(data, seq) { if (!(data.polys && data.polys.length)) { reply({ seq, union: codec.encode([]) }); return; @@ -66,7 +81,7 @@ const funcs = self.minion = { reply({ seq, union: codec.encode(union) }, state.zeros); }, - topShells: (data, seq) => { + topShells(data, seq) { let top = codec.decode(data.top, {full: true}); let {z, count, offset1, offsetN, fillOffset, opt} = data; doTopShells(z, top, count, offset1, offsetN, fillOffset, opt); @@ -74,7 +89,7 @@ const funcs = self.minion = { reply({ seq, top: codec.encode(top, {full: true}) }, state.zeros); }, - fill: (data, seq) => { + fill(data, seq) { let polys = codec.decode(data.polys); let { angle, spacing, minLen, maxLen } = data; let fill = POLY.fillArea(polys, angle, spacing, [], minLen, maxLen); @@ -89,7 +104,7 @@ const funcs = self.minion = { reply({ seq, fill: arr }, [ arr.buffer ]); }, - clip: (data, seq) => { + clip(data, seq) { const clip = new clib.Clipper(); const ctre = new clib.PolyTree(); const clips = []; @@ -115,8 +130,8 @@ const funcs = self.minion = { reply({ seq, clips }, state.zeros); }, - sliceZ: (data, seq) => { - console.log('minion.sliceZ', { data, seq }); + sliceZ(data, seq) { + log('minion.sliceZ', { data, seq }); let { z, points, options } = data; let i = 0, p = 0, realp = new Array(points.length / 3); while (i < points.length) { @@ -136,7 +151,7 @@ const funcs = self.minion = { }); }, - putCache: msg => { + putCache(msg) { const { key, data } = msg; // log({ minion_putCache: key, data }); if (data) { @@ -146,13 +161,13 @@ const funcs = self.minion = { } }, - clearCache: msg => { + clearCache(msg) { for (let key in cache) { delete cache[key]; } }, - wasm: data => { + wasm(data) { if (data.enable) { wasm_ctrl.enable(); } else { @@ -160,9 +175,27 @@ const funcs = self.minion = { } }, - bad: (data, seq, cmd) => { - reply({ seq, error: `invalid command (${cmd})` }); - } -}; + cam_slice_init() { + cache.slicer = new cam_slicer(); + }, -broker.publish("minion.started", { funcs, cache, reply, log }); + cam_slice_cleanup() { + delete cache.slicer; + }, + + cam_slice(data, seq) { + const { bucket, opt } = data; + cache.slicer.sliceBucket(bucket, opt, slice => { + // log({ slice }); + }).then(data => { + data.forEach(rec => { + rec.polys = encode(rec.polys); + if (rec.lines) { + const points = rec.lines.map(l => [l.p1, l.p2]).flat(); + rec.lines = encodePointArray(points); + } + }); + reply({ seq, slices: data }); + }); + }, +}; diff --git a/src/kiri-run/worker.js b/src/kiri-run/worker.js index 7c772d8d..9b62f35c 100644 --- a/src/kiri-run/worker.js +++ b/src/kiri-run/worker.js @@ -6,7 +6,6 @@ import '../add/three.js'; import '../ext/jszip.js'; import { base } from '../geo/base.js'; -import { broker } from '../moto/broker.js'; import { codec } from '../kiri/codec.js'; import { util } from '../geo/base.js'; import { newPoint } from '../geo/point.js'; @@ -28,8 +27,7 @@ import { WJET } from '../kiri-mode/wjet/driver.js'; const { time } = util; -let debug = (self.debug === true), - drivers = { +let drivers = { DRAG, CAM, FDM, @@ -39,7 +37,7 @@ let debug = (self.debug === true), WJET }, ccvalue = self.navigator ? self.navigator.hardwareConcurrency || 0 : 0, - concurrent = Math.min(4, self.Worker && ccvalue > 3 ? ccvalue - 1 : 0), + concurrent = 1,//Math.min(4, self.Worker && ccvalue > 3 ? ccvalue - 1 : 0), current = { print: null, snap: null, @@ -53,6 +51,11 @@ let debug = (self.debug === true), minifns = {}, miniseq = 0; +function debug() { + if (self.debug === true) + console.log(...arguments); +} + // catch clipper alerts and convert to console messages self.alert = function(o) { console.log(o); @@ -88,11 +91,11 @@ const minwork = { for (let i=0; i < concurrent; i++) { let minion = new Worker(`/lib/kiri-run/minion.js`, { type: 'module' }); minion.onerror = (error) => { - console.log({ MINION_ERROR: error }); + debug({ MINION_ERROR: error }); error.preventDefault(); }; minion.onmessageerror = (error) => { - console.log({ MINION_MESSAGE_ERROR: error }); + debug({ MINION_MESSAGE_ERROR: error }); error.preventDefault(); }; minion.onmessage = minhandler; @@ -189,11 +192,11 @@ const minwork = { }, sliceZ(z, points, options) { - console.log('minwork.sliceZ', { z, points, options }); + debug('minwork.sliceZ', { z, points, options }); return new Promise((resolve, reject) => { - if (concurrent < 2) { - reject("concurrent slice unavaiable"); - } + // if (concurrent < 2) { + // reject("concurrent slice unavaiable"); + // } let { each } = options; // todo use shared array buffer? let i = 0, floatP = new Float32Array(points.length * 3); @@ -202,7 +205,7 @@ const minwork = { floatP[i++] = p.y; floatP[i++] = p.z; } - const state = { zeros: [] }; + const state = { zeros: [ floatP.buffer ] }; minwork.queue({ cmd: "sliceZ", z, @@ -219,12 +222,13 @@ const minwork = { }, queue(work, ondone, direct) { - if (direct) { - return ondone(work); - } + debug('WORKER.queue', { work, direct }); + // if (direct) { + // return ondone(work); + // } let seq = ++miniseq; minifns[seq] = ondone; - minionq.push({ seq, work }); + minionq.push({ seq, work, direct }); minwork.kick(); }, @@ -239,9 +243,10 @@ const minwork = { return; } let minion = minions.shift(); - let { seq, work } = minionq.shift(); + let { seq, work, direct } = minionq.shift(); work.seq = seq; - minion.postMessage(work); + debug('WORKER.send', { work, direct }); + minion.postMessage(work, direct); minions.push(minion); }, @@ -768,5 +773,3 @@ CAM.init(worker); FDM.init(worker); LASER.init(worker); SLA.init(worker); - -broker.publish("worker.started", { dispatch, minions: minwork }); diff --git a/src/kiri/settings.js b/src/kiri/settings.js index b01d8570..062a8010 100644 --- a/src/kiri/settings.js +++ b/src/kiri/settings.js @@ -756,9 +756,14 @@ function setEnableWASM(bool) { api.event.emit("set.assembly", bool); } -// extend API (api.conf) -const apiConf = { - dbo: () => { return ls2o('ws-settings') }, +// merged api for backward compatibility +const apiSet = { + dbo() { return ls2o('ws-settings') }, + dev() { return settings.device }, + proc() { return settings.process }, + ctrl() { return settings.controller }, + mode() { return settings.mode }, + prof() { return settings.sproc[settings.mode] }, get: getSettings, put: putSettings, load: loadSettings, @@ -773,20 +778,9 @@ const apiConf = { restore: restoreSettings, export: settingsExport, import: settingsImport, -}; - -// extend API (api.settings) -const apiSet = { - get: getSettings, - import: settingsImport, import_zip: settingsImportZip, import_url: settingsImportUrl, import_prusa: settingsPrusaConvert, - dev() { return settings.device }, - proc() { return settings.process }, - ctrl() { return settings.controller }, - mode() { return settings.mode }, - prof() { return settings.sproc[settings.mode] }, sync: { async get() {}, async put() {}, @@ -794,14 +788,16 @@ const apiSet = { } }; -export default { - conf: apiConf, - set: apiSet, - settings: apiSet -}; +// for backward compatibility +apiSet.conf = apiSet; +apiSet.set = apiSet; +apiSet.settings = apiSet; +export default apiSet; + +// for backward compatibility export { - apiConf as conf, + apiSet as conf, apiSet as set, apiSet as settings }; diff --git a/src/moto/broker.js b/src/moto/broker.js index 55b4c4a6..08ca8734 100644 --- a/src/moto/broker.js +++ b/src/moto/broker.js @@ -5,6 +5,7 @@ class Broker { #topics = {}; #used = {}; #send = {}; + #uuid = ((Math.random() * 0xffffffff) | 0).toString(36); constructor() { // using the pattern "broker.send(msg)" induces runtime errors @@ -36,6 +37,9 @@ class Broker { // creates topic if new topic // creates a send function if new topic subscribe(topic, listener) { + if (this.#debug) { + console.log({ subscribe: topic, listener }); + } if (Array.isArray(topic)) { for (let t of topic) { this.subscribe(t, listener); @@ -91,7 +95,7 @@ class Broker { this.publish(".topic.publish", {topic, message, options}); } if (this.#debug && !topic.startsWith(".")) { - console.log({ topic, message }); + console.log({ publish: topic, message }); } // store last seen message on a topic // acts as a tracker for all used topics