From 53d75fd4ed72d458f717f3db2b61910008a3ce3c Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 3 Nov 2020 21:43:06 -0500 Subject: [PATCH] checkpoint roughing refactor --- src/geo/polygon.js | 7 +- src/geo/polygons.js | 56 ++++++++------- src/kiri/slicer2.js | 11 ++- src/mode/cam/driver.js | 154 ++++++++++++++++++++--------------------- 4 files changed, 120 insertions(+), 108 deletions(-) diff --git a/src/geo/polygon.js b/src/geo/polygon.js index 99c57e53..8ff28826 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -1286,7 +1286,7 @@ * @param {Polygon} poly * @returns {?Polygon} intersected polygon or null if no intersection */ - PRO.union = function(poly, min) { + PRO.union = function(poly, min, all) { if (!this.overlaps(poly)) return null; let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang, @@ -1305,10 +1305,15 @@ if (clip.Execute(ctyp.ctUnion, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { let union = POLY().fromClipperTreeUnion(ctre, poly.getZ(), minarea); + if (all) { + return union; + } if (union.length === 1) { union = union[0]; union.fillang = fillang; return union; + } else { + console.log({check_union_call_path: union}); } } diff --git a/src/geo/polygons.js b/src/geo/polygons.js index 1ab91805..9b91c837 100644 --- a/src/geo/polygons.js +++ b/src/geo/polygons.js @@ -31,6 +31,7 @@ union : union, nest : nest, diff : doDiff, + setZ : setZ, filter : filter, toClipper : toClipper, fromClipperNode : fromClipperNode, @@ -49,6 +50,11 @@ return num !== undefined ? num : def; } + function setZ(polys, z) { + polys.forEach(p => p.setZ(z)); + return polys; + } + function toClipper(polys,debug) { let out = []; polys.forEach(function(poly) { poly.toClipper(out,debug) }); @@ -336,7 +342,7 @@ * @param {Polygon[]} polys * @returns {Polygon[]} */ - function union(polys, minarea) { + function union(polys, minarea, all) { if (polys.length < 2) return polys; let out = polys.slice(), i, j, union, uset = []; @@ -345,11 +351,15 @@ if (!out[i]) continue; for (j=i+1; j 1 ? dist.shift() : dist[0]) : dist, mina = numOrDefault(opts.minArea, 0.1), - zed = opt.z || 0; + zed = opts.z || 0; // setup offset polys.forEach(function(poly) { @@ -494,45 +504,41 @@ polys = fromClipperTree(ctre, zed, null, null, mina); // if specified, perform offset gap analysis - if (opt.gaps && polys.length) { + if (opts.gaps && polys.length) { let oneg = offset(polys, -offs, { - fill: opt.fill, join: opt.join, type: opt.type, z: opt.z, minArea: mina + fill: opts.fill, join: opts.join, type: opts.type, z: opts.z, minArea: mina }); let suba = []; let diff = subtract(orig, oneg, suba, null, zed); - opt.gaps.append(suba, opt.flat); + opts.gaps.append(suba, opts.flat); } // if offset fails, consider last polygons as gap areas - if (opt.gaps && !polys.length) { - opt.gaps.append(orig, opt.flat); + if (opts.gaps && !polys.length) { + opts.gaps.append(orig, opts.flat); } // if specified, perform up to *count* successive offsets if (polys.length) { // ensure opts has offset accumulator array - opt.outs = opt.outs || []; + opts.outs = opts.outs || []; // store polys in accumulator - opt.outs.append(polys, opt.flat); + opts.outs.append(polys, opts.flat); // callback for expand() compatibility - if (opt.call) { - opt.call(polys, count, depth); + if (opts.call) { + opts.call(polys, count, depth); } // check for more offsets if (count > 1) { // decrement count, increment depth - opt.count = count - 1; - opt.depth = depth + 1; + opts.count = count - 1; + opts.depth = depth + 1; // call next offset - offset(polys, dist, opt); - // } else if (count === 0) { - // // depth = 0 means offset until failure - // opt.depth = depth + 1; - // offset(polys, dist, opt); + offset(polys, dist, opts); } } - return opt.flat ? opt.outs : polys; + return opts.flat ? opts.outs : polys; } /** diff --git a/src/kiri/slicer2.js b/src/kiri/slicer2.js index 4a06e889..3b706dfc 100644 --- a/src/kiri/slicer2.js +++ b/src/kiri/slicer2.js @@ -180,12 +180,19 @@ return rarr; } - let phash = {}, + let znorm = z.toFixed(5), + flatoff = opt.flatoff || 0.007, + onflat = this.zFlat[znorm], + phash = {}, lines = [], zScale = this.zScale, buckets = this.buckets, bucket = buckets.length ? buckets[Math.floor(z * zScale)] : points; + if (onflat) { + z += flatoff; + } + if (!bucket) { console.log({no_bucket_for_z: z}); return; @@ -236,7 +243,7 @@ } } - if (opt.each) { + if (opt.each && (lines.length || opt.emptyok)) { opt.each(retn, index, total, UTIL.time() - mark); } diff --git a/src/mode/cam/driver.js b/src/mode/cam/driver.js index e1a8b670..962e62a1 100644 --- a/src/mode/cam/driver.js +++ b/src/mode/cam/driver.js @@ -288,7 +288,6 @@ let out = []; POLY.expand(last, -offset*1.1, 0, out, 1); - return out; } @@ -667,50 +666,31 @@ * @param {Polygon[]} shell enclosing slice tops * @param {number} diameter of tool (mm) * @param {number} stock to leave (mm) - * @param {number} percent overlap on each pass - * @param {boolean} widecut expand outer cutout - * @returns {Object} shell or newly generated shell + * @param {number} overlap on each pass */ - function createRoughPaths(slice, shell, diameter, stock, overlap, holes) { - let tops = slice.gatherTopPolys([]).clone(true), - outer = [], - offset = []; + function createRoughPaths(slice, shell, diameter, stock, overlap) { + let tops = slice.shadow; + let offset = [shell.clone(true),tops.clone(true)].flat(); + let flat = POLY.flatten(offset, [], true); - // when thru holes present, treat them as top offsets - // to prevent roughing out the entire hole - if (holes) { - tops.appendAll(holes); - } - - // clone and flatten the shell with tops to offset array - shell.clone(true).forEach(function(poly) { - poly.setZ(slice.z).flattenTo(offset); - }); - POLY.flatten(tops, offset, true); - - // only tab cut polys should be open (happens later) - offset.forEach(function(trace) { - trace.setClosed(); - }); - - // re-nest offset array - offset = POLY.nest(offset); + offset = POLY.setZ(POLY.nest(flat), slice.z); + // slice.tops[0].inner = offset; // inset offset array by 1/2 diameter then by tool overlap % + slice.tops[0].traces = POLY.offset(offset, [-(diameter / 2 + stock), -diameter * overlap], { z: slice.z, count: 999, flat: true, - outs: outer, call: (polys, count, depth) => { polys.forEach(p => { p.depth = depth; - if (p.inner) p.inner.forEach(p => p.depth = depth); + if (p.inner) { + p.inner.forEach(p => p.depth = depth); + } }); } }); - - slice.tops[0].traces = outer; }; /** @@ -853,7 +833,7 @@ roughToolDiam = getToolDiameter(conf, proc.camRoughTool), outlineToolDiam = getToolDiameter(conf, proc.camOutlineTool), contourToolDiam = getToolDiameter(conf, proc.camContourTool), - procFacing = proc.camRoughOn && proc.camZTopOffset, + procFacing = false && proc.camRoughOn && proc.camZTopOffset, procRough = proc.camRoughOn && proc.camRoughDown && roughToolDiam, procOutlineIn = proc.camOutlineIn, procOutlineOut = proc.camOutlineOut, @@ -1002,7 +982,7 @@ }); // set all default shells - const camShellPolys = shellRough = shellOutline = facePolys = camShell.gatherTopPolys([]); + const camShellPolys = shellOutline = facePolys = camShell.gatherTopPolys([]); if (procDrillReg) { sliceDrillReg(settings, widget, sliceAll, zThru); @@ -1012,11 +992,6 @@ sliceDrill(settings, widget, slices, sliceAll); } - if (procRough) { - // expand shell by half tool diameter + stock to leave - shellRough = facePolys = POLY.expand(shellRough, (roughToolDiam / 2) + camRoughStock, 0); - } - if (procOutline) { if (!procOutlineOut) { // expand shell minimally triggering a clean @@ -1048,18 +1023,6 @@ } } - if (procRough) { - let selected = []; - selectSlices(slices, camRoughDown * units, CPRO.ROUGH, selected); - if (zThru) { - addZThru(selected); - } - sliceAll.appendAll(selected); - if (!proc.camRoughVoid) { - thruHoles = holes(slices, roughToolDiam + camRoughStock); - } - } - if (procOutline) { let selected = []; selectSlices(slices, proc.camOutlineDown * units, CPRO.OUTLINE, selected); @@ -1069,32 +1032,62 @@ sliceAll.appendAll(selected); } } -/* + let slicer = new KIRI.slicer2(widget.getPoints(), { zlist: true, - zline: true, - genso: true // generate slice object + zline: true }); - let zindex = slicer.interval(1, { down: true }); - let terrain = slicer.slice(zindex, { each: (data, index, total) => { + let tshadow = []; + let tzindex = slicer.interval(1); // bottom up + let terrain = slicer.slice(tzindex, { each: (data, index, total) => { console.log('terrain', index, total, data); + tshadow = POLY.union(tshadow.appendAll(data.tops), 0.01, true); } }); - let shadow = []; - // shadow generation bottom-up is faster - terrain.reverse().forEach(data => { - if (data.tops) { - shadow = POLY.union(shadow.appendAll(data.tops)); - } - }); - console.log({slicer, zindex, shadow, terrain}); + console.log({slicer, tzindex, tshadow, terrain}); + + // do creating roughing slices + if (procRough) { + // identify through holes + thruHoles = tshadow.map(p => p.inner || []).flat(); + + let shadow = []; + let slices = []; + slicer.slice(slicer.interval(roughDown, { down: true }), { each: (data, index, total) => { + shadow = POLY.union(shadow.appendAll(data.tops), 0.01, true); + data.shadow = shadow.clone(true); + data.slice.camMode = CPRO.ROUGH; + data.slice.shadow = data.shadow; + slices.push(data.slice); + }, genso: true }); + + // inset or eliminate thru holes from shadow + shadow = POLY.flatten(shadow.clone(true), [], true); + thruHoles.forEach(hole => { + shadow = shadow.map(p => { + if (p.isEquivalent(hole)) { + // eliminate thru holes when roughing voids enabled + if (proc.camRoughVoid) { + return undefined; + } + let po = POLY.offset([p], -(roughToolDiam + camRoughStock)); + return po ? po[0] : undefined; + } else { + return p; + } + }).filter(p => p); + }); + shadow = POLY.nest(shadow); + + // expand shadow by half tool diameter + stock to leave + shellRough = POLY.offset(shadow, (roughToolDiam / 4) + camRoughStock); + + if (zThru) { + addZThru(slices); + } + + sliceAll.appendAll(slices); + } - // do roughing slices - if (procRough) - slicer.slice(slicer.interval(roughDown, { down: true }), { each: (data, index, total) => { - // annotate slice - console.log('rough', data.z, data); - } }); -*/ // horizontal slices for rough/outline doSlicing(widget, {height:sliceDepth, cam:true, zmin:zBottom, noEmpty:true}, camSlicesDone, function(update) { onupdate(0.0 + update * 0.25, "slicing"); @@ -1103,15 +1096,15 @@ // we need topo for safe travel moves when roughing and outlining // not generated when drilling-only. then all z moves use bounds max. // also generates x and y contouring when selected - if (procRough || procOutline || procContour) - generateTopoMap(widget, settings, function(slices) { - sliceAll.appendAll(slices); - // todo union rough / outline shells - // todo union rough / outline tabs - // todo append to generated topo map - }, function(update, msg) { - onupdate(0.40 + update * 0.50, msg || "create topo"); - }); + // if (procRough || procOutline || procContour) + // generateTopoMap(widget, settings, function(slices) { + // sliceAll.appendAll(slices); + // // todo union rough / outline shells + // // todo union rough / outline tabs + // // todo append to generated topo map + // }, function(update, msg) { + // onupdate(0.40 + update * 0.50, msg || "create topo"); + // }); // prepare for tracing paths let traceTool; @@ -1253,7 +1246,8 @@ tops.forEach(function(top) { outline.poly(top.poly, 0x999900, true, open); - if (top.inner) outline.poly(top.inner, 0xdddddd, true); + // if (top.inner) outline.poly(top.inner, 0xdddddd, true); + if (top.inner) outline.poly(top.inner, 0xff0000, true); }); // various outlining