From 80e8f1c8e65d3c607865e97b53fac4a364e2ff78 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Thu, 24 Jun 2021 22:23:42 -0400 Subject: [PATCH] add profiling. use simple tops for support clipping --- src/geo/polygons.js | 36 +++++++++++++++++++++----------- src/kiri/slice.js | 6 +++++- src/mode/fdm/slice.js | 48 +++++++++++++++++++++++-------------------- 3 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/geo/polygons.js b/src/geo/polygons.js index 7888ced7..60bcd201 100644 --- a/src/geo/polygons.js +++ b/src/geo/polygons.js @@ -292,7 +292,7 @@ * @param {number} [minArea] * @returns {Polygon[]} out */ - function subtract(setA, setB, outA, outB, z, minArea) { + function subtract(setA, setB, outA, outB, z, minArea, opt = {}) { let min = minArea || 0.1, out = []; @@ -306,7 +306,25 @@ return to; } - if (true) { + if (opt.prof) { + if (setA.length === 0 || setB.length === 0) { + console.log('sub_zero', {setA, setB}); + } + opt.prof.pin = (opt.prof.pin || 0) + points(setA) + points(setB); + opt.prof.call = (opt.prof.call || 0) + 1; + } + + if (opt.wasm) { + let oA = outA ? [] : undefined; + let oB = outB ? [] : undefined; + geo.wasm.js.diff(setA, setB, z, oA, oB); + if (oA) { + outA.appendAll(filter(oA)); + } + if (oB) { + outB.appendAll(filter(oB)); + } + } else { let clib = self.ClipperLib, ctyp = clib.ClipType, ptyp = clib.PolyType, @@ -338,16 +356,10 @@ filter(fromClipperTree(ctre, z, null, null, min), outB); } } - } else { - let oA = outA ? [] : undefined; - let oB = outB ? [] : undefined; - geo.wasm.js.diff(setA, setB, z, oA, oB); - if (oA) { - outA.appendAll(filter(oA)); - } - if (oB) { - outB.appendAll(filter(oB)); - } + } + + if (opt.prof) { + opt.prof.pout = (opt.prof.pout || 0) + points(out); } return out; diff --git a/src/kiri/slice.js b/src/kiri/slice.js index ed873ce3..bf3749b3 100644 --- a/src/kiri/slice.js +++ b/src/kiri/slice.js @@ -106,6 +106,10 @@ return this.tops.map(top => top.poly); }; + PRO.topSimples = function() { + return this.tops.map(top => top.simple); + }; + // FDM top intersect optimization PRO.topPolysFlat = function() { if (this.topFlatPolys) { @@ -188,7 +192,7 @@ top.fill_off = poly.fill_off; top.last = poly.last; top.shells = poly.shells; - top.shadow = poly.shadow; + top.simple = poly.simple; this.tops.push(top); return top; } diff --git a/src/mode/fdm/slice.js b/src/mode/fdm/slice.js index 3ca7d3a1..122a7703 100644 --- a/src/mode/fdm/slice.js +++ b/src/mode/fdm/slice.js @@ -28,6 +28,10 @@ PROTO = Object.clone(COLOR), bwcomp = (1 / Math.cos(Math.PI/4)), getRangeParameters = FDM.getRangeParameters, + noop = function() {}, + profile = false, + profileStart = profile ? console.profile : noop, + profileEnd = profile ? console.profileEnd : noop, debug = false; let isThin = false, // force line rendering @@ -88,9 +92,9 @@ danger: isDanger })); } - // add shadow (low rez poly) if needed + // add simple (low rez poly) where less accuracy is OK for (let top of nutops) { - top.shadow = top.poly.clean(true, undefined, CONF.clipper / 10); + top.simple = top.poly.clean(true, undefined, CONF.clipper / 10); } data.tops = nutops; }; @@ -203,7 +207,7 @@ // create shadow for clipping supports let alltops = widget.group .map(w => w.slices).flat() - .map(s => s.tops).flat().map(t => t.shadow); + .map(s => s.tops).flat().map(t => t.simple); let shadow = isConcurrent ? await KIRI.minions.union(alltops, 0.1) : POLY.union(alltops, 0.1, true); @@ -281,16 +285,6 @@ } // trim to group's shadow if not in belt mode if (!isBelt) { - // let group = widget.group[0]; - // if (!group.shadow) { - // let gs = []; - // for (let w of group) { - // if (w.shadow) { - // gs = POLY.union([w.shadow,...gs],null,0.1); - // } - // } - // group.shadow = gs; - // } tops = POLY.setZ(POLY.trimTo(tops, widget.shadow), slice.z); } } @@ -452,14 +446,18 @@ // calculations only relevant when solid layers are used if (solidLayers && !vaseMode && !isSynth) { + profileStart("delta"); forSlices(0.2, 0.34, slice => { if (slice.index > 0) doDiff(slice, solidMinArea); }, "layer deltas"); + profileEnd(); + profileStart("delta-project"); forSlices(0.34, 0.35, slice => { projectFlats(slice, solidLayers); projectBridges(slice, solidLayers); }, "layer deltas"); - // console.log('start'); await BASE.util.ptimer(1000); + profileEnd(); + profileStart("solid-fill") let promises = isConcurrent ? [] : undefined; forSlices(0.35, promises ? 0.4 : 0.5, slice => { let params = slice.params || process; @@ -475,7 +473,7 @@ trackupdate(i / t, 0.4, 0.5); }); } - // console.log('stop'); await BASE.util.ptimer(1000); + profileEnd(); } if (!isSynth && !vaseMode) { @@ -532,15 +530,16 @@ // auto support generation if (!isBelt && !isSynth && supportDensity && process.sliceSupportEnable) { doShadow(slices); - // console.log('start'); await BASE.util.ptimer(1000); + profileStart("support"); let promises = []; forSlices(0.7, 0.75, slice => { - promises.push(doSupport(slice, process, widget.shadow, controller.danger)); + promises.push(doSupport(slice, process, widget.shadow, { exp: isDanger })); }, "support"); await tracker(promises, (i, t) => { trackupdate(i / t, 0.75, 0.8); }); - // console.log('stop'); await BASE.util.ptimer(1000); + profileEnd(); + profileStart("support-fill"); promises = false && isConcurrent ? [] : undefined; forSlices(0.8, promises ? 0.88 : 0.9, slice => { doSupportFill(promises, slice, lineWidth, supportDensity, process.sliceSupportArea); @@ -550,6 +549,7 @@ trackupdate(i / t, 0.88, 0.9); }); } + profileEnd(); } // render if not explicitly disabled @@ -796,6 +796,7 @@ // for diffing top.last = last; + // top.last_simple = last.map(p => p.clean(true, undefined, CONF.clipper / 10)); return top; } @@ -1155,7 +1156,7 @@ /** * calculate external overhangs requiring support */ - async function doSupport(slice, proc, shadow, experimental) { + async function doSupport(slice, proc, shadow, opt = {}) { let maxBridge = proc.sliceSupportSpan || 5, minArea = proc.supportMinArea, pillarSize = proc.sliceSupportSize, @@ -1179,11 +1180,11 @@ down_tops = down ? down.topPolys() : null, down_traces = down ? POLY.flatten(down.topShells().clone(true)) : null; - if (experimental && down_tops) { + if (opt.exp && down_tops) { let points = down_tops.map(p => p.deepLength).reduce((a,v)=>a+v); if (points > 200) { // use de-rez'd top shadow instead - down_tops = down.tops.map(t => t.shadow); + down_tops = down.topSimples(); // de-rez trace polys because it's not that important for supports down_traces = down_traces.map(p => p.clean(true, undefined, CONF.clipper / 10)); } @@ -1271,7 +1272,10 @@ let trimmed = [], culled = []; // clip supports to shell offsets - POLY.subtract(supports, down.topPolys(), trimmed, null, slice.z, min); + POLY.subtract(supports, down.topSimples(), trimmed, null, slice.z, min, { + prof: opt.prof, + wasm: false + }); // set depth hint on support polys for infill density trimmed.forEach(function(trim) {