From 8fffc240c4d5ee0c50390a636ab8f3c90d5a376c Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Wed, 12 Oct 2022 22:25:57 -0400 Subject: [PATCH] add sliceSupportFill process parameter to optionally force aligned support infill at a fixed angle --- src/geo/polygons.js | 24 +++++++++++++++++++++ src/kiri-mode/fdm/slice.js | 44 ++++++++++++++++++++++++++++---------- src/kiri/conf.js | 1 + 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/geo/polygons.js b/src/geo/polygons.js index 062dd0c8..3466ca30 100644 --- a/src/geo/polygons.js +++ b/src/geo/polygons.js @@ -668,8 +668,15 @@ function fillArea(polys, angle, spacing, output, minLen, maxLen) { p0 = polys[0], zpos = p0.getZ(), bounds = p0.bounds.clone(), + align = false, raySlope; + // testing force to 90 + if (angle >= 1000) { + align = true; + angle -= 1000; + } + // ensure angle is in the -90:90 range angle = angle % 180; while (angle < -90) angle += 180; @@ -686,6 +693,23 @@ function fillArea(polys, angle, spacing, output, minLen, maxLen) { bounds.merge(polys[i++].bounds); } + // align start/end to multiples of spacing + // only works with 0 and 90 degree angles :/ + if (align) { + let mxo = bounds.minx / spacing; + let myo = bounds.miny / spacing; + mxo = mxo - (mxo | 0) + (mxo < 0 ? 1 : 0); + myo = myo - (myo | 0) + (myo < 0 ? 1 : 0); + bounds.minx -= mxo * spacing; + bounds.miny -= myo * spacing; + let Mxo = bounds.maxx / spacing; + let Myo = bounds.maxy / spacing; + Mxo = Mxo - (Mxo | 0) + (Mxo < 0 ? 1 : 0); + Myo = Myo - (Myo | 0) + (Myo < 0 ? 1 : 0); + bounds.maxx = bounds.maxx - Mxo * spacing + spacing; + bounds.maxy = bounds.maxy - Myo * spacing + spacing; + } + // ray stepping is an axis from the line perpendicular to the ray let rayint = output || [], stepX = -raySlope.dy, diff --git a/src/kiri-mode/fdm/slice.js b/src/kiri-mode/fdm/slice.js index a3571d21..b13c9fd7 100644 --- a/src/kiri-mode/fdm/slice.js +++ b/src/kiri-mode/fdm/slice.js @@ -124,6 +124,13 @@ FDM.slice = function(settings, widget, onupdate, ondone) { isThin = !isFlat && controller.lineType === "line"; offset = lineWidth / 2; + // allow overriding support fill auto angle algorithm + // also causes support fill to be aligned on start boundaries + // best with angles that are a multiple of 90 degrees + if (process.sliceSupportFill !== undefined) { + process.sliceSupportFill += 1000; + } + if (isFlat) { Object.values(COLOR).forEach(color => { color.flat = true; @@ -324,6 +331,7 @@ FDM.slice = function(settings, widget, onupdate, ondone) { return onSliceDone(slices); }).then(ondone); + // shadow used to clip supports in non-belt mode async function doShadow(slices) { if (widget.shadow) { return; @@ -718,12 +726,18 @@ FDM.slice = function(settings, widget, onupdate, ondone) { for (let top of slice.tops) { if (!outline) { let offset = top.shells; - fillSupportPolys(promises, offset, lineWidth, density, slice.z, isBelt); + fillSupportPolys({ + promises, polys: offset, lineWidth, density, z: slice.z, isBelt, + angle: process.sliceSupportFill + }); resolve.push({top, offset}); } else { let offset = []; POLY.expand(top.shells || [], -lineWidth/4, slice.z, offset); - fillSupportPolys(promises, offset, lineWidth, density, slice.z, isBelt); + fillSupportPolys({ + promises, polys: offset, lineWidth, density, z: slice.z, isBelt, + angle: process.sliceSupportFill + }); resolve.push({top, offset}); } } @@ -784,7 +798,11 @@ FDM.slice = function(settings, widget, onupdate, ondone) { profileStart("support-fill"); promises = false && isConcurrent ? [] : undefined; forSlices(0.8, promises ? 0.88 : 0.9, slice => { - doSupportFill(promises, slice, lineWidth, supportDensity, process.sliceSupportArea, isBelt); + doSupportFill({ + promises, slice, lineWidth, density: supportDensity, + minArea: process.sliceSupportArea, isBelt, + angle: process.sliceSupportFill + }); }, "support"); if (promises) { await tracker(promises, (i, t) => { @@ -1498,7 +1516,8 @@ async function doSupport(slice, proc, shadow, opt = {}) { } -function doSupportFill(promises, slice, linewidth, density, minArea, isBelt) { +function doSupportFill(args) { + const { promises, slice, lineWidth, density, minArea, isBelt, angle } = args; let supports = slice.supports, nsB = [], nsC = [], @@ -1520,24 +1539,27 @@ function doSupportFill(promises, slice, linewidth, density, minArea, isBelt) { } if (supports) { - fillSupportPolys(promises, supports, linewidth, density, slice.z, isBelt); + fillSupportPolys({ + promises, polys: supports, lineWidth, density, z: slice.z, isBelt, angle + }); } // re-assign new supports back to slice slice.supports = supports; }; -function fillSupportPolys(promises, polys, linewidth, density, z, isBelt) { +function fillSupportPolys(args) { + const { promises, polys, lineWidth, density, z, isBelt, angle } = args; // calculate fill density - let spacing = linewidth * (1 / density); + let spacing = lineWidth * (1 / density); polys.forEach(function (poly) { - // angle based on width/height ratio - let angle = isBelt || (poly.bounds.width() / poly.bounds.height() > 1) ? 90 : 0; + // calculate angle based on width/height ratio + let auto = isBelt || (poly.bounds.width() / poly.bounds.height() > 1) ? 90 : 0; // inset support poly for fill lines 33% of nozzle width - let inset = POLY.offset([poly], -linewidth/3, {flat: true, z, wasm: true}); + let inset = POLY.offset([poly], -lineWidth/3, {flat: true, z, wasm: true}); // do the fill if (inset && inset.length > 0) { - doFillArea(promises, inset, angle, spacing, poly.fill = []); + doFillArea(promises, inset, angle || auto, spacing, poly.fill = []); } return true; }); diff --git a/src/kiri/conf.js b/src/kiri/conf.js index d568b9df..465838e9 100644 --- a/src/kiri/conf.js +++ b/src/kiri/conf.js @@ -323,6 +323,7 @@ const conf = exports({ sliceSupportNozzle: 0, sliceSupportEnable: false, sliceSupportOutline: true, + sliceSupportFill: undefined, sliceSolidMinArea: 1, sliceSolidLayers: 3, sliceBottomLayers: 3,