move shell generation into slice (new) post-processor which means it can be distributed and co-located with slicing in minion
This commit is contained in:
parent
7072afb613
commit
e2ef4ff7e2
10 changed files with 246 additions and 156 deletions
|
|
@ -38,8 +38,8 @@
|
||||||
let count = 0;
|
let count = 0;
|
||||||
if (tracker)
|
if (tracker)
|
||||||
for (let p of promises) {
|
for (let p of promises) {
|
||||||
p.then(() => {
|
p.then(data => {
|
||||||
tracker(count++, promises.length);
|
tracker(count++, promises.length, data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,10 @@ const funcs = {
|
||||||
realp[p++] = BASE.newPoint(points[i++], points[i++], points[i++]);
|
realp[p++] = BASE.newPoint(points[i++], points[i++], points[i++]);
|
||||||
}
|
}
|
||||||
let output = [];
|
let output = [];
|
||||||
for (let slice of slices) {
|
for (let params of slices) {
|
||||||
output.push({
|
output.push({
|
||||||
slice,
|
params,
|
||||||
tops: KIRI.slicer.sliceZ(slice.z, realp, options).tops
|
data: { tops: KIRI.slicer.sliceZ(params.z, realp, options, params).tops }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
reply({ seq, output: CODEC.encode(output) });
|
reply({ seq, output: CODEC.encode(output) });
|
||||||
|
|
|
||||||
|
|
@ -176,9 +176,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
PRO.addTop = function(poly) {
|
PRO.addTop = function(poly) {
|
||||||
let top = new Top(poly);
|
if (poly.length) {
|
||||||
this.tops.push(top);
|
let top = new Top(poly);
|
||||||
return top;
|
this.tops.push(top);
|
||||||
|
return top;
|
||||||
|
} else {
|
||||||
|
let top = new Top(poly.poly);
|
||||||
|
top.fill_lines = poly.fill_lines;
|
||||||
|
top.fill_off = poly.fill_off;
|
||||||
|
top.last = poly.last;
|
||||||
|
top.shells = poly.shells;
|
||||||
|
this.tops.push(top);
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
console.log('top', poly);
|
||||||
|
throw "invalid top";
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.findClosestPointTo = function(target) {
|
PRO.findClosestPointTo = function(target) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slicing engine used by FDM, Laser, and SLA
|
||||||
|
*/
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (self.kiri.slicer) return;
|
if (self.kiri.slicer) return;
|
||||||
|
|
@ -10,7 +13,8 @@
|
||||||
slice,
|
slice,
|
||||||
sliceZ,
|
sliceZ,
|
||||||
sliceWidget,
|
sliceWidget,
|
||||||
connectLines
|
connectLines,
|
||||||
|
createSlice
|
||||||
};
|
};
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
let KIRI = self.kiri,
|
||||||
|
|
@ -138,8 +142,8 @@
|
||||||
if (concurrent > 1) {
|
if (concurrent > 1) {
|
||||||
if (bucketCount < concurrent) {
|
if (bucketCount < concurrent) {
|
||||||
bucketCount = concurrent;
|
bucketCount = concurrent;
|
||||||
} else if (bucketCount > 128) {
|
} else if (bucketCount > 100) {
|
||||||
bucketCount = 128;
|
bucketCount = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -302,42 +306,65 @@
|
||||||
|
|
||||||
function bucketZ(index, z, height, thick) {
|
function bucketZ(index, z, height, thick) {
|
||||||
buckets[Math.floor(z * zScale)].slices.push({
|
buckets[Math.floor(z * zScale)].slices.push({
|
||||||
index, z, height, thick
|
index, z, height, thick, total: zIndexes.length
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sliceBuckets() {
|
async function sliceBuckets() {
|
||||||
let output = [];
|
let output = [];
|
||||||
// console.log({buckets});
|
if (concurrent) {
|
||||||
if (concurrent < 2) {
|
let promises = buckets.map(
|
||||||
sliceBucketsLocal(buckets, output);
|
bucket => KIRI.minions.sliceBucket(bucket, options, output)
|
||||||
} else {
|
);
|
||||||
let promises = [];
|
await tracker(promises, (i,t,d) => {
|
||||||
for (let bucket of buckets) {
|
|
||||||
promises.push(KIRI.minions.sliceBucket(bucket, options, output));
|
|
||||||
}
|
|
||||||
await tracker(promises, (i,t) => {
|
|
||||||
onupdate(0.1 + (i / t) * 0.9);
|
onupdate(0.1 + (i / t) * 0.9);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
let count = 0;
|
||||||
|
for (let bucket of buckets) {
|
||||||
|
for (let params of bucket.slices) {
|
||||||
|
output.push(createSlice(
|
||||||
|
params,
|
||||||
|
sliceZ(params.z, bucket.points, options, params),
|
||||||
|
options
|
||||||
|
));
|
||||||
|
onupdate(0.1 + (count++ / zIndexes.length) * 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sliceBucketsLocal(buckets, output) {
|
}
|
||||||
let count = 0;
|
|
||||||
for (let bucket of buckets) {
|
function createSlice(params, data, options = {}) {
|
||||||
for (let slice of bucket.slices) {
|
let { index, z, height, thick } = params;
|
||||||
let { index, z, height, thick } = slice;
|
let { lines, groups, tops } = data;
|
||||||
let { lines, groups, tops } = sliceZ(z, bucket.points, options);
|
let slice = newSlice(z).addTops(tops);
|
||||||
slice = newSlice(z).addTops(tops);
|
slice.height = height;
|
||||||
slice.height = height;
|
slice.index = index;
|
||||||
slice.index = index;
|
slice.thick = thick;
|
||||||
slice.thick = thick;
|
// debugging (non-threaded mode only)
|
||||||
output.push(slice);
|
let { debug, xray, view } = options;
|
||||||
onupdate(0.1 + (count++ / zIndexes.length) * 0.9);
|
if (view && (debug || xray)) {
|
||||||
}
|
if ((debug && lines.excessive) || xray) {
|
||||||
|
const dash = xray || 3;
|
||||||
|
lines.forEach((line, i) => {
|
||||||
|
const group = i % dash;
|
||||||
|
const color = [ 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff ][group];
|
||||||
|
slice.output().setLayer(`xl-${group}`, color).addLine(line.p1, line.p2);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
POLY.nest(groups).forEach((poly, i) => {
|
||||||
|
slice.addTop(poly);
|
||||||
|
if (xray) {
|
||||||
|
const group = i % (xray || 3);
|
||||||
|
const color = [ 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff ][group];
|
||||||
|
slice.output().setLayer(`xg-${group}`, color).addPoly(poly);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
return slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ***** SLICING FUNCTIONS ***** */
|
/** ***** SLICING FUNCTIONS ***** */
|
||||||
|
|
@ -421,7 +448,7 @@
|
||||||
* @param {number} z
|
* @param {number} z
|
||||||
* @param {number} [height] optional real height (fdm)
|
* @param {number} [height] optional real height (fdm)
|
||||||
*/
|
*/
|
||||||
function sliceZ(z, points, options = {}) {
|
function sliceZ(z, points, options = {}, params = {}) {
|
||||||
let phash = {},
|
let phash = {},
|
||||||
lines = [],
|
lines = [],
|
||||||
p1, p2, p3;
|
p1, p2, p3;
|
||||||
|
|
@ -477,28 +504,18 @@
|
||||||
groups = POLY.flatten(POLY.union(POLY.nest(groups), null, true), null, true);
|
groups = POLY.flatten(POLY.union(POLY.nest(groups), null, true), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ((debug && lines.excessive) || xray) {
|
|
||||||
// const dash = xray || 3;
|
|
||||||
// lines.forEach((line, i) => {
|
|
||||||
// const group = i % dash;
|
|
||||||
// const color = [ 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff ][group];
|
|
||||||
// slice.output().setLayer(`xl-${group}`, color).addLine(line.p1, line.p2);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
let tops = POLY.nest(groups);
|
let tops = POLY.nest(groups);
|
||||||
|
let data = { lines, groups, tops };
|
||||||
|
|
||||||
// identify and add tops to slice
|
// look for driver-specific slice post-processor
|
||||||
// POLY.nest(groups).forEach((poly, i) => {
|
if (options.mode) {
|
||||||
// slice.addTop(poly);
|
let fn = KIRI.driver[options.mode].slicePost;
|
||||||
// if (xray) {
|
if (fn) {
|
||||||
// const group = i % (xray || 3);
|
fn(data, options, params);
|
||||||
// const color = [ 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff ][group];
|
}
|
||||||
// slice.output().setLayer(`xg-${group}`, color).addPoly(poly);
|
}
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
return { lines, groups, tops };
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slicing engine used by CAM
|
||||||
|
*/
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
let KIRI = self.kiri,
|
||||||
|
|
|
||||||
|
|
@ -145,16 +145,12 @@ KIRI.minions = {
|
||||||
slices,
|
slices,
|
||||||
options
|
options
|
||||||
}, data => {
|
}, data => {
|
||||||
for (let rec of KIRI.codec.decode(data.output)) {
|
let recs = KIRI.codec.decode(data.output);
|
||||||
let { slice, tops } = rec;
|
for (let rec of recs) {
|
||||||
let newSlice = KIRI.newSlice(slice.z);
|
let { params, data } = rec;
|
||||||
newSlice.index = slice.index;
|
output.push(KIRI.slicer.createSlice(params, data));
|
||||||
newSlice.thick = slice.thick;
|
|
||||||
newSlice.height = slice.height;
|
|
||||||
newSlice.addTops(tops);
|
|
||||||
output.push(newSlice);
|
|
||||||
}
|
}
|
||||||
resolve();
|
resolve(recs);
|
||||||
}, [ floatP.buffer ]);
|
}, [ floatP.buffer ]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,15 @@
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRangeParameters(settings, index) {
|
function getRangeParameters(process, index) {
|
||||||
if (index === undefined || index === null || index < 0) {
|
if (index === undefined || index === null || index < 0) {
|
||||||
return settings.process;
|
return process;
|
||||||
}
|
}
|
||||||
let ranges = settings.process.ranges;
|
let ranges = process.ranges;
|
||||||
if (!(ranges && ranges.length)) {
|
if (!(ranges && ranges.length)) {
|
||||||
return settings.process;
|
return process;
|
||||||
}
|
}
|
||||||
let params = Object.clone(settings.process);
|
let params = Object.clone(process);
|
||||||
for (let range of ranges) {
|
for (let range of ranges) {
|
||||||
if (index >= range.lo && index <= range.hi) {
|
if (index >= range.lo && index <= range.hi) {
|
||||||
for (let [key,value] of Object.entries(range.fields)) {
|
for (let [key,value] of Object.entries(range.fields)) {
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
|
|
||||||
// smallish band-aid. refactor above to remove redundancy
|
// smallish band-aid. refactor above to remove redundancy
|
||||||
function updateParams(layer) {
|
function updateParams(layer) {
|
||||||
let process = getRangeParameters(settings, layer);
|
let process = getRangeParameters(process, layer);
|
||||||
zhop = process.zHopDistance || 0; // range
|
zhop = process.zHopDistance || 0; // range
|
||||||
retDist = process.outputRetractDist || 0; // range
|
retDist = process.outputRetractDist || 0; // range
|
||||||
retSpeed = process.outputRetractSpeed * 60 || 1; // range
|
retSpeed = process.outputRetractSpeed * 60 || 1; // range
|
||||||
|
|
|
||||||
|
|
@ -374,7 +374,7 @@
|
||||||
return a.dst - b.dst;
|
return a.dst - b.dst;
|
||||||
});
|
});
|
||||||
let { z, slice, offset } = order[0];
|
let { z, slice, offset } = order[0];
|
||||||
let params = getRangeParameters(settings, slice.index);
|
let params = getRangeParameters(process, slice.index);
|
||||||
slice.prep = true;
|
slice.prep = true;
|
||||||
// retract between widgets or layers (when set)
|
// retract between widgets or layers (when set)
|
||||||
if (layerout.length && slice.widget !== lastWidget) {
|
if (layerout.length && slice.widget !== lastWidget) {
|
||||||
|
|
@ -474,7 +474,7 @@
|
||||||
// iterate over layers, find extrusion on belt and
|
// iterate over layers, find extrusion on belt and
|
||||||
// apply corrections and add brim when specified
|
// apply corrections and add brim when specified
|
||||||
for (let layer of output) {
|
for (let layer of output) {
|
||||||
let params = getRangeParameters(settings, layer.layer || 0);
|
let params = getRangeParameters(process, layer.layer || 0);
|
||||||
let brimHalf = params.firstLayerBrim < 0;
|
let brimHalf = params.firstLayerBrim < 0;
|
||||||
let firstLayerBrim = Math.abs(params.firstLayerBrim);
|
let firstLayerBrim = Math.abs(params.firstLayerBrim);
|
||||||
let firstLayerBrimIn = params.firstLayerBrimIn;
|
let firstLayerBrimIn = params.firstLayerBrimIn;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
PROTO = Object.clone(COLOR),
|
PROTO = Object.clone(COLOR),
|
||||||
bwcomp = (1 / Math.cos(Math.PI/4)),
|
bwcomp = (1 / Math.cos(Math.PI/4)),
|
||||||
getRangeParameters = FDM.getRangeParameters,
|
getRangeParameters = FDM.getRangeParameters,
|
||||||
|
slicePost = true,
|
||||||
debug = false;
|
debug = false;
|
||||||
|
|
||||||
let isThin = false; // force line rendering
|
let isThin = false; // force line rendering
|
||||||
|
|
@ -46,6 +47,49 @@
|
||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log('slicing', {debug, slicePost});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* may run in minion or worker context. do not create objects
|
||||||
|
* that will not quickly encode in threaded mode. add to existing
|
||||||
|
* data object. return is ignored.
|
||||||
|
*/
|
||||||
|
FDM.slicePost = slicePost ? function(data, options, params) {
|
||||||
|
let { lines, groups, tops } = data;
|
||||||
|
let { z, index, total, height, thick } = params;
|
||||||
|
let { process, isSynth, isDanger, vaseMode, shellOffset, fillOffset } = options.post;
|
||||||
|
let range = getRangeParameters(process, index);
|
||||||
|
let shellFrac = (range.sliceShells - (range.sliceShells | 0));
|
||||||
|
let sliceShells = range.sliceShells | 0;
|
||||||
|
if (shellFrac) {
|
||||||
|
let v1 = shellFrac > 0.5 ? 1 - shellFrac : shellFrac;
|
||||||
|
let v2 = 1 - v1;
|
||||||
|
let parts = Math.round(v2/v1) + 1;
|
||||||
|
let rem = index % parts;
|
||||||
|
let trg = shellFrac > 0.5 ? 1 : parts - 1;
|
||||||
|
sliceShells += rem >= trg ? 1 : 0;
|
||||||
|
}
|
||||||
|
let spaceMult = index === 0 ? process.firstLayerLineMult || 1 : 1;
|
||||||
|
let isBottom = index < process.sliceBottomLayers;
|
||||||
|
let isTop = index > total - process.sliceTopLayers - 1;
|
||||||
|
let isDense = range.sliceFillSparse > 0.98;
|
||||||
|
let isSolid = (isBottom || ((isTop || isDense) && !vaseMode)) && !isSynth;
|
||||||
|
let solidWidth = isSolid ? range.sliceFillWidth || 1 : 0;
|
||||||
|
let count = isSynth ? 1 : sliceShells;
|
||||||
|
let offset = shellOffset * spaceMult;
|
||||||
|
let fillOff = fillOffset * spaceMult;
|
||||||
|
|
||||||
|
let nutops = [];
|
||||||
|
for (let top of tops) {
|
||||||
|
nutops.push(FDM.share.doTopShells(z, top, count, offset/2, offset, fillOff, {
|
||||||
|
vase: vaseMode,
|
||||||
|
thin: process.detectThinWalls && !isSynth,
|
||||||
|
danger: isDanger
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
data.tops = nutops;
|
||||||
|
} : undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DRIVER SLICE CONTRACT
|
* DRIVER SLICE CONTRACT
|
||||||
*
|
*
|
||||||
|
|
@ -62,32 +106,31 @@
|
||||||
FDM.slice = function(settings, widget, onupdate, ondone) {
|
FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
FDM.fixExtruders(settings);
|
FDM.fixExtruders(settings);
|
||||||
let render = settings.render !== false,
|
let render = settings.render !== false,
|
||||||
ctrl = settings.controller,
|
{ process, device, controller } = settings,
|
||||||
spro = settings.process,
|
isBelt = device.bedBelt,
|
||||||
sdev = settings.device,
|
|
||||||
isBelt = sdev.bedBelt,
|
|
||||||
isSynth = widget.track.synth,
|
isSynth = widget.track.synth,
|
||||||
minSolid = spro.sliceSolidMinArea,
|
isDanger = controller.danger,
|
||||||
solidLayers = spro.sliceSolidLayers,
|
minSolid = process.sliceSolidMinArea,
|
||||||
vaseMode = spro.sliceFillType === 'vase' && !isSynth,
|
solidLayers = process.sliceSolidLayers,
|
||||||
|
vaseMode = process.sliceFillType === 'vase' && !isSynth,
|
||||||
doSolidLayers = solidLayers && !vaseMode && !isSynth,
|
doSolidLayers = solidLayers && !vaseMode && !isSynth,
|
||||||
metadata = settings.widget[widget.id] || {},
|
metadata = settings.widget[widget.id] || {},
|
||||||
extruder = metadata.extruder || 0,
|
extruder = metadata.extruder || 0,
|
||||||
sliceHeight = spro.sliceHeight,
|
sliceHeight = process.sliceHeight,
|
||||||
firstSliceHeight = isBelt ? sliceHeight : spro.firstSliceHeight,
|
firstSliceHeight = isBelt ? sliceHeight : process.firstSliceHeight,
|
||||||
nozzleSize = sdev.extruders[extruder].extNozzle,
|
nozzleSize = device.extruders[extruder].extNozzle,
|
||||||
lineWidth = spro.sliceLineWidth || nozzleSize,
|
lineWidth = process.sliceLineWidth || nozzleSize,
|
||||||
fillOffsetMult = 1.0 - bound(spro.sliceFillOverlap, 0, 0.8),
|
fillOffsetMult = 1.0 - bound(process.sliceFillOverlap, 0, 0.8),
|
||||||
shellOffset = lineWidth,
|
shellOffset = lineWidth,
|
||||||
fillSpacing = lineWidth,
|
fillSpacing = lineWidth,
|
||||||
fillOffset = lineWidth * fillOffsetMult,
|
fillOffset = lineWidth * fillOffsetMult,
|
||||||
sliceFillAngle = spro.sliceFillAngle,
|
sliceFillAngle = process.sliceFillAngle,
|
||||||
supportDensity = spro.sliceSupportDensity,
|
supportDensity = process.sliceSupportDensity,
|
||||||
beltfact = Math.cos(Math.PI/4),
|
beltfact = Math.cos(Math.PI/4),
|
||||||
doConcurrent = ctrl.threaded && KIRI.minions.concurrent;
|
doConcurrent = controller.threaded && KIRI.minions.concurrent;
|
||||||
|
|
||||||
isFlat = ctrl.lineType === "flat";
|
isFlat = controller.lineType === "flat";
|
||||||
isThin = !isFlat && ctrl.lineType === "line";
|
isThin = !isFlat && controller.lineType === "line";
|
||||||
offset = lineWidth / 2;
|
offset = lineWidth / 2;
|
||||||
|
|
||||||
if (isFlat) {
|
if (isFlat) {
|
||||||
|
|
@ -117,8 +160,8 @@
|
||||||
firstSliceHeight = sliceHeight;
|
firstSliceHeight = sliceHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sliceMinHeight = spro.sliceAdaptive && spro.sliceMinHeight > 0 ?
|
const sliceMinHeight = process.sliceAdaptive && process.sliceMinHeight > 0 ?
|
||||||
Math.min(spro.sliceMinHeight, sliceHeight) : 0;
|
Math.min(process.sliceMinHeight, sliceHeight) : 0;
|
||||||
|
|
||||||
if (firstSliceHeight < sliceHeight) {
|
if (firstSliceHeight < sliceHeight) {
|
||||||
DBUG.log("invalid first layer height < slice height");
|
DBUG.log("invalid first layer height < slice height");
|
||||||
|
|
@ -127,15 +170,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
SLICER.sliceWidget(widget, {
|
SLICER.sliceWidget(widget, {
|
||||||
|
mode: 'FDM',
|
||||||
height: sliceHeight,
|
height: sliceHeight,
|
||||||
minHeight: sliceMinHeight,
|
minHeight: sliceMinHeight,
|
||||||
firstHeight: firstSliceHeight,
|
firstHeight: firstSliceHeight,
|
||||||
union: ctrl.healMesh,
|
union: controller.healMesh,
|
||||||
|
indices: process.indices,
|
||||||
|
concurrent: doConcurrent,
|
||||||
|
post: slicePost ? {
|
||||||
|
shellOffset,
|
||||||
|
fillOffset,
|
||||||
|
lineWidth,
|
||||||
|
vaseMode,
|
||||||
|
isSynth,
|
||||||
|
process,
|
||||||
|
isDanger
|
||||||
|
} : undefined
|
||||||
// debug: true,
|
// debug: true,
|
||||||
// xray: 3,
|
|
||||||
// view: view,
|
// view: view,
|
||||||
indices: spro.indices,
|
// xray: 3,
|
||||||
concurrent: doConcurrent
|
|
||||||
}, onSliceDone, onSliceUpdate);
|
}, onSliceDone, onSliceUpdate);
|
||||||
|
|
||||||
function onSliceUpdate(update) {
|
function onSliceUpdate(update) {
|
||||||
|
|
@ -169,8 +222,8 @@
|
||||||
shadow = doConcurrent ?
|
shadow = doConcurrent ?
|
||||||
await KIRI.minions.union(alltops, 0.1) :
|
await KIRI.minions.union(alltops, 0.1) :
|
||||||
POLY.union(alltops, 0.1, true);
|
POLY.union(alltops, 0.1, true);
|
||||||
if (spro.sliceSupportExtra) {
|
if (process.sliceSupportExtra) {
|
||||||
shadow = POLY.offset(shadow, spro.sliceSupportExtra);
|
shadow = POLY.offset(shadow, process.sliceSupportExtra);
|
||||||
}
|
}
|
||||||
widget.shadow = POLY.setZ(shadow, 0);
|
widget.shadow = POLY.setZ(shadow, 0);
|
||||||
// slices[0].output()
|
// slices[0].output()
|
||||||
|
|
@ -198,7 +251,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// create shadow for non-belt supports
|
// create shadow for non-belt supports
|
||||||
if (!isBelt && (isSynth || (!isSynth && supportDensity && spro.sliceSupportEnable))) {
|
if (!isBelt && (isSynth || (!isSynth && supportDensity && process.sliceSupportEnable))) {
|
||||||
await doShadow(slices);
|
await doShadow(slices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,7 +267,7 @@
|
||||||
slice.addTop(u);
|
slice.addTop(u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let gap = sliceHeight * (isBelt ? 0 : spro.sliceSupportGap);
|
let gap = sliceHeight * (isBelt ? 0 : process.sliceSupportGap);
|
||||||
// clip tops to other widgets in group
|
// clip tops to other widgets in group
|
||||||
tops = slice.topPolys();
|
tops = slice.topPolys();
|
||||||
for (let peer of widget.group) {
|
for (let peer of widget.group) {
|
||||||
|
|
@ -226,9 +279,9 @@
|
||||||
if (Math.abs(Math.abs(pslice.z - slice.z) - gap) > 0.1) {
|
if (Math.abs(Math.abs(pslice.z - slice.z) - gap) > 0.1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// offset pslice tops by spro.sliceSupportOffset
|
// offset pslice tops by process.sliceSupportOffset
|
||||||
if (!pslice.synth_off) {
|
if (!pslice.synth_off) {
|
||||||
pslice.synth_off = POLY.offset(pslice.topPolys(), spro.sliceSupportOffset);
|
pslice.synth_off = POLY.offset(pslice.topPolys(), process.sliceSupportOffset);
|
||||||
}
|
}
|
||||||
let ptops = pslice.synth_off;
|
let ptops = pslice.synth_off;
|
||||||
let ntops = [];
|
let ntops = [];
|
||||||
|
|
@ -276,7 +329,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not hint polygin fill longer than a max span length
|
// do not hint polygin fill longer than a max span length
|
||||||
CONF.hint_len_max = UTIL.sqr(spro.sliceBridgeMax);
|
CONF.hint_len_max = UTIL.sqr(process.sliceBridgeMax);
|
||||||
|
|
||||||
// reset for solids, support projections
|
// reset for solids, support projections
|
||||||
// and other annotations
|
// and other annotations
|
||||||
|
|
@ -286,46 +339,48 @@
|
||||||
slice.solids = [];
|
slice.solids = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
let promises = doConcurrent ? [] : undefined;
|
|
||||||
// create shells and diff inner fillable areas
|
// create shells and diff inner fillable areas
|
||||||
forSlices(0.0, promises ? 0.05 : 0.15, slice => {
|
if (!slicePost) {
|
||||||
let params = slice.params = getRangeParameters(settings, slice.index);
|
let promises = doConcurrent ? [] : undefined;
|
||||||
let shellFrac = (params.sliceShells - (params.sliceShells | 0));
|
forSlices(0.0, promises ? 0.05 : 0.15, slice => {
|
||||||
let sliceShells = params.sliceShells | 0;
|
let params = slice.params = getRangeParameters(process, slice.index);
|
||||||
if (shellFrac) {
|
let shellFrac = (params.sliceShells - (params.sliceShells | 0));
|
||||||
let v1 = shellFrac > 0.5 ? 1 - shellFrac : shellFrac;
|
let sliceShells = params.sliceShells | 0;
|
||||||
let v2 = 1 - v1;
|
if (shellFrac) {
|
||||||
let parts = Math.round(v2/v1) + 1;
|
let v1 = shellFrac > 0.5 ? 1 - shellFrac : shellFrac;
|
||||||
let rem = slice.index % parts;
|
let v2 = 1 - v1;
|
||||||
let trg = shellFrac > 0.5 ? 1 : parts - 1;
|
let parts = Math.round(v2/v1) + 1;
|
||||||
sliceShells += rem >= trg ? 1 : 0;
|
let rem = slice.index % parts;
|
||||||
|
let trg = shellFrac > 0.5 ? 1 : parts - 1;
|
||||||
|
sliceShells += rem >= trg ? 1 : 0;
|
||||||
|
}
|
||||||
|
let first = slice.index === 0;
|
||||||
|
let spaceMult = first ? process.firstLayerLineMult || 1 : 1;
|
||||||
|
let isBottom = slice.index < process.sliceBottomLayers;
|
||||||
|
let isTop = slice.index > slices.length - process.sliceTopLayers-1;
|
||||||
|
let isDense = params.sliceFillSparse > 0.98;
|
||||||
|
let solidWidth = params.sliceFillWidth || 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: process.detectThinWalls && !isSynth,
|
||||||
|
danger: controller.danger
|
||||||
|
}, promises);
|
||||||
|
}, "shells");
|
||||||
|
if (promises) {
|
||||||
|
// await Promise.all(promises);
|
||||||
|
await tracker(promises, (i, t) => {
|
||||||
|
trackupdate(i / t, 0.05, 0.15);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
let first = slice.index === 0;
|
|
||||||
let spaceMult = first ? spro.firstLayerLineMult || 1 : 1;
|
|
||||||
let isBottom = slice.index < spro.sliceBottomLayers;
|
|
||||||
let isTop = slice.index > slices.length - spro.sliceTopLayers-1;
|
|
||||||
let isDense = params.sliceFillSparse > 0.98;
|
|
||||||
let solidWidth = params.sliceFillWidth || 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,
|
|
||||||
danger: ctrl.danger
|
|
||||||
}, promises);
|
|
||||||
}, "shells");
|
|
||||||
if (promises) {
|
|
||||||
// await Promise.all(promises);
|
|
||||||
await tracker(promises, (i, t) => {
|
|
||||||
trackupdate(i / t, 0.05, 0.15);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// just the top/bottom special solid layers
|
// just the top/bottom special solid layers
|
||||||
|
|
@ -335,7 +390,7 @@
|
||||||
doSolidLayerFill(slice, fillSpace, sliceFillAngle);
|
doSolidLayerFill(slice, fillSpace, sliceFillAngle);
|
||||||
}
|
}
|
||||||
sliceFillAngle += 90.0;
|
sliceFillAngle += 90.0;
|
||||||
}, "shells");
|
}, "solid layers");
|
||||||
|
|
||||||
// add lead in when specified in belt mode
|
// add lead in when specified in belt mode
|
||||||
if (!isSynth && isBelt) {
|
if (!isSynth && isBelt) {
|
||||||
|
|
@ -374,13 +429,13 @@
|
||||||
if (!start) start = slice;
|
if (!start) start = slice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let offset = spro.firstLayerBeltLead * beltfact;
|
let offset = process.firstLayerBeltLead * beltfact;
|
||||||
// ensure we start against a layer with shells
|
// ensure we start against a layer with shells
|
||||||
while (start.up && start.topShells().length === 0) {
|
while (start.up && start.topShells().length === 0) {
|
||||||
start = start.up;
|
start = start.up;
|
||||||
}
|
}
|
||||||
// if a brim applies, add that width to anchor
|
// if a brim applies, add that width to anchor
|
||||||
let brim = getRangeParameters(settings, 0).firstLayerBrim || 0;
|
let brim = getRangeParameters(process, 0).firstLayerBrim || 0;
|
||||||
if (brim) {
|
if (brim) {
|
||||||
minx -= brim;
|
minx -= brim;
|
||||||
maxx += brim;
|
maxx += brim;
|
||||||
|
|
@ -414,7 +469,7 @@
|
||||||
offset -= sliceHeight;
|
offset -= sliceHeight;
|
||||||
}
|
}
|
||||||
// add anchor bump
|
// add anchor bump
|
||||||
let bump = spro.firstLayerBeltBump;
|
let bump = process.firstLayerBeltBump;
|
||||||
if (bump) {
|
if (bump) {
|
||||||
adds = adds.reverse().slice(1, adds.length - 1);
|
adds = adds.reverse().slice(1, adds.length - 1);
|
||||||
let count = 1;
|
let count = 1;
|
||||||
|
|
@ -456,7 +511,7 @@
|
||||||
// console.log('start'); await BASE.util.ptimer(1000);
|
// console.log('start'); await BASE.util.ptimer(1000);
|
||||||
let promises = doConcurrent ? [] : undefined;
|
let promises = doConcurrent ? [] : undefined;
|
||||||
forSlices(0.35, promises ? 0.4 : 0.5, slice => {
|
forSlices(0.35, promises ? 0.4 : 0.5, slice => {
|
||||||
let params = slice.params || spro;
|
let params = slice.params || process;
|
||||||
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;
|
||||||
|
|
@ -477,16 +532,16 @@
|
||||||
let lastType;
|
let lastType;
|
||||||
let promises = doConcurrent ? [] : undefined;
|
let promises = doConcurrent ? [] : undefined;
|
||||||
forSlices(0.5, promises ? 0.55 : 0.7, slice => {
|
forSlices(0.5, promises ? 0.55 : 0.7, slice => {
|
||||||
let params = slice.params || spro;
|
let params = slice.params || process;
|
||||||
if (vaseMode || !params.sliceFillSparse) {
|
if (vaseMode || !params.sliceFillSparse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let newType = params.sliceFillType;
|
let newType = params.sliceFillType;
|
||||||
doSparseLayerFill(slice, {
|
doSparseLayerFill(slice, {
|
||||||
settings: settings,
|
settings,
|
||||||
process: spro,
|
process,
|
||||||
device: sdev,
|
device,
|
||||||
lineWidth: lineWidth,
|
lineWidth,
|
||||||
spacing: fillOffset,
|
spacing: fillOffset,
|
||||||
density: params.sliceFillSparse,
|
density: params.sliceFillSparse,
|
||||||
bounds: widget.getBoundingBox(),
|
bounds: widget.getBoundingBox(),
|
||||||
|
|
@ -505,7 +560,7 @@
|
||||||
} else if (isSynth) {
|
} else if (isSynth) {
|
||||||
let promises = doConcurrent ? [] : undefined;
|
let promises = doConcurrent ? [] : undefined;
|
||||||
forSlices(0.5, promises ? 0.6 : 0.7, slice => {
|
forSlices(0.5, promises ? 0.6 : 0.7, slice => {
|
||||||
let params = slice.params || spro;
|
let params = slice.params || process;
|
||||||
let density = params.sliceSupportDensity;
|
let density = params.sliceSupportDensity;
|
||||||
if (density)
|
if (density)
|
||||||
for (let top of slice.tops) {
|
for (let top of slice.tops) {
|
||||||
|
|
@ -523,16 +578,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto support generation
|
// auto support generation
|
||||||
if (!isBelt && !isSynth && supportDensity && spro.sliceSupportEnable) {
|
if (!isBelt && !isSynth && supportDensity && process.sliceSupportEnable) {
|
||||||
doShadow(slices);
|
doShadow(slices);
|
||||||
// console.log('start'); await BASE.util.ptimer(1000);
|
// console.log('start'); await BASE.util.ptimer(1000);
|
||||||
forSlices(0.7, 0.8, slice => {
|
forSlices(0.7, 0.8, slice => {
|
||||||
doSupport(slice, spro, widget.shadow, ctrl.danger);
|
doSupport(slice, process, widget.shadow, controller.danger);
|
||||||
}, "support");
|
}, "support");
|
||||||
// console.log('stop'); await BASE.util.ptimer(1000);
|
// console.log('stop'); await BASE.util.ptimer(1000);
|
||||||
let promises = doConcurrent ? [] : undefined;
|
let promises = doConcurrent ? [] : undefined;
|
||||||
forSlices(0.8, promises ? 0.88 : 0.9, slice => {
|
forSlices(0.8, promises ? 0.88 : 0.9, slice => {
|
||||||
doSupportFill(promises, slice, lineWidth, supportDensity, spro.sliceSupportArea);
|
doSupportFill(promises, slice, lineWidth, supportDensity, process.sliceSupportArea);
|
||||||
}, "support");
|
}, "support");
|
||||||
if (promises) {
|
if (promises) {
|
||||||
await tracker(promises, (i, t) => {
|
await tracker(promises, (i, t) => {
|
||||||
|
|
@ -544,8 +599,8 @@
|
||||||
// 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 || spro;
|
let params = slice.params || process;
|
||||||
doRender(slice, isSynth, params, ctrl.devel);
|
doRender(slice, isSynth, params, controller.devel);
|
||||||
}, "render");
|
}, "render");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -631,7 +686,7 @@
|
||||||
// console.log(slice.index, slice.render.stats);
|
// console.log(slice.index, slice.render.stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// shared with SLA driver
|
// shared with SLA driver and minions
|
||||||
FDM.share = {
|
FDM.share = {
|
||||||
doShells,
|
doShells,
|
||||||
doTopShells,
|
doTopShells,
|
||||||
|
|
@ -682,6 +737,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function doTopShells(z, top, count, offset1, offsetN, fillOffset, opt = {}) {
|
function doTopShells(z, top, count, offset1, offsetN, fillOffset, opt = {}) {
|
||||||
|
// pretend we're a top object in minions
|
||||||
|
if (!top.poly) {
|
||||||
|
top = { poly: top };
|
||||||
|
}
|
||||||
|
|
||||||
let top_poly = [ top.poly ];
|
let top_poly = [ top.poly ];
|
||||||
|
|
||||||
if (opt.vase) {
|
if (opt.vase) {
|
||||||
|
|
@ -801,6 +861,8 @@
|
||||||
|
|
||||||
// for diffing
|
// for diffing
|
||||||
top.last = last;
|
top.last = last;
|
||||||
|
|
||||||
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue