add experimental promises + concurrent shell offsetting

This commit is contained in:
Stewart Allen 2021-06-20 00:25:35 -04:00
commit a8973dbef8
7 changed files with 97 additions and 35 deletions

2
app.js
View file

@ -342,6 +342,8 @@ const script = {
"geo/polygon",
"geo/polygons",
"geo/gyroid",
"mode/fdm/driver",
"mode/fdm/slice",
"kiri/slice",
"kiri/layers",
"kiri/widget",

View file

@ -21,7 +21,7 @@
newPoint = BASE.newPoint,
Bounds = BASE.Bounds;
let seqid = 1;
let seqid = Math.round(Math.random() * 0xffffffff);
/** ******************************************************************
* Constructors

View file

@ -231,14 +231,27 @@
});
KIRI.Top.prototype.encode = function(state) {
return {
let obj = {
type: 'top',
poly: encode(this.poly, state),
poly: encode(this.poly, state)
};
if (state.full) {
obj.last = encode(this.last, state);
obj.shells = encode(this.shells, state);
obj.fill_off = encode(this.fill_off, state);
obj.fill_lines = encode(this.fill_lines, state);
}
return obj;
};
registerDecoder('top', function(v, state) {
let top = KIRI.newTop(decode(v.poly, state));
if (state.full) {
top.last = decode(v.last, state);
top.shells = decode(v.shells, state);
top.fill_off = decode(v.fill_off, state);
top.fill_lines = decode(v.fill_lines, state);
}
return top;
});

View file

@ -13,20 +13,30 @@ self.alert = function(o) {
console.log(o);
};
function reply(msg) {
self.postMessage(msg);
}
self.onmessage = function(msg) {
let data = msg.data;
switch (data.cmd) {
case "union":
if (!(data.polys && data.polys.length)) {
self.postMessage({union: CODEC.encode([])});
reply({union: CODEC.encode([])});
return;
}
let polys = CODEC.decode(data.polys);
let union = POLY.union(polys, data.minarea || 0, true);
self.postMessage({union: CODEC.encode(union)});
reply({union: CODEC.encode(union)});
break;
case "top.shells":
let top = CODEC.decode(data.top, {full: true});
let {z, count, offset1, offsetN, fillOffset, opt} = data;
KIRI.driver.FDM.share.doTopShells(z, top, count, offset1, offsetN, fillOffset, opt);
reply({top: CODEC.encode(top, {full: true})});
break;
default:
self.postMessage({error: "invalid command"});
reply({error: "invalid command"});
break;
}
};

View file

@ -32,6 +32,7 @@ if (concurrent) {
}
// for concurrent operations
const minwork =
KIRI.minions = {
union: function(polys, minarea) {
return new Promise((resolve, reject) => {
@ -41,30 +42,27 @@ KIRI.minions = {
let polyper = Math.ceil(polys.length / concurrent);
let running = 0;
let union = [];
let receiver = function(msg) {
let polys = KIRI.codec.decode(msg.data.union);
let receiver = function(data) {
let polys = KIRI.codec.decode(data.union);
union.appendAll(polys);
if (--running === 0) {
resolve(POLY.union(union, 0, true));
}
};
for (let i=0; i<polys.length; i += polyper) {
minions[running].onmessage = receiver;
minions[running].postMessage({
running++;
minwork.queue({
cmd: "union",
minarea,
polys: KIRI.codec.encode(polys.slice(i, i + polyper))
});
running++;
}, receiver);
}
});
},
queue: function(work) {
return new Promise((resolve, reject) => {
minionq.push({work, resolve, reject});
kick();
});
queue: function(work, ondone) {
minionq.push({work, ondone});
minwork.kick();
},
kick: function() {
@ -72,10 +70,11 @@ KIRI.minions = {
let qrec = minionq.shift();
let minion = minions.shift();
minion.onmessage = (msg) => {
qrec.resolve(msg.data);
minions.push(minion);
qrec.ondone(msg.data);
minwork.kick();
};
minion.postMessage(work);
minion.postMessage(qrec.work);
}
}
};

View file

@ -680,8 +680,8 @@
if (Math.abs(angle) <= 3 * Math.PI / 4) {
cc = BASE.util.center2pr(from, to, arcQ.rSum / cl, gc === "G3");
}
}
if (!cc) {
cc = {x:arcQ.xSum/cl, y:arcQ.ySum/cl, z:arcQ[0].z, r:arcQ.rSum/cl};
}

View file

@ -263,9 +263,10 @@
slice.solids = [];
});
let promises = ctrl.danger ? [] : undefined;
// create shells and diff inner fillable areas
forSlices(0.0, 0.2, slice => {
let params = getRangeParameters(settings, slice.index);
forSlices(0.0, 0.15, slice => {
let params = slice.params = getRangeParameters(settings, slice.index);
let shellFrac = (params.sliceShells - (params.sliceShells | 0));
let sliceShells = params.sliceShells | 0;
if (ctrl.danger && shellFrac) {
@ -280,24 +281,38 @@
let isBottom = slice.index < spro.sliceBottomLayers;
let isTop = slice.index > slices.length - spro.sliceTopLayers-1;
let isDense = params.sliceFillSparse > 0.98;
let solid = (isBottom || ((isTop || isDense) && !vaseMode)) && !isSynth;
let solidWidth = params.sliceFillWidth || 1;
let spaceMult = first ? spro.firstLayerLineMult || 1 : 1;
if ((isBottom || ((isTop || isDense) && !vaseMode)) && !isSynth) {
slice.solid = {
solidWidth,
spaceMult
};
}
let offset = shellOffset * spaceMult;
let fillOff = fillOffset * spaceMult;
let count = isSynth ? 1 : sliceShells;
doShells(slice, count, offset, fillOff, {
vase: vaseMode,
thin: spro.detectThinWalls && !isSynth,
widget: widget,
// widget: widget,
danger: ctrl.danger
});
if (solid) {
let fillSpace = fillSpacing * spaceMult * solidWidth;
}, promises);
}, "shells");
if (promises) {
await Promise.all(promises);
// console.log('resolved', promises.length);
}
// just the top/bottom special solid layers
forSlices(0.15, 0.2, slice => {
if (slice.solid) {
let fillSpace = fillSpacing * slice.solid.spaceMult * slice.solid.solidWidth;
doSolidLayerFill(slice, fillSpace, sliceFillAngle);
}
sliceFillAngle += 90.0;
}, "offsets");
}, "shells");
// add lead in when specified in belt mode
if (!isSynth && isBelt) {
@ -474,10 +489,10 @@
alltops = alltops.map(p => p.clean(true, undefined, 5000));
// console.log({reduced: alltops.map(p => p.deepLength).reduce((a,v)=>a+v)});
}
// let mark = Date.now();
let mark = Date.now();
// shadow = POLY.union(alltops, 0.1, true);
shadow = await KIRI.minions.union(alltops, 0.1);
// console.log({unioned_in: Date.now() - mark});
console.log({unioned_in: Date.now() - mark});
if (spro.sliceSupportExtra) {
shadow = POLY.offset(shadow, spro.sliceSupportExtra);
}
@ -586,6 +601,7 @@
// shared with SLA driver
FDM.share = {
doShells,
doTopShells,
doDiff,
projectFlats,
projectBridges,
@ -604,7 +620,7 @@
* @param {number} fillOffset
* @param {Obejct} options
*/
function doShells(slice, count, offsetN, fillOffset, opt = {}) {
function doShells(slice, count, offsetN, fillOffset, opt = {}, promises) {
let offset1 = offsetN / 2;
if (slice.index === 0) {
@ -612,12 +628,34 @@
// segment polygon
}
for (let top of slice.tops) {
doTopShells(slice.z, top, count, offset1, offsetN, fillOffset, opt);
if (promises) {
let oldtops = slice.tops;
let newtops = slice.tops = [];
oldtops.old = true;
for (let top of oldtops) {
promises.push(
new Promise((resolve, reject) => {
KIRI.minions.queue({
cmd: "top.shells",
z: slice.z, count, offset1, offsetN, fillOffset, opt,
top: KIRI.codec.encode(top, {full: true})
}, data => {
let top = KIRI.codec.decode(data.top, {full: true});
newtops.push(top);
resolve();
});
})
);
}
newtops.new = true;
} else {
for (let top of slice.tops) {
doTopShells(slice.z, top, count, offset1, offsetN, fillOffset, opt);
}
}
}
function doTopShells(z, top, count, offset1, offsetN, fillOffset, opt) {
function doTopShells(z, top, count, offset1, offsetN, fillOffset, opt = {}) {
let top_poly = [ top.poly ];
if (opt.vase) {