add worker / minion slicing

This commit is contained in:
Stewart Allen 2023-01-16 15:14:58 -05:00
commit 0c09c44de7
2 changed files with 144 additions and 13 deletions

View file

@ -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<l; i += 3) {
const x = vertices[i];
const z = vertices[i + 2];
vertices[i] = z;
vertices[i + 2] = x;
range.min = Math.min(range.min, x);
range.max = Math.max(range.max, x);
}
const shards = Math.ceil(Math.min(25, vertices.length / 27000));
const step = (range.max - range.min) / shards;
let index = 0;
let slices = this.slices = [];
let slice = { min: range.min, max: range.min + step, index };
for (let z = range.min; z < range.max; z += resolution) {
if (z > 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;
};
});

View file

@ -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})` });
}
};