concurrent refactor. added clipping. all toggled with experimental
This commit is contained in:
parent
cb15501a23
commit
881992b52e
3 changed files with 88 additions and 28 deletions
|
|
@ -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"});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue