From 0c09c44de70420e73f7d06d4c9d7e17d2c89ab62 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Mon, 16 Jan 2023 15:14:58 -0500 Subject: [PATCH] add worker / minion slicing --- src/kiri-mode/cam/topo4.js | 150 ++++++++++++++++++++++++++++++++++--- src/kiri-run/minion.js | 7 +- 2 files changed, 144 insertions(+), 13 deletions(-) diff --git a/src/kiri-mode/cam/topo4.js b/src/kiri-mode/cam/topo4.js index 624c5a99..19e2d694 100644 --- a/src/kiri-mode/cam/topo4.js +++ b/src/kiri-mode/cam/topo4.js @@ -16,7 +16,7 @@ gapp.register("kiri-mode.cam.topo", [], (root, exports) => { const { base, kiri } = root; const { driver, newSlice } = kiri; const { CAM } = driver; -const { polygons, newLine, newSlope, newPoint, newPolygon } = base; +const { polygons, newLine, newSlope, newPoint, newPolygon, sliceConnect } = base; const PRO = CAM.process; const POLY = polygons; @@ -58,13 +58,127 @@ class Topo4 { console.log(widget.id, 'topo4 auto tolerance', resolution.round(4)); } - this.tolerance = resolution; + this.widget = widget; + this.resolution = resolution; onupdate(0, "lathe"); + const slices = await this.slice(onupdate); + for (let slice of slices) { + slice.output() + .setLayer("lathe", { line: 0x888888 }) + .addPolys(slice.topPolys()); + } onupdate(1, "lathe"); - ondone([]); + ondone(slices); } + + async slice(onupdate) { + const { widget, resolution } = this; + + const vertices = this.vertices = widget.getGeoVertices().toShared(); + const range = this.range = { min: Infinity, max: -Infinity }; + const box = this.box = new THREE.Box2(); + + // swap XZ in shared array + for (let i=0, l=vertices.length; i slice.max) { + slices.push(slice); + slice = { min: z, max: z + step, index }; + } + index++; + } + slices.push(slice); + + // console.log({ shards, range, step, slices }); + + if (kiri.minions.running > 1) { + return await this.sliceMinions(onupdate); + } else { + return await this.sliceWorker(onupdate); + } + } + + async sliceWorker(onupdate) { + const { vertices, slices, resolution } = this; + + let output = []; + let complete = 0; + for (let slice of slices) { + const recs = new kiri.topo_slicer(slice.index) + .setFromArray(vertices, slice) + .slice(resolution) + .map(rec => { + const slice = kiri.newSlice(rec.z); + for (let line of rec.lines) { + const { p1, p2 } = line; + if (!p1.swapped) { p1.swapXZ(); p1.swapped = true } + if (!p2.swapped) { p2.swapXZ(); p2.swapped = true } + } + slice.index = rec.index; + slice.addTops(sliceConnect(rec.lines)); + return slice; + }); + output.appendAll(recs); + onupdate(++complete /slices.length); + } + + return output; + } + + async sliceMinions(onupdate) { + const { worker, minions, codec } = kiri; + const { widget, vertices, slices, resolution } = this; + + worker.putCache({ key: widget.id, data: vertices }, { done: data => { + // console.log({ put_cache_done: data }); + }}); + + let complete = 0; + let promises = slices.map(slice => { + return new Promise(resolve => { + minions.queue({ + cmd: "topo4_raster", + id: widget.id, + resolution, + slice + }, data => { + resolve(data); + onupdate(++complete / slices.length); + }); + }); + }); + + // merge boxes for all rasters for contouring clipping + const output = codec.decode(await Promise.all(promises)) + .map(rec => rec.recs) + .flat() + .map(rec => newSlice(rec.z).addTops(rec.polys)) + .sort((a,b) => a.z - b.z); + + worker.clearCache({}, { done: data => { + // console.log({ clear_cache_done: data }); + }}); + + return output; + } + } CAM.Topo4 = async function(opt) { @@ -73,27 +187,43 @@ CAM.Topo4 = async function(opt) { moto.broker.subscribe("minion.started", msg => { const { funcs, cache, reply, log } = msg; + const { codec } = kiri; funcs.topo4_raster = (data, seq) => { + const { id, slice, resolution } = data; + const vertices = cache[id]; + const recs = new kiri.topo_slicer(slice.index) + .setFromArray(vertices, slice) + .slice(resolution) + .map(rec => { + const { z, index, lines } = rec; + + for (let line of lines) { + const { p1, p2 } = line; + if (!p1.swapped) { p1.swapXZ(); p1.swapped = true } + if (!p2.swapped) { p2.swapXZ(); p2.swapped = true } + } + + return codec.encode({ z, index, polys: sliceConnect(lines) }); + }); + // only pass back bounds of rasters to be merged + reply({ seq, recs }); }; funcs.trace4_init = data => { + const { cache } = self; + const { codec } = kiri; + cache.topo4 = data; }; funcs.trace4_y = (data, seq) => { }; funcs.trace4_x = (data, seq) => { - const { cache } = self; - const { trace } = cache.trace; - trace.crossX_sync(data.params, slice => { - slice = kiri.codec.encode(slice); - reply({ seq, slice }); - }); }; funcs.trace4_cleanup = () => { - delete cache.trace; + delete cache.topo4; }; }); diff --git a/src/kiri-run/minion.js b/src/kiri-run/minion.js index 1c504c03..a7eb74e1 100644 --- a/src/kiri-run/minion.js +++ b/src/kiri-run/minion.js @@ -11,6 +11,7 @@ // dep: kiri.codec // dep: kiri-mode.fdm.post // dep: kiri-mode.cam.topo +// dep: kiri-mode.cam.topo4 // use: kiri-mode.cam.slicer // dep: ext.clip2 gapp.register("kiri-run.minion", [], (root, exports) => { @@ -36,7 +37,7 @@ self.alert = function(o) { self.onmessage = function(msg) { let data = msg.data; let cmd = data.cmd; - (funcs[cmd] || funcs.bad)(data, data.seq); + (funcs[cmd] || funcs.bad)(data, data.seq, cmd); }; function reply(msg, direct) { @@ -164,8 +165,8 @@ const funcs = self.minion = { } }, - bad: (data, seq) => { - reply({ seq, error: "invalid command" }); + bad: (data, seq, cmd) => { + reply({ seq, error: `invalid command (${cmd})` }); } };