allow FDM mixing of automatic and manual / detected supports. add outline toggling to automatic supports
This commit is contained in:
parent
8fffc240c4
commit
fc6973ecf9
5 changed files with 68 additions and 69 deletions
|
|
@ -5,6 +5,7 @@ Full docs @ https://docs.grid.space/projects/kiri-moto
|
||||||
|
|
||||||
# Release 3.6
|
# Release 3.6
|
||||||
|
|
||||||
|
* allow FDM mixing of automatic and manual / detected supports
|
||||||
* improve CAM animation speeds using shared array buffers
|
* improve CAM animation speeds using shared array buffers
|
||||||
* improve CAM render quality using solids instead of lines
|
* improve CAM render quality using solids instead of lines
|
||||||
* add CAM leveling part offset parameters for XY and Z
|
* add CAM leveling part offset parameters for XY and Z
|
||||||
|
|
|
||||||
|
|
@ -130,23 +130,6 @@ FDM.init = function(kiri, api) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
api.event.on("boolean.click", func.updateSupportButtons = () => {
|
|
||||||
if (!isFdmMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (let btn of [
|
|
||||||
ui.ssaGen,
|
|
||||||
ui.ssmAdd,
|
|
||||||
ui.ssmDun,
|
|
||||||
ui.ssmClr
|
|
||||||
]) {
|
|
||||||
btn.disabled = ui.sliceSupportEnable.checked;
|
|
||||||
}
|
|
||||||
if (ui.sliceSupportEnable.checked) {
|
|
||||||
func.sclear();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
api.event.on("function.animate", (mode) => {
|
api.event.on("function.animate", (mode) => {
|
||||||
if (!isFdmMode) {
|
if (!isFdmMode) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -205,7 +188,6 @@ FDM.init = function(kiri, api) {
|
||||||
});
|
});
|
||||||
api.event.on("settings.saved", (settings) => {
|
api.event.on("settings.saved", (settings) => {
|
||||||
updateRanges(settings.process.ranges);
|
updateRanges(settings.process.ranges);
|
||||||
func.updateSupportButtons();
|
|
||||||
// let ranges = settings.process.ranges;
|
// let ranges = settings.process.ranges;
|
||||||
// ui.rangeGroup.style.display = isFdmMode && ranges && ranges.length ? 'flex' : 'none';
|
// ui.rangeGroup.style.display = isFdmMode && ranges && ranges.length ? 'flex' : 'none';
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ FDM.prepare = function(widgets, settings, update) {
|
||||||
widgets = widgets.filter(w => !w.track.ignore && !w.meta.disabled);
|
widgets = widgets.filter(w => !w.track.ignore && !w.meta.disabled);
|
||||||
|
|
||||||
let { device, process, controller, bounds, mode } = settings,
|
let { device, process, controller, bounds, mode } = settings,
|
||||||
{ sliceHeight, firstSliceHeight, firstLayerRate } = process,
|
{ sliceHeight, firstSliceHeight, firstLayerRate, sliceSupportOutline } = process,
|
||||||
{ outputSeekrate, outputDraftShield, outputPurgeTower } = process,
|
{ outputSeekrate, outputDraftShield, outputPurgeTower } = process,
|
||||||
{ bedWidth, bedDepth, filamentSource } = device,
|
{ bedWidth, bedDepth, filamentSource } = device,
|
||||||
{ lineType, danger } = controller,
|
{ lineType, danger } = controller,
|
||||||
|
|
@ -1358,7 +1358,9 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) {
|
||||||
print.setType('support');
|
print.setType('support');
|
||||||
// support polygon
|
// support polygon
|
||||||
next.setZ(z);
|
next.setZ(z);
|
||||||
|
if (sliceSupportOutline !== false) {
|
||||||
outputTraces([next].appendAll(next.inner || []));
|
outputTraces([next].appendAll(next.inner || []));
|
||||||
|
}
|
||||||
if (next.fill) {
|
if (next.fill) {
|
||||||
next.fill.forEach(p => { p.z = z });
|
next.fill.forEach(p => { p.z = z });
|
||||||
outputFills(next.fill, {fast: true});
|
outputFills(next.fill, {fast: true});
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,8 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
// allow overriding support fill auto angle algorithm
|
// allow overriding support fill auto angle algorithm
|
||||||
// also causes support fill to be aligned on start boundaries
|
// also causes support fill to be aligned on start boundaries
|
||||||
// best with angles that are a multiple of 90 degrees
|
// best with angles that are a multiple of 90 degrees
|
||||||
if (process.sliceSupportFill !== undefined) {
|
if (process.sliceSupportFill >= 0) {
|
||||||
|
// yes, an ugly hack to allow it to pass through old code paths
|
||||||
process.sliceSupportFill += 1000;
|
process.sliceSupportFill += 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -414,8 +415,15 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
let clipto = pslice.clips;
|
||||||
|
if (pslice.supportOutline) {
|
||||||
|
// merge support outlines into slice clips which
|
||||||
|
// should only happen when automatic and manual
|
||||||
|
// supports are used together
|
||||||
|
clipto.appendAll(pslice.supportOutline);
|
||||||
|
}
|
||||||
let ntops = [];
|
let ntops = [];
|
||||||
POLY.subtract(tops, pslice.clips, ntops, null, slice.z, 0);
|
POLY.subtract(tops, clipto, ntops, null, slice.z, 0);
|
||||||
tops = ntops;
|
tops = ntops;
|
||||||
}
|
}
|
||||||
// trim to group's shadow if not in belt mode
|
// trim to group's shadow if not in belt mode
|
||||||
|
|
@ -724,23 +732,18 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
let density = params.sliceSupportDensity;
|
let density = params.sliceSupportDensity;
|
||||||
if (density)
|
if (density)
|
||||||
for (let top of slice.tops) {
|
for (let top of slice.tops) {
|
||||||
if (!outline) {
|
|
||||||
let offset = top.shells;
|
|
||||||
fillSupportPolys({
|
|
||||||
promises, polys: offset, lineWidth, density, z: slice.z, isBelt,
|
|
||||||
angle: process.sliceSupportFill
|
|
||||||
});
|
|
||||||
resolve.push({top, offset});
|
|
||||||
} else {
|
|
||||||
let offset = [];
|
let offset = [];
|
||||||
|
if (!outline) {
|
||||||
|
POLY.expand(top.shells || [], lineWidth, slice.z, offset);
|
||||||
|
} else {
|
||||||
POLY.expand(top.shells || [], -lineWidth/4, slice.z, offset);
|
POLY.expand(top.shells || [], -lineWidth/4, slice.z, offset);
|
||||||
|
}
|
||||||
fillSupportPolys({
|
fillSupportPolys({
|
||||||
promises, polys: offset, lineWidth, density, z: slice.z, isBelt,
|
promises, polys: offset, lineWidth, density, z: slice.z, isBelt,
|
||||||
angle: process.sliceSupportFill
|
angle: process.sliceSupportFill
|
||||||
});
|
});
|
||||||
resolve.push({top, offset});
|
resolve.push({top, offset});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}, "infill");
|
}, "infill");
|
||||||
if (promises) {
|
if (promises) {
|
||||||
await tracker(promises, (i, t) => {
|
await tracker(promises, (i, t) => {
|
||||||
|
|
@ -748,35 +751,11 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (let rec of resolve) {
|
for (let rec of resolve) {
|
||||||
|
let spacing = lineWidth * (1 / supportDensity);
|
||||||
let lines = rec.top.fill_lines = rec.offset.map(o => o.fill).flat().filter(v => v);
|
let lines = rec.top.fill_lines = rec.offset.map(o => o.fill).flat().filter(v => v);
|
||||||
// if copying simply's support type, eliminate shells
|
// if copying simply's support type, eliminate shells and zig/zag fill lines
|
||||||
// and zig/zag lines connectd by shell segments
|
|
||||||
if (!outline) {
|
if (!outline) {
|
||||||
let newlines = [];
|
let newlines = connect_lines(lines, spacing * 2);
|
||||||
let op2;
|
|
||||||
let eo = 0;
|
|
||||||
let idx = 1;
|
|
||||||
for (let i=0; i<lines.length; i += 2) {
|
|
||||||
let p1 = lines[i];
|
|
||||||
let p2 = lines[i+1];
|
|
||||||
p1.index = idx;
|
|
||||||
p2.index = idx++;
|
|
||||||
if (eo++ % 2 === 1) {
|
|
||||||
let t = p1;
|
|
||||||
p1 = p2;
|
|
||||||
p2 = t;
|
|
||||||
}
|
|
||||||
if (op2) {
|
|
||||||
let op1 = p1.clone();
|
|
||||||
op1.index = op2.index;
|
|
||||||
newlines.push(op2);
|
|
||||||
newlines.push(op1);
|
|
||||||
}
|
|
||||||
newlines.push(p1);
|
|
||||||
newlines.push(p2);
|
|
||||||
op2 = p2.clone();
|
|
||||||
op2.index = idx++;
|
|
||||||
}
|
|
||||||
rec.top.fill_lines = newlines;
|
rec.top.fill_lines = newlines;
|
||||||
rec.top.shells = [];
|
rec.top.shells = [];
|
||||||
}
|
}
|
||||||
|
|
@ -801,7 +780,8 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
doSupportFill({
|
doSupportFill({
|
||||||
promises, slice, lineWidth, density: supportDensity,
|
promises, slice, lineWidth, density: supportDensity,
|
||||||
minArea: process.sliceSupportArea, isBelt,
|
minArea: process.sliceSupportArea, isBelt,
|
||||||
angle: process.sliceSupportFill
|
angle: process.sliceSupportFill,
|
||||||
|
outline: process.sliceSupportOutline !== false
|
||||||
});
|
});
|
||||||
}, "support");
|
}, "support");
|
||||||
if (promises) {
|
if (promises) {
|
||||||
|
|
@ -832,6 +812,35 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function connect_lines(lines, maxd = Infinity) {
|
||||||
|
const newlines = [];
|
||||||
|
let op2;
|
||||||
|
let eo = 0;
|
||||||
|
let idx = 1;
|
||||||
|
for (let i=0; i<lines.length; i += 2) {
|
||||||
|
let p1 = lines[i];
|
||||||
|
let p2 = lines[i+1];
|
||||||
|
p1.index = idx;
|
||||||
|
p2.index = idx++;
|
||||||
|
if (eo++ % 2 === 1) {
|
||||||
|
let t = p1;
|
||||||
|
p1 = p2;
|
||||||
|
p2 = t;
|
||||||
|
}
|
||||||
|
if (op2 && p1.distTo2D(op2) <= maxd) {
|
||||||
|
let op1 = p1.clone();
|
||||||
|
op1.index = op2.index;
|
||||||
|
newlines.push(op2);
|
||||||
|
newlines.push(op1);
|
||||||
|
}
|
||||||
|
newlines.push(p1);
|
||||||
|
newlines.push(p2);
|
||||||
|
op2 = p2.clone();
|
||||||
|
op2.index = idx++;
|
||||||
|
}
|
||||||
|
return newlines;
|
||||||
|
}
|
||||||
|
|
||||||
function bound(v,min,max) {
|
function bound(v,min,max) {
|
||||||
return Math.max(min,Math.min(max,v));
|
return Math.max(min,Math.min(max,v));
|
||||||
}
|
}
|
||||||
|
|
@ -847,7 +856,7 @@ function doRender(slice, isSynth, params, devel) {
|
||||||
.addPolys(top.poly);
|
.addPolys(top.poly);
|
||||||
|
|
||||||
output
|
output
|
||||||
.setLayer("shells", isSynth ? COLOR.support : COLOR.shell)
|
.setLayer(isSynth ? "support" : "shells", isSynth ? COLOR.support : COLOR.shell)
|
||||||
.addPolys(top.shells || [], vopt({ offset, height, clean: true }));
|
.addPolys(top.shells || [], vopt({ offset, height, clean: true }));
|
||||||
|
|
||||||
output
|
output
|
||||||
|
|
@ -893,7 +902,7 @@ function doRender(slice, isSynth, params, devel) {
|
||||||
.addAreas(slice.flats);
|
.addAreas(slice.flats);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slice.supports) output
|
if (slice.supports && params.sliceSupportOutline) output
|
||||||
.setLayer("support", COLOR.support)
|
.setLayer("support", COLOR.support)
|
||||||
.addPolys(slice.supports, vopt({ offset, height }));
|
.addPolys(slice.supports, vopt({ offset, height }));
|
||||||
|
|
||||||
|
|
@ -902,6 +911,7 @@ function doRender(slice, isSynth, params, devel) {
|
||||||
.setLayer("support", COLOR.support)
|
.setLayer("support", COLOR.support)
|
||||||
.addLines(poly.fill, vopt({ offset, height }));
|
.addLines(poly.fill, vopt({ offset, height }));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (slice.xray) {
|
if (slice.xray) {
|
||||||
const color = [ 0xff0000, 0x00aa00, 0x0000ff, 0xaaaa00, 0xff00ff, 0x0 ];
|
const color = [ 0xff0000, 0x00aa00, 0x0000ff, 0xaaaa00, 0xff00ff, 0x0 ];
|
||||||
if (slice.lines) {
|
if (slice.lines) {
|
||||||
|
|
@ -1517,7 +1527,7 @@ async function doSupport(slice, proc, shadow, opt = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSupportFill(args) {
|
function doSupportFill(args) {
|
||||||
const { promises, slice, lineWidth, density, minArea, isBelt, angle } = args;
|
const { promises, slice, lineWidth, density, minArea, isBelt, angle, outline } = args;
|
||||||
let supports = slice.supports,
|
let supports = slice.supports,
|
||||||
nsB = [],
|
nsB = [],
|
||||||
nsC = [],
|
nsC = [],
|
||||||
|
|
@ -1540,16 +1550,17 @@ function doSupportFill(args) {
|
||||||
|
|
||||||
if (supports) {
|
if (supports) {
|
||||||
fillSupportPolys({
|
fillSupportPolys({
|
||||||
promises, polys: supports, lineWidth, density, z: slice.z, isBelt, angle
|
promises, polys: supports, lineWidth, density, z: slice.z, isBelt, angle, outline
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-assign new supports back to slice
|
// re-assign new supports back to slice
|
||||||
|
slice.supportOutline = supports;
|
||||||
slice.supports = supports;
|
slice.supports = supports;
|
||||||
};
|
};
|
||||||
|
|
||||||
function fillSupportPolys(args) {
|
function fillSupportPolys(args) {
|
||||||
const { promises, polys, lineWidth, density, z, isBelt, angle } = args;
|
const { promises, polys, lineWidth, density, z, isBelt, angle, outline } = args;
|
||||||
// calculate fill density
|
// calculate fill density
|
||||||
let spacing = lineWidth * (1 / density);
|
let spacing = lineWidth * (1 / density);
|
||||||
polys.forEach(function (poly) {
|
polys.forEach(function (poly) {
|
||||||
|
|
@ -1560,6 +1571,9 @@ function fillSupportPolys(args) {
|
||||||
// do the fill
|
// do the fill
|
||||||
if (inset && inset.length > 0) {
|
if (inset && inset.length > 0) {
|
||||||
doFillArea(promises, inset, angle || auto, spacing, poly.fill = []);
|
doFillArea(promises, inset, angle || auto, spacing, poly.fill = []);
|
||||||
|
if (!outline && poly.fill.length) {
|
||||||
|
poly.fill = connect_lines(poly.fill, spacing * 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1862,10 +1862,10 @@ gapp.register("kiri.init", [], (root, exports) => {
|
||||||
sliceSupportArea: uc.newInput(LANG.sp_area_s, {title:LANG.sp_area_l, bound:uc.bound(0.0,200.0), convert:uc.toFloat, modes:FDM}),
|
sliceSupportArea: uc.newInput(LANG.sp_area_s, {title:LANG.sp_area_l, bound:uc.bound(0.0,200.0), convert:uc.toFloat, modes:FDM}),
|
||||||
sliceSupportExtra: uc.newInput(LANG.sp_xpnd_s, {title:LANG.sp_xpnd_l, bound:uc.bound(0.0,200.0), convert:uc.toFloat, modes:FDM}),
|
sliceSupportExtra: uc.newInput(LANG.sp_xpnd_s, {title:LANG.sp_xpnd_l, bound:uc.bound(0.0,200.0), convert:uc.toFloat, modes:FDM}),
|
||||||
fdmSep: uc.newBlank({class:"pop-sep", modes:FDM}),
|
fdmSep: uc.newBlank({class:"pop-sep", modes:FDM}),
|
||||||
sliceSupportAngle: uc.newInput(LANG.sp_angl_s, {title:LANG.sp_angl_l, bound:uc.bound(0.0,90.0), convert:uc.toFloat, modes:FDM, show:() => !ui.sliceSupportEnable.checked}),
|
sliceSupportAngle: uc.newInput(LANG.sp_angl_s, {title:LANG.sp_angl_l, bound:uc.bound(0.0,90.0), convert:uc.toFloat, modes:FDM}),
|
||||||
sliceSupportSpan: uc.newInput(LANG.sp_span_s, {title:LANG.sp_span_l, bound:uc.bound(0.0,200.0), convert:uc.toFloat, modes:FDM, show:() => ui.sliceSupportEnable.checked}),
|
sliceSupportSpan: uc.newInput(LANG.sp_span_s, {title:LANG.sp_span_l, bound:uc.bound(0.0,200.0), convert:uc.toFloat, modes:FDM, show:() => ui.sliceSupportEnable.checked}),
|
||||||
sliceSupportEnable: uc.newBoolean(LANG.sp_auto_s, onBooleanClick, {title:LANG.sp_auto_l, modes:FDM, show:isNotBelt}),
|
sliceSupportEnable: uc.newBoolean(LANG.sp_auto_s, onBooleanClick, {title:LANG.sp_auto_l, modes:FDM, show:isNotBelt}),
|
||||||
sliceSupportOutline: uc.newBoolean(LANG.sp_outl_s, onBooleanClick, {title:LANG.sp_outl_l, modes:FDM, show:() => !ui.sliceSupportEnable.checked}),
|
sliceSupportOutline: uc.newBoolean(LANG.sp_outl_s, onBooleanClick, {title:LANG.sp_outl_l, modes:FDM}),
|
||||||
|
|
||||||
sliceSupportGen: uc.newRow([
|
sliceSupportGen: uc.newRow([
|
||||||
ui.ssaGen = uc.newButton(LANG.sp_detect, onButtonClick, {class: "f-col grow a-center"})
|
ui.ssaGen = uc.newButton(LANG.sp_detect, onButtonClick, {class: "f-col grow a-center"})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue