cam fix slice z output order, restore progress bar accuracy

This commit is contained in:
Stewart Allen 2023-01-15 15:06:29 -05:00
commit 70c00e1bab
3 changed files with 71 additions and 54 deletions

View file

@ -256,7 +256,9 @@ class OpRough extends CamOp {
} }
// console.log('indices', ...indices, {zBottom}); // console.log('indices', ...indices, {zBottom});
await slicer.slice(indices, { each: (data, index, total) => { let cnt = 0;
let tot = 0;
await slicer.slice(indices, { each: data => {
shadow = unsafe ? data.tops : POLY.union(shadow.slice().appendAll(data.tops), 0.01, true); shadow = unsafe ? data.tops : POLY.union(shadow.slice().appendAll(data.tops), 0.01, true);
if (flats.indexOf(data.z) >= 0) { if (flats.indexOf(data.z) >= 0) {
// exclude flats injected to complete shadow // exclude flats injected to complete shadow
@ -268,8 +270,11 @@ class OpRough extends CamOp {
// data.slice.tops[0].inner = data.shadow; // data.slice.tops[0].inner = data.shadow;
// data.slice.tops[0].inner = POLY.setZ(tshadow.clone(true), data.z); // data.slice.tops[0].inner = POLY.setZ(tshadow.clone(true), data.z);
slices.push(data.slice); slices.push(data.slice);
progress((index / total) * 0.5); progress(0.25 + 0.25 * (++cnt / tot));
}, genso: true }); }, progress: (index, total) => {
tot = total;
progress((index / total) * 0.25);
} });
if (trueShadow) { if (trueShadow) {
shadow = tshadow.clone(true); shadow = tshadow.clone(true);
@ -376,7 +381,7 @@ class OpRough extends CamOp {
slice.output() slice.output()
.setLayer("roughing", {face: color, line: color}) .setLayer("roughing", {face: color, line: color})
.addPolys(offset); .addPolys(offset);
progress(0.5 + (index / slices.length) * 0.5); progress(0.5 + 0.5 * (index / slices.length));
}); });
this.sliceOut = slices.filter(slice => slice.camLines); this.sliceOut = slices.filter(slice => slice.camLines);
@ -505,6 +510,8 @@ class OpOutline extends CamOp {
.filter(v => v > 0 && indices.indexOf(v) < 0); .filter(v => v > 0 && indices.indexOf(v) < 0);
indices = indices.appendAll(flats).sort((a,b) => b-a); indices = indices.appendAll(flats).sort((a,b) => b-a);
// console.log('indices', ...indices, {zBottom, slicer}); // console.log('indices', ...indices, {zBottom, slicer});
let cnt = 0;
let tot = 0;
if (op.outside && !op.inside) { if (op.outside && !op.inside) {
// console.log({outline_bypass: indices, down: op.down}); // console.log({outline_bypass: indices, down: op.down});
indices.forEach((ind,i) => { indices.forEach((ind,i) => {
@ -517,7 +524,7 @@ class OpOutline extends CamOp {
slices.push(slice); slices.push(slice);
}); });
} else } else
await slicer.slice(indices, { each: (data, index, total) => { await slicer.slice(indices, { each: data => {
shadow = unsafe ? data.tops : POLY.union(shadow.slice().appendAll(data.tops), 0.01, true); shadow = unsafe ? data.tops : POLY.union(shadow.slice().appendAll(data.tops), 0.01, true);
if (flats.indexOf(data.z) >= 0) { if (flats.indexOf(data.z) >= 0) {
// exclude flats injected to complete shadow // exclude flats injected to complete shadow
@ -530,8 +537,11 @@ class OpOutline extends CamOp {
slices.push(data.slice); slices.push(data.slice);
// data.slice.xray(); // data.slice.xray();
// onupdate(0.2 + (index/total) * 0.1, "outlines"); // onupdate(0.2 + (index/total) * 0.1, "outlines");
progress(0.5 + 0.5 * (++cnt / tot));
}, progress: (index, total) => {
tot = total;
progress((index / total) * 0.5); progress((index / total) * 0.5);
}, genso: true }); } });
shadow = POLY.union(shadow.appendAll(shadowTop.tops), 0.01, true); shadow = POLY.union(shadow.appendAll(shadowTop.tops), 0.01, true);
// start slices at top of stock when `clear top` enabled // start slices at top of stock when `clear top` enabled
@ -1493,7 +1503,7 @@ class OpXRay extends CamOp {
let xrayind = Object.keys(slicer.zLine) let xrayind = Object.keys(slicer.zLine)
.map(v => parseFloat(v).round(5)) .map(v => parseFloat(v).round(5))
.sort((a,b) => a-b); .sort((a,b) => a-b);
let xrayopt = { each: (data, index, total) => { let xrayopt = { each: data => {
let slice = newSlice(data.z); let slice = newSlice(data.z);
slice.addTops(data.tops); slice.addTops(data.tops);
// data.tops.forEach(top => slice.addTop(top)); // data.tops.forEach(top => slice.addTop(top));
@ -1534,7 +1544,9 @@ class OpShadow extends CamOp {
} }
let lsz; // only shadow up to bottom of last shadow for progressive union let lsz; // only shadow up to bottom of last shadow for progressive union
let terrain = await slicer.slice(tzindex, { each: (data, index, total) => { let cnt = 0;
let tot = 0;
let terrain = await slicer.slice(tzindex, { each: data => {
let shadow = trueShadow ? shadowAt(data.z, lsz) : []; let shadow = trueShadow ? shadowAt(data.z, lsz) : [];
tshadow = POLY.union(tshadow.slice().appendAll(data.tops).appendAll(shadow), 0.01, true); tshadow = POLY.union(tshadow.slice().appendAll(data.tops).appendAll(shadow), 0.01, true);
tslices.push(data.slice); tslices.push(data.slice);
@ -1562,8 +1574,11 @@ class OpShadow extends CamOp {
// .addLines(p2, { thin: true }); // .addLines(p2, { thin: true });
} }
lsz = data.z; lsz = data.z;
progress(index / total); progress(0.5 + 0.5 * (++cnt / tot));
}, genso: true }); }, progress: (index, total) => {
tot = total;
progress((index / total) * 0.5);
} });
if (terrain.length === 0) { if (terrain.length === 0) {
throw `invalid widget shadow`; throw `invalid widget shadow`;

View file

@ -342,7 +342,7 @@ CAM.traces = async function(settings, widget, single) {
let traces = []; let traces = [];
// find and trim polys (including open) to shadow // find and trim polys (including open) to shadow
let oneach = (data, index, total) => { let oneach = data => {
if (single) { if (single) {
for (let line of data.lines) { for (let line of data.lines) {
if (line.p1.distTo2D(line.p2) > 1) { if (line.p1.distTo2D(line.p2) > 1) {

View file

@ -15,6 +15,15 @@ const { sliceConnect, sliceDedup } = base;
const { newSlice } = kiri; const { newSlice } = kiri;
const POLY = polygons; const POLY = polygons;
const timing = false;
const begin = function() {
if (timing) console.time(...arguments);
};
const end = function() {
if (timing) console.timeEnd(...arguments);
};
class Slicer { class Slicer {
constructor(widget, options = { zlist: true, zline: true, lines: false }) { constructor(widget, options = { zlist: true, zline: true, lines: false }) {
@ -30,14 +39,10 @@ class Slicer {
return this.options.threaded; return this.options.threaded;
} }
// notopok = when genso set, allow empty top array
// emptyok = allow empty slices
// openok = allow open tops
// zList = generate list of z vertices // zList = generate list of z vertices
// zline = generate list of z vertices with coplanar lines // zline = generate list of z vertices with coplanar lines
// trace = find z coplanar trace lines // trace = find z coplanar trace lines
// flatoff = amount to offset z when slicing on detected flats // flatoff = amount to offset z when slicing on detected flats
// genso = generate a slice object with tops
// each = call for each slice generated from an interval // each = call for each slice generated from an interval
setOptions(options) { setOptions(options) {
Object.assign(this.options, options || {}); Object.assign(this.options, options || {});
@ -57,7 +62,7 @@ class Slicer {
// these are used for auto-slicing in laser // these are used for auto-slicing in laser
// and to flats detection in CAM mode // and to flats detection in CAM mode
computeFeatures(options) { computeFeatures(options) {
console.time('computeFeatures'); begin('compute features');
const opt = this.setOptions(options); const opt = this.setOptions(options);
const bounds = this.bounds = new THREE.Box3(); const bounds = this.bounds = new THREE.Box3();
@ -120,10 +125,9 @@ class Slicer {
} }
} }
end('compute features');
// console.log({ bounds, zFlat, zLine, zList }); // console.log({ bounds, zFlat, zLine, zList });
console.timeEnd('computeFeatures');
return this; return this;
} }
@ -151,11 +155,11 @@ class Slicer {
const plen = points.length; const plen = points.length;
const zlen = zs.length; const zlen = zs.length;
const ppz = plen / zlen; const ppz = plen / zlen;
const count = 100;//Math.ceil(ppz / 10000); const count = 25;//Math.ceil(ppz / 10000);
const step = Math.ceil(zlen / count); const step = Math.ceil(zlen / count);
const buckets = []; const buckets = [];
console.log({ plen, zlen, ppz, count, step }); // console.log({ plen, zlen, ppz, count, step });
if (count === 1) { if (count === 1) {
buckets.push({ zs }); buckets.push({ zs });
@ -173,7 +177,7 @@ class Slicer {
p2 = newPoint(0,0,0), p2 = newPoint(0,0,0),
p3 = newPoint(0,0,0); p3 = newPoint(0,0,0);
console.time("create buckets"); begin("create buckets");
for (let i = 0, il = points.length; i < il; ) { for (let i = 0, il = points.length; i < il; ) {
p1.set(points[i++], points[i++], points[i++]); p1.set(points[i++], points[i++], points[i++]);
p2.set(points[i++], points[i++], points[i++]); p2.set(points[i++], points[i++], points[i++]);
@ -190,30 +194,35 @@ class Slicer {
if (zmin > max && zmax > max) { if (zmin > max && zmax > max) {
continue; continue;
} }
index.push(i); index.push(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z);
} }
} }
console.timeEnd("create buckets"); end("create buckets");
} }
// console.log({ zs, zlen, count, step, buckets }); // console.log({ zs, zlen, count, step, buckets });
console.time("slicing"); begin("slicing");
const { minions } = kiri; const { minions } = kiri;
const threaded = minions && minions.running; const threaded = minions && minions.running;
const sliceFn = (threaded ? this.sliceBucketMinion : this.sliceBucket).bind(this); const sliceFn = (threaded ? this.sliceBucketMinion : this.sliceBucket).bind(this);
const track = { count: 0, total: zs.length }; const track = { count: 0, total: zs.length };
if (threaded) minions.broadcast("cam_slice_init", { points: this.points }); if (threaded) minions.broadcast("cam_slice_init", {});
console.log({ buckets });
const promises = [] const promises = []
for (let bucket of buckets) { for (let bucket of buckets) {
promises.push(sliceFn(bucket, opt)); promises.push(sliceFn(bucket, opt, slice => {
track.count++;
if (opt.progress) {
opt.progress(track.count, track.total);
}
// console.log({ oneach: slice, ...track });
}));
} }
const data = (await Promise.all(promises)).flat(); const data = (await Promise.all(promises)).flat();
data.sort((a,b) => a.z - b.z).forEach((rec, i) => { data.sort((a,b) => b.z - a.z).forEach((rec, i) => {
rec.tops = rec.polys; rec.tops = rec.polys;
rec.slice = newSlice(rec.z).addTops(rec.tops); rec.slice = newSlice(rec.z).addTops(rec.tops);
if (opt.each) { if (opt.each) {
@ -222,13 +231,12 @@ class Slicer {
}); });
if (threaded) minions.broadcast("cam_slice_cleanup"); if (threaded) minions.broadcast("cam_slice_cleanup");
end("slicing");
console.timeEnd("slicing");
return data; return data;
} }
async sliceBucketMinion(bucket, opt) { async sliceBucketMinion(bucket, opt, oneach) {
const slices = (await new Promise(resolve => { const slices = (await new Promise(resolve => {
kiri.minions.queue({ kiri.minions.queue({
cmd: "cam_slice", cmd: "cam_slice",
@ -236,11 +244,14 @@ class Slicer {
bucket, bucket,
}, resolve); }, resolve);
})).slices; })).slices;
console.log(bucket, slices); for (let slice of slices) {
oneach(slice);
}
// console.log(bucket, slices);
return kiri.codec.decode(slices); return kiri.codec.decode(slices);
} }
async sliceBucket(bucket, opt) { async sliceBucket(bucket, opt, oneach) {
const { zs, index } = bucket; const { zs, index } = bucket;
const slices = []; const slices = [];
for (let z of zs) { for (let z of zs) {
@ -248,6 +259,7 @@ class Slicer {
if (slice) { if (slice) {
slices.push(slice); slices.push(slice);
} }
oneach(slice);
} }
return slices; return slices;
} }
@ -259,19 +271,15 @@ class Slicer {
over = opt.over || false, over = opt.over || false,
debug = opt.debug, debug = opt.debug,
phash = {}, phash = {},
lines = [], lines = [];
index = 0,
next = 0;
const { points } = this, // const { points } = this,
const points = indices,
p1 = newPoint(0,0,0), p1 = newPoint(0,0,0),
p2 = newPoint(0,0,0), p2 = newPoint(0,0,0),
p3 = newPoint(0,0,0); p3 = newPoint(0,0,0);
while (true) { for (let index = 0; index < points.length; ) {
if (indices) {
index = indices[next++];
}
p1.set(points[index++], points[index++], points[index++]); p1.set(points[index++], points[index++], points[index++]);
p2.set(points[index++], points[index++], points[index++]); p2.set(points[index++], points[index++], points[index++]);
p3.set(points[index++], points[index++], points[index++]); p3.set(points[index++], points[index++], points[index++]);
@ -307,13 +315,6 @@ class Slicer {
console.log({msg: "invalid ips", line: line, where: where}); console.log({msg: "invalid ips", line: line, where: where});
} }
} }
if (index >= points.length) {
break;
}
if (indices && next >= indices.length) {
break;
}
} }
if (dedup) { if (dedup) {
@ -461,8 +462,8 @@ kiri.cam_slicer = Slicer;
moto.broker.subscribe("minion.started", msg => { moto.broker.subscribe("minion.started", msg => {
const { funcs, cache, reply, log } = msg; const { funcs, cache, reply, log } = msg;
funcs.cam_slice_init = data => { funcs.cam_slice_init = () => {
cache.slicer = new Slicer().setPoints(data.points); cache.slicer = new Slicer();
}; };
funcs.cam_slice_cleanup = () => { funcs.cam_slice_cleanup = () => {
@ -471,10 +472,11 @@ moto.broker.subscribe("minion.started", msg => {
funcs.cam_slice = (data, seq) => { funcs.cam_slice = (data, seq) => {
const { bucket, opt } = data; const { bucket, opt } = data;
cache.slicer.sliceBucket(bucket, opt) cache.slicer.sliceBucket(bucket, opt, slice => {
.then(data => { // console.log({ slice });
reply({ seq, slices: kiri.codec.encode(data) }); }).then(data => {
}); reply({ seq, slices: kiri.codec.encode(data) });
});
}; };
}); });