diff --git a/js/kiri-conf.js b/js/kiri-conf.js index cce57853..503d4cc9 100644 --- a/js/kiri-conf.js +++ b/js/kiri-conf.js @@ -320,6 +320,7 @@ let gs_kiri_conf = exports; slaFillLine: 0.5, slaFirstOffset: 0, slaSupportLayers: 0, + slaSupportDensity: 0, } }, cam:{ diff --git a/js/kiri-driver-fdm.js b/js/kiri-driver-fdm.js index 76bb707e..79e000fc 100644 --- a/js/kiri-driver-fdm.js +++ b/js/kiri-driver-fdm.js @@ -185,6 +185,9 @@ let gs_kiri_fdm = exports; if (!vaseMode && spro.sliceFillSparse > 0.0) { forSlices(0.8, 1.0, function(slice) { slice.doSparseLayerFill({ + settings: settings, + process: spro, + device: sdev, lineWidth: nozzleSize, spacing: fillOffset, density: spro.sliceFillSparse, diff --git a/js/kiri-driver-sla.js b/js/kiri-driver-sla.js index b067bbab..7e750c5d 100644 --- a/js/kiri-driver-sla.js +++ b/js/kiri-driver-sla.js @@ -75,43 +75,58 @@ let gs_kiri_sla = exports; height: height, add: !process.slaOpenTop }, function(slices) { - widget.slices = slices.filter(slice => slice.tops.length); - if (process.slaOpenTop) { - // with closed top, filter out any empty above slices - // that will generate a diff producing a solid projection - slices = widget.slices; + // hold onto last (empty) slice + let last = slices[slices.length-1]; + // remove empty slices + slices = widget.slices = slices.filter(slice => slice.tops.length); + if (!process.slaOpenTop) { + // re-add last empty slice for open top + slices.push(last); } - // insert support layers + // prepend raft layers to slices array if (process.slaSupportLayers) { let zoff = height / 2, snew = [], - polys = []; + polys = [], + off = 2, // starting union offset from part + gap = 10, // gap layers above raft + grow = 0.1; // union per layer expand let outer = slices.forEach(slice => { polys.appendAll(slice.tops.map(t => t.poly)); }); - let union = POLY.expand(POLY.union(polys), 2, zoff, [], 1); - for (let s=0; s { + slice.synth = true; + expand.forEach(u => { slice.tops.push(newTop(u.clone(true).setZ(zoff))); }); - union = POLY.expand(union, 0.1, zoff, [], 1); + expand = POLY.expand(expand, grow, zoff, [], 1); + lastraft = slice; } snew.push(slice); zoff += height; } - widget.slices = slices = snew.concat(slices.map(s => { - s.tops.forEach(t => { - t.poly.setZ(s.z + zoff); - }); + // replace slices with new appended array + slices = widget.slices = snew.concat(slices.map(s => { + s.tops.forEach(t => t.poly.setZ(s.z + zoff)); s.index += snew.length; s.z += zoff; return s; })); + // annotate widget for support generation + widget.union = union; + widget.lastraft = lastraft; + } + // re-connect slices into linked list for island/bridge projections + for (let i=1; i { return t + p.areaDeep() }, 0), + slices = widget.slices, + length = slices.length, + trigger = (1 - process.slaSupportDensity), + layer = 0, + accu = 0, + totmass = 0, // total widget "mass" + totbear = 0; // total "mass-bearing" area + + // compute total "mass" by slice + slices.forEach(slice => { + if (slice.synth || !slice.solids.unioned) return; + slice.mass = slice.solids.unioned.reduce((t,p) => { return t + p.areaDeep() }, 0); + if (slice.up && slice.up.bridges) { + slice.bear = slice.up.bridges.reduce((t,p) => { return t + p.areaDeep() }, 0); + totbear += slice.bear; + } else { + slice.bear = 0; + } + totmass += slice.mass; + // console.log('mass', slice.index, slice.mass.toFixed(3), slice.bear.toFixed(3)); + }); + + slices.forEach(slice => { + let weight = Math.pow(10, 0 + ((length - layer) / length)); + if (slice.up && slice.up.bridges) { + let sum = 0; + slice.up.bridges.forEach(bridge => { + sum += bridge.areaDeep() / area; + }); + accu += sum * weight; + if (layer === 0 || accu > trigger) { + // console.log('gen @', layer, slice.index); + accu = 0; + slice.supports = slice.up.bridges.map(p => { + return p.clone(true).setZ(slice.z); + }); + } + } + if (slice.mass > 0) layer++; + }); + } + function fillPolys(slice, settings) { let process = settings.process, device = settings.device, @@ -374,14 +436,14 @@ let gs_kiri_sla = exports; } else if (slice.tops) { slice.tops.forEach(top => { outline.poly(top.poly, 0x010101, true, false); - outline.solid(top.poly, 0xeeee55); + outline.solid(top.poly, 0xfcba03); }); } if (slice.supports) slice.supports.forEach(poly => { - layer.poly(poly, 0x010105, true, false); - layer.solid(poly, 0xffff99); + support.poly(poly, 0x010105, true, false); + support.solid(poly, 0xfcba03); }); slice.renderDiff(); diff --git a/js/kiri-init.js b/js/kiri-init.js index b6abfdb7..36981587 100644 --- a/js/kiri-init.js +++ b/js/kiri-init.js @@ -1478,6 +1478,7 @@ var gs_kiri_init = exports; slaSupport: LOCAL ? UC.newGroup('support', null, {modes:SLA, group:"sla-support"}) : null, slaSupportLayers: LOCAL ? UC.newInput('layers', {title:'base support layers\n0-10', convert:UC.toInt, bound:UC.bound(0,10), modes:SLA}) : null, + slaSupportDensity: LOCAL ? UC.newInput('density', {title:'used to compute the\nnumber of support pillars\n0.0-1.0 (0 = disable)', convert:UC.toFloat, bound:UC.bound(0,1), modes:SLA}) : null, slaOutput: UC.newGroup('output', null, {modes:SLA, group:"sla-first"}), slaFirstOffset: UC.newInput('z offset', {title:'z layer offset\nalmost always 0.0\n0.0-1.0 in millimeters', convert:UC.toFloat, bound:UC.bound(0,1), modes:SLA, expert:true}), diff --git a/notes.md b/notes.md index 149d4886..d99ee748 100644 --- a/notes.md +++ b/notes.md @@ -65,6 +65,7 @@ # References +* https://www.canva.com/colors/color-wheel/ * http://lcamtuf.coredump.cx/gcnc/full/ * http://wiki.imal.org/howto/cnc-milling-introduction-cutting-tools * http://www.twak.co.uk/2011/01/degeneracy-in-weighted-straight.html