add minions and 1st implementation with poly array union
This commit is contained in:
parent
e94a8d4d1f
commit
1884cd10d1
5 changed files with 245 additions and 123 deletions
25
app.js
25
app.js
|
|
@ -325,6 +325,29 @@ const script = {
|
|||
"kiri/codec",
|
||||
"kiri/worker"
|
||||
].map(p => `src/${p}.js`),
|
||||
minion : [
|
||||
"kiri",
|
||||
"license",
|
||||
"ext/clip2",
|
||||
"ext/earcut",
|
||||
"add/array",
|
||||
"add/class",
|
||||
"geo/base",
|
||||
"geo/debug",
|
||||
"geo/point",
|
||||
"geo/points",
|
||||
"geo/slope",
|
||||
"geo/line",
|
||||
"geo/bounds",
|
||||
"geo/polygon",
|
||||
"geo/polygons",
|
||||
"geo/gyroid",
|
||||
"kiri/slice",
|
||||
"kiri/layers",
|
||||
"kiri/widget",
|
||||
"kiri/codec",
|
||||
"kiri/minion"
|
||||
].map(p => `src/${p}.js`),
|
||||
engine : [
|
||||
"kiri",
|
||||
"license",
|
||||
|
|
@ -342,7 +365,6 @@ const script = {
|
|||
"geo/polygon",
|
||||
"geo/polygons",
|
||||
"moto/kv",
|
||||
// "moto/ajax",
|
||||
"moto/load-stl",
|
||||
"kiri/conf",
|
||||
"kiri/client",
|
||||
|
|
@ -550,6 +572,7 @@ function prepareScripts() {
|
|||
code.meta = concatCode(script.meta);
|
||||
code.kiri = concatCode(script.kiri);
|
||||
code.worker = concatCode(script.worker);
|
||||
code.minion = concatCode(script.minion);
|
||||
code.engine = concatCode(script.engine);
|
||||
code.frame = concatCode(script.frame);
|
||||
}
|
||||
|
|
|
|||
34
src/kiri/minion.js
Normal file
34
src/kiri/minion.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
"use strict";
|
||||
|
||||
let BASE = self.base,
|
||||
KIRI = self.kiri,
|
||||
UTIL = BASE.util,
|
||||
POLY = BASE.polygons,
|
||||
CODEC = KIRI.codec;
|
||||
|
||||
// catch clipper alerts and convert to console messages
|
||||
self.alert = function(o) {
|
||||
console.log(o);
|
||||
};
|
||||
|
||||
self.onmessage = function(msg) {
|
||||
let data = msg.data;
|
||||
switch (data.cmd) {
|
||||
case "union":
|
||||
if (!(data.polys && data.polys.length)) {
|
||||
self.postMessage({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)});
|
||||
break;
|
||||
default:
|
||||
self.postMessage({error: "invalid command"});
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// console.log(`kiri | init mini | ${KIRI.version || "rogue"}`);
|
||||
|
|
@ -5,20 +5,81 @@
|
|||
let BASE = self.base,
|
||||
KIRI = self.kiri,
|
||||
UTIL = BASE.util,
|
||||
POLY = BASE.polygons,
|
||||
time = UTIL.time,
|
||||
qtpi = Math.cos(Math.PI/4),
|
||||
concurrent = self.Worker ? navigator.hardwareConcurrency || 0 : 0,
|
||||
current = self.worker = {
|
||||
print: null,
|
||||
snap: null
|
||||
},
|
||||
wgroup = {},
|
||||
wcache = {};
|
||||
wcache = {},
|
||||
minions = [],
|
||||
minionq = [];
|
||||
|
||||
// catch clipper alerts and convert to console messages
|
||||
self.alert = function(o) {
|
||||
console.log(o);
|
||||
};
|
||||
|
||||
// start concurrent workers (minions)
|
||||
if (concurrent) {
|
||||
for (let i=0; i < concurrent; i++) {
|
||||
minions.push(new Worker(`/code/minion.js?${self.kiri.version}`));
|
||||
}
|
||||
console.log(`kiri | init mini | ${KIRI.version || "rogue"} | ${concurrent}`);
|
||||
}
|
||||
|
||||
// for concurrent operations
|
||||
KIRI.minions = {
|
||||
union: function(polys, minarea) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (concurrent === 0 || polys.length * 2 < concurrent) {
|
||||
resolve(POLY.union(polys, 0, true));
|
||||
}
|
||||
let polyper = Math.ceil(polys.length / concurrent);
|
||||
let running = 0;
|
||||
let union = [];
|
||||
let receiver = function(msg) {
|
||||
let polys = KIRI.codec.decode(msg.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({
|
||||
cmd: "union",
|
||||
minarea,
|
||||
polys: KIRI.codec.encode(polys.slice(i, i + polyper))
|
||||
});
|
||||
running++;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
queue: function(work) {
|
||||
return new Promise((resolve, reject) => {
|
||||
minionq.push({work, resolve, reject});
|
||||
kick();
|
||||
});
|
||||
},
|
||||
|
||||
kick: function() {
|
||||
if (minions.length && minionq.length) {
|
||||
let qrec = minionq.shift();
|
||||
let minion = minions.shift();
|
||||
minion.onmessage = (msg) => {
|
||||
qrec.resolve(msg.data);
|
||||
minions.push(minion);
|
||||
};
|
||||
minion.postMessage(work);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
console.log(`kiri | init work | ${KIRI.version || "rogue"}`);
|
||||
BASE.debug.disable();
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,10 @@
|
|||
}
|
||||
|
||||
function onSliceDone(slices) {
|
||||
onSliceDoneAsync(slices).then(ondone);
|
||||
}
|
||||
|
||||
async function onSliceDoneAsync(slices) {
|
||||
// remove all empty slices above part but leave below
|
||||
// for multi-part (multi-extruder) setups where the void is ok
|
||||
// also reverse because slicing occurs bottom-up
|
||||
|
|
@ -294,6 +298,7 @@
|
|||
}
|
||||
sliceFillAngle += 90.0;
|
||||
}, "offsets");
|
||||
|
||||
// add lead in when specified in belt mode
|
||||
if (!isSynth && isBelt) {
|
||||
// find adjusted zero point from slices
|
||||
|
|
@ -461,16 +466,18 @@
|
|||
// auto support generation
|
||||
if (!isBelt && !isSynth && supportDensity && spro.sliceSupportEnable) {
|
||||
// create shadow for clipping supports
|
||||
let mark = Date.now();
|
||||
let shadow = null;
|
||||
let alltops = slices.map(slice => slice.topPolys()).flat();
|
||||
let alllen = alltops.map(p => p.deepLength).reduce((a,v)=>a+v);
|
||||
// console.log({alllen});
|
||||
if (alllen > 100000) {
|
||||
alltops = alltops.map(p => p.clean(true, undefined, 10000));
|
||||
// console.log({alllen});
|
||||
alltops = alltops.map(p => p.clean(true, undefined, 5000));
|
||||
// console.log({reduced: alltops.map(p => p.deepLength).reduce((a,v)=>a+v)});
|
||||
}
|
||||
shadow = POLY.union(alltops,0.1,true);
|
||||
// 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});
|
||||
if (spro.sliceSupportExtra) {
|
||||
shadow = POLY.offset(shadow, spro.sliceSupportExtra);
|
||||
}
|
||||
|
|
@ -502,9 +509,6 @@
|
|||
widget.belt.miny = -bounds.miny;
|
||||
widget.belt.midy = (bounds.miny + bounds.maxy) / 2;
|
||||
}
|
||||
|
||||
// report slicing complete
|
||||
ondone();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -602,16 +606,20 @@
|
|||
*/
|
||||
function doShells(slice, count, offsetN, fillOffset, opt = {}) {
|
||||
let offset1 = offsetN / 2;
|
||||
let shellout = 0;
|
||||
|
||||
slice.tops.forEach(function(top) {
|
||||
let top_poly = [ top.poly ];
|
||||
|
||||
if (slice.index === 0) {
|
||||
// console.log({slice_top_0: top_poly, count});
|
||||
// segment polygon
|
||||
}
|
||||
|
||||
for (let top of slice.tops) {
|
||||
doTopShells(slice.z, top, count, offset1, offsetN, fillOffset, opt);
|
||||
}
|
||||
}
|
||||
|
||||
function doTopShells(z, top, count, offset1, offsetN, fillOffset, opt) {
|
||||
let top_poly = [ top.poly ];
|
||||
|
||||
if (opt.vase) {
|
||||
// remove top poly inners in vase mode
|
||||
top.poly = top.poly.clone(false);
|
||||
|
|
@ -622,8 +630,7 @@
|
|||
top.fill_lines = [];
|
||||
|
||||
let last = [],
|
||||
gaps = [],
|
||||
z = top.poly.getZ();
|
||||
gaps = [];
|
||||
|
||||
if (count) {
|
||||
// permit offset of 0 for laser and drag knife
|
||||
|
|
@ -720,20 +727,17 @@
|
|||
// if gaps present, remove that area from fill inset
|
||||
if (gaps.length) {
|
||||
let nulast = [];
|
||||
POLY.subtract(last, gaps, nulast, null, slice.z);
|
||||
POLY.subtract(last, gaps, nulast, null, z);
|
||||
last = nulast;
|
||||
}
|
||||
last.forEach(function(inner) {
|
||||
POLY.offset([inner], -fillOffset, {outs: top.fill_off, flat: true, z: slice.z});
|
||||
POLY.offset([inner], -fillOffset, {outs: top.fill_off, flat: true, z});
|
||||
});
|
||||
}
|
||||
|
||||
// for diffing
|
||||
top.last = last;
|
||||
|
||||
shellout += top.shells.length;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an entirely solid layer by filling all top polygons
|
||||
|
|
|
|||
Loading…
Reference in a new issue