concurrent refactor. added clipping. all toggled with experimental

This commit is contained in:
Stewart Allen 2021-06-20 18:10:19 -04:00
commit 881992b52e
3 changed files with 88 additions and 28 deletions

View file

@ -6,7 +6,11 @@ let BASE = self.base,
KIRI = self.kiri, KIRI = self.kiri,
UTIL = BASE.util, UTIL = BASE.util,
POLY = BASE.polygons, POLY = BASE.polygons,
CODEC = KIRI.codec; CODEC = KIRI.codec,
clib = self.ClipperLib,
ctyp = clib.ClipType,
ptyp = clib.PolyType,
cfil = clib.PolyFillType;
// catch clipper alerts and convert to console messages // catch clipper alerts and convert to console messages
self.alert = function(o) { self.alert = function(o) {
@ -56,6 +60,23 @@ const funcs = {
reply({ fill: arr }, [ arr.buffer ]); reply({ fill: arr }, [ arr.buffer ]);
}, },
clip: data => {
let clip = new clib.Clipper();
let ctre = new clib.PolyTree();
let clips = [];
clip.AddPaths(data.lines, ptyp.ptSubject, false);
clip.AddPaths(data.polys, ptyp.ptClip, true);
if (clip.Execute(ctyp.ctIntersection, ctre, cfil.pftNonZero, cfil.pftEvenOdd)) {
for (let node of ctre.m_AllPolys) {
clips.push(CODEC.encode(POLY.fromClipperNode(node, data.z)));
}
}
reply({ clips });
},
bad: data => { bad: data => {
reply({error: "invalid command"}); reply({error: "invalid command"});
} }

View file

@ -34,10 +34,13 @@ if (concurrent) {
// for concurrent operations // for concurrent operations
const minwork = const minwork =
KIRI.minions = { KIRI.minions = {
concurrent,
union: function(polys, minarea) { union: function(polys, minarea) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (concurrent === 0 || polys.length * 2 < concurrent) { if (concurrent === 0 || polys.length * 2 < concurrent) {
resolve(POLY.union(polys, 0, true)); resolve(POLY.union(polys, 0, true));
return;
} }
let polyper = Math.ceil(polys.length / concurrent); let polyper = Math.ceil(polys.length / concurrent);
let running = 0; let running = 0;
@ -64,6 +67,7 @@ KIRI.minions = {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (concurrent === 0) { if (concurrent === 0) {
resolve(POLY.fillArea(polys, angle, spacing, [], minLen, maxLen)); resolve(POLY.fillArea(polys, angle, spacing, [], minLen, maxLen));
return;
} }
minwork.queue({ minwork.queue({
cmd: "fill", cmd: "fill",
@ -83,6 +87,30 @@ KIRI.minions = {
}); });
}, },
clip: function(slice, polys, lines) {
return new Promise((resolve, reject) => {
if (concurrent === 0) {
reject("concurrent clip unavaiable");
}
minwork.queue({
cmd: "clip",
polys: POLY.toClipper(polys),
lines: lines.map(a => a.map(p => p.toClipper())),
z: slice.z
}, data => {
let polys = KIRI.codec.decode(data.clips);
for (let top of slice.tops) {
for (let poly of polys) {
if (poly.isInside(top.poly)) {
top.fill_sparse.push(poly);
}
}
}
resolve(polys);
});
});
},
queue: function(work, ondone) { queue: function(work, ondone) {
minionq.push({work, ondone}); minionq.push({work, ondone});
minwork.kick(); minwork.kick();

View file

@ -82,7 +82,8 @@
fillOffset = lineWidth * fillOffsetMult, fillOffset = lineWidth * fillOffsetMult,
sliceFillAngle = spro.sliceFillAngle, sliceFillAngle = spro.sliceFillAngle,
supportDensity = spro.sliceSupportDensity, supportDensity = spro.sliceSupportDensity,
beltfact = Math.cos(Math.PI/4); beltfact = Math.cos(Math.PI/4),
doConcurrent = ctrl.danger && KIRI.minions.concurrent;
isFlat = ctrl.lineType === "flat"; isFlat = ctrl.lineType === "flat";
isThin = !isFlat && ctrl.lineType === "line"; isThin = !isFlat && ctrl.lineType === "line";
@ -263,7 +264,7 @@
slice.solids = []; slice.solids = [];
}); });
let promises = ctrl.danger ? [] : undefined; let promises = doConcurrent ? [] : undefined;
// create shells and diff inner fillable areas // create shells and diff inner fillable areas
forSlices(0.0, 0.15, slice => { forSlices(0.0, 0.15, slice => {
let params = slice.params = getRangeParameters(settings, slice.index); let params = slice.params = getRangeParameters(settings, slice.index);
@ -298,10 +299,8 @@
danger: ctrl.danger danger: ctrl.danger
}, promises); }, promises);
}, "shells"); }, "shells");
if (promises) { if (promises) {
await Promise.all(promises); await Promise.all(promises);
// console.log('resolved', promises.length);
} }
// just the top/bottom special solid layers // just the top/bottom special solid layers
@ -429,23 +428,28 @@
projectFlats(slice, solidLayers); projectFlats(slice, solidLayers);
projectBridges(slice, solidLayers); projectBridges(slice, solidLayers);
}, "project solids"); }, "project solids");
let promises = doConcurrent ? [] : undefined;
forSlices(0.35, 0.5, slice => { forSlices(0.35, 0.5, slice => {
let params = slice.params;// getRangeParameters(settings, slice.index); let params = slice.params;
let first = slice.index === 0; let first = slice.index === 0;
let solidWidth = params.sliceFillWidth || 1; let solidWidth = params.sliceFillWidth || 1;
let spaceMult = first ? params.firstLayerLineMult || 1 : 1; let spaceMult = first ? params.firstLayerLineMult || 1 : 1;
let fillSpace = fillSpacing * spaceMult * solidWidth; let fillSpace = fillSpacing * spaceMult * solidWidth;
doSolidsFill(slice, fillSpace, sliceFillAngle, minSolid); doSolidsFill(slice, fillSpace, sliceFillAngle, minSolid, promises);
sliceFillAngle += 90.0; sliceFillAngle += 90.0;
}, "fill solids"); }, "fill solids");
await fillResolve(); if (promises) {
console.log({fill_awaiting: promises.length});
await Promise.all(promises);
}
} }
// sparse layers only present when non-vase mose and sparse % > 0 // sparse layers only present when non-vase mose and sparse % > 0
if (!isSynth) { if (!isSynth) {
let lastType; let lastType;
let promises = doConcurrent ? [] : undefined;
forSlices(0.5, 0.7, slice => { forSlices(0.5, 0.7, slice => {
let params = slice.params;// getRangeParameters(settings, slice.index); let params = slice.params;
if (vaseMode || !params.sliceFillSparse) { if (vaseMode || !params.sliceFillSparse) {
return; return;
} }
@ -460,13 +464,18 @@
bounds: widget.getBoundingBox(), bounds: widget.getBoundingBox(),
height: sliceHeight, height: sliceHeight,
type: newType, type: newType,
cache: params._range !== true && lastType === newType cache: params._range !== true && lastType === newType,
promises
}); });
lastType = newType; lastType = newType;
}, "infill"); }, "infill");
if (promises) {
console.log({infill_awaiting: promises.length});
await Promise.all(promises);
}
} else if (isSynth) { } else if (isSynth) {
forSlices(0.5, 0.7, slice => { forSlices(0.5, 0.7, slice => {
let params = slice.params;// getRangeParameters(settings, slice.index); let params = slice.params;
let density = params.sliceSupportDensity; let density = params.sliceSupportDensity;
if (density) if (density)
for (let top of slice.tops) { for (let top of slice.tops) {
@ -491,7 +500,9 @@
} }
let mark = Date.now(); let mark = Date.now();
// shadow = POLY.union(alltops, 0.1, true); // shadow = POLY.union(alltops, 0.1, true);
shadow = await KIRI.minions.union(alltops, 0.1); shadow = doConcurrent ?
await KIRI.minions.union(alltops, 0.1) :
POLY.union(alltops, 0.1, true);
// console.log({unioned_in: Date.now() - mark}); // console.log({unioned_in: Date.now() - mark});
if (spro.sliceSupportExtra) { if (spro.sliceSupportExtra) {
shadow = POLY.offset(shadow, spro.sliceSupportExtra); shadow = POLY.offset(shadow, spro.sliceSupportExtra);
@ -511,7 +522,7 @@
// render if not explicitly disabled // render if not explicitly disabled
if (render) { if (render) {
forSlices(0.9, 1.0, slice => { forSlices(0.9, 1.0, slice => {
let params = slice.params;// getRangeParameters(settings, slice.index); let params = slice.params;
doRender(slice, isSynth, params, ctrl.devel); doRender(slice, isSynth, params, ctrl.devel);
}, "render"); }, "render");
} }
@ -803,7 +814,7 @@
* Take output from pluggable sparse infill algorithm and clip to * Take output from pluggable sparse infill algorithm and clip to
* the bounds of the top polygons and their inner solid areas. * the bounds of the top polygons and their inner solid areas.
*/ */
function doSparseLayerFill(slice, options) { function doSparseLayerFill(slice, options = {}) {
let process = options.process, let process = options.process,
spacing = options.spacing, // spacing space between fill lines spacing = options.spacing, // spacing space between fill lines
density = options.density, // density of infill 0.0 - 1.0 density = options.density, // density of infill 0.0 - 1.0
@ -950,6 +961,11 @@
return; return;
} }
if (options.promises) {
options.promises.push(KIRI.minions.clip(slice, polys, lines));
return;
}
lines = lines.map(a => a.map(p => p.toClipper())); lines = lines.map(a => a.map(p => p.toClipper()));
clip.AddPaths(lines, ptyp.ptSubject, false); clip.AddPaths(lines, ptyp.ptSubject, false);
clip.AddPaths(POLY.toClipper(polys), ptyp.ptClip, true); clip.AddPaths(POLY.toClipper(polys), ptyp.ptClip, true);
@ -1026,7 +1042,7 @@
* fill projected areas and store line data * fill projected areas and store line data
* @return {boolean} true if filled, false if not * @return {boolean} true if filled, false if not
*/ */
function doSolidsFill(slice, spacing, angle, minArea) { function doSolidsFill(slice, spacing, angle, minArea, fillQ) {
let minarea = minArea || 1, let minarea = minArea || 1,
tops = slice.tops, tops = slice.tops,
@ -1103,33 +1119,28 @@
} }
}); });
if (tofill.length > 0) { if (tofill.length > 0) {
fillAsync(tofill, angle, spacing, newfill); doFillArea(fillQ, tofill, angle, spacing, newfill);
top.fill_lines_norm = {angle:angle,spacing:spacing}; top.fill_lines_norm = {angle:angle,spacing:spacing};
} }
if (angfill.length > 0) { if (angfill.length > 0) {
top.fill_lines_ang = {spacing:spacing,list:[],poly:[]}; top.fill_lines_ang = {spacing:spacing,list:[],poly:[]};
angfill.forEach(function(af) { angfill.forEach(function(af) {
fillAsync([af], af.fillang.angle + 45, spacing, newfill); doFillArea(fillQ, [af], af.fillang.angle + 45, spacing, newfill);
top.fill_lines_ang.list.push(af.fillang.angle + 45); top.fill_lines_ang.list.push(af.fillang.angle + 45);
top.fill_lines_ang.poly.push(af.clone()); top.fill_lines_ang.poly.push(af.clone());
}); });
} }
// top.fill_lines.appendAll(newfill);
}); });
return true; return true;
}; };
let fillQ = []; function doFillArea(fillQ, polys, angle, spacing, output, minLen, maxLen) {
if (fillQ) {
function fillAsync(polys, angle, spacing, output, minLen, maxLen) { fillQ.push(KIRI.minions.fill(polys, angle, spacing, output, minLen, maxLen));
fillQ.push(KIRI.minions.fill(polys, angle, spacing, output, minLen, maxLen)); } else {
} POLY.fillArea(polys, angle, spacing, output, minLen, maxLen);
}
async function fillResolve() {
// console.log({resolving: fillQ.length});
await Promise.all(fillQ);
fillQ.length = 0;
} }
/** /**