add worker / minion slicing
This commit is contained in:
parent
8a8f4d8485
commit
0c09c44de7
2 changed files with 144 additions and 13 deletions
|
|
@ -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;
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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})` });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue