diff --git a/notes.md b/notes.md index 817de5de..138b3d1f 100644 --- a/notes.md +++ b/notes.md @@ -4,6 +4,7 @@ * `cnc` * - tracing (chamfer, engrave) * - auto feature detection (slicing) +* - show tool x,y,z during animation * `laser` * - drag knife support * `all` diff --git a/src/geo/base.js b/src/geo/base.js index b0a93774..539a577e 100644 --- a/src/geo/base.js +++ b/src/geo/base.js @@ -15,6 +15,10 @@ function time() { return Date.now() } + function numOrDefault(num, def) { + return num !== undefined ? num : def; + } + /** * call function with all combinations of a1, a2 * and passing in the supplied arg object. @@ -372,23 +376,24 @@ }; BASE.util = { - sqr : sqr, - time : time, - round : round, - area2: area2, + sqr, + time, + round, + area2, distSq : dist2, distSqv2 : dist2v2, - inRange : inRange, - isCloseTo : isCloseTo, - inCloseRange : inCloseRange, - isCollinear : isCollinear, - isClockwise : isClockwise, - isCounterClockwise : isCounterClockwise, - doCombinations : doCombinations, - offsetPrecision : offsetPrecision, - intersectRayLine : intersectRayLine, - intersect : intersect, - determinant : determinant, + inRange, + isCloseTo, + inCloseRange, + isCollinear, + isClockwise, + isCounterClockwise, + doCombinations, + offsetPrecision, + intersectRayLine, + intersect, + determinant, + numOrDefault, comma: (v) => { if (!v) return v; let [lt,rt] = v.toString().split('.'); diff --git a/src/geo/polygons.js b/src/geo/polygons.js index 78fdbc18..993fe0b0 100644 --- a/src/geo/polygons.js +++ b/src/geo/polygons.js @@ -15,7 +15,8 @@ SQRT = Math.sqrt, SQR = UTIL.sqr, NOKEY = BASE.key.NONE, - newPoint = BASE.newPoint; + newPoint = BASE.newPoint, + numOrDefault = UTIL.numOrDefault; BASE.polygons = { rayIntersect, @@ -46,10 +47,6 @@ * Polygon array utility functions ******************************************************************* */ - function numOrDefault(num, def) { - return num !== undefined ? num : def; - } - function setZ(polys, z) { polys.forEach(p => p.setZ(z)); return polys; diff --git a/src/kiri/init.js b/src/kiri/init.js index f3cde2d9..fb74e120 100644 --- a/src/kiri/init.js +++ b/src/kiri/init.js @@ -1479,8 +1479,8 @@ lprefs: UC.newGroup(LANG.op_menu, $('prefs-gen1'), {inline: true}), // hoverPop: UC.newBoolean(LANG.op_hopo_s, booleanSave, {title:LANG.op_hopo_l}), - dark: UC.newBoolean(LANG.op_dark_s, booleanSave, {title:LANG.op_dark_l}), reverseZoom: UC.newBoolean(LANG.op_invr_s, booleanSave, {title:LANG.op_invr_l}), + dark: UC.newBoolean(LANG.op_dark_s, booleanSave, {title:LANG.op_dark_l}), decals: UC.newBoolean(LANG.op_decl_s, booleanSave, {title:LANG.op_decl_s}), expert: UC.newBoolean(LANG.op_xprt_s, booleanSave, {title:LANG.op_xprt_l}), @@ -1607,11 +1607,11 @@ camContourSep: UC.newBlank({class:"pop-sep"}), camContourXOn: UC.newBoolean(LANG.cf_linx_s, onBooleanClick, {title:LANG.cf_linx_l, modes:CAM}), camContourYOn: UC.newBoolean(LANG.cf_liny_s, onBooleanClick, {title:LANG.cf_liny_l, modes:CAM}), - // camTracing: UC.newGroup(LANG.cu_menu, null, {modes:CAM, marker:true}), - // camTraceTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), - // camTraceSpeed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, modes:CAM}), - // camTracingSep: UC.newBlank({class:"pop-sep"}), - // camTraceOn: UC.newBoolean(LANG.enable, onBooleanClick, {title:'todo', modes:CAM}), + camTracing: UC.newGroup(LANG.cu_menu, null, {modes:CAM, marker:true}), + camTraceTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), + camTraceSpeed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, modes:CAM}), + camTracingSep: UC.newBlank({class:"pop-sep"}), + camTraceOn: UC.newBoolean(LANG.enable, onBooleanClick, {title:'todo', modes:CAM}), camDrill: UC.newGroup(LANG.cd_menu, null, {modes:CAM, marker:true}), camDrillTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), camDrillSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM, visible:spindleShow}), diff --git a/src/kiri/slicer2.js b/src/kiri/slicer2.js index 12f19a32..58407425 100644 --- a/src/kiri/slicer2.js +++ b/src/kiri/slicer2.js @@ -175,7 +175,7 @@ zM = Math.max(p1.z, p2.z, p3.z), bm = Math.floor(zm * zScale), bM = Math.ceil(zM * zScale); - for (let j = bm; j < bM; j++) { + for (let j = bm; j <= bM; j++) { buckets[j].push(p1); buckets[j].push(p2); buckets[j].push(p3); @@ -203,8 +203,9 @@ } let znorm = z.toFixed(5), - flatoff = opt.flatoff || 0.01, + flatoff = UTIL.numOrDefault(opt.flatoff, 0.01), onflat = this.zFlat[znorm], + edges = opt.edges || false, phash = {}, lines = [], zScale = this.zScale, @@ -236,7 +237,7 @@ // one side of triangle is on the Z plane and 3rd is below // drop lines with 3rd above because that leads to ambiguities // with complex nested polygons on flat surface - if (where.under.length === 1) { + if (edges || where.under.length === 1) { lines.push(makeZLine(phash, where.on[0], where.on[1], false, true)); } } else if (where.on.length === 3) { @@ -245,7 +246,7 @@ // that will satisfy the if above (line) with 2 points } else if (where.under.length === 0 || where.over.length === 0) { // does not intersect but one point is on the slice Z plane - } else { + } else if (!edges) { // compute two point intersections and construct line let line = intersectPoints(where.over, where.under, z); if (line.length < 2 && where.on.length === 1) { @@ -277,7 +278,7 @@ } const haslines = lines.length || opt.emptyok; - const hastops = !opt.genso || opt.notopok || (retn.tops && retn.tops.length); + const hastops = !opt.genso || opt.notopok || (retn.tops && retn.tops.length) || edges; if (opt.each && haslines && hastops) { opt.each(retn, index, total, UTIL.time() - mark); @@ -515,6 +516,7 @@ search = 1, nextMod = 1, bridge = CONF.bridgeLineGapDistance, + minPoly = opt.openok ? 2 : 3, p1, p2; function cachedPoint(p) { @@ -609,7 +611,7 @@ // emit a polygon if it can be cleaned and still have 2 or more points function emit(poly) { poly = poly.clean(); - if (poly.length > 2) output.push(poly); + if (poly.length >= minPoly) output.push(poly); } // given an array of paths, emit longest to shortest @@ -641,7 +643,7 @@ // emit polygons largest to smallest // omit polygon if it intersects previously emitted (has del points) paths.forEach(function(path) { - if (path.length < 3) return; + if (path.length < minPoly) return; let len = path.length, i; for (i = 0; i < len; i++) if (path[i].del) return; for (i = 0; i < len; i++) path[i].del = true; diff --git a/src/mode/cam/client.js b/src/mode/cam/client.js index b0ed1a09..5564a28f 100644 --- a/src/mode/cam/client.js +++ b/src/mode/cam/client.js @@ -49,13 +49,13 @@ api.event.on("settings.saved", (settings) => { const proc = settings.process; // show/hide dots in enabled process pop buttons - // api.ui.camTabs.marker.style.display = proc.camTabsOn ? 'flex' : 'none'; api.ui.camRough.marker.style.display = proc.camRoughOn ? 'flex' : 'none'; api.ui.camDrill.marker.style.display = proc.camDrillingOn || proc.camDrillReg !== 'none' ? 'flex' : 'none'; api.ui.camOutline.marker.style.display = proc.camOutlineOn ? 'flex' : 'none'; api.ui.camContour.marker.style.display = proc.camContourXOn || proc.camContourYOn ? 'flex' : 'none'; + api.ui.camTracing.marker.style.display = proc.camTraceOn ? 'flex' : 'none'; updateStock(settings, 'settings.saved.internal'); }); diff --git a/src/mode/cam/slice.js b/src/mode/cam/slice.js index 4e408111..7cea406a 100644 --- a/src/mode/cam/slice.js +++ b/src/mode/cam/slice.js @@ -438,7 +438,7 @@ offset.slice().forEach(op => { // clone removes inners but the real solution is // to limit expanded shells to through holes - POLY.expand([op.clone()], outlineToolDiam * 0.5, slice.z, offset, 1); + POLY.expand([op.clone(true)], outlineToolDiam * 0.5, slice.z, offset, 1); }); } } @@ -484,13 +484,30 @@ } // prepare for tracing paths - let traceTool; - let traceToolProfile; if (procTrace) { - traceTool = getToolById(conf, proc.camTraceTool); - if (traceTool.type !== 'endmill') { - traceToolProfile = createToolProfile(conf, proc.camTraceTool, widget.topo); - } + let traceTool = new CAM.Tool(conf, proc.camTraceTool); + let traceToolDiam = traceTool.fluteDiameter(); + maxToolDiam = Math.max(maxToolDiam, traceToolDiam); + // unique merge of z flats and z line indices + let indices = [...new Set(Object.keys(slicer.zFlat) + .map(kv => parseFloat(kv).round(5)) + .appendAll(Object.entries(slicer.zLine).map(ze => { + let [ zk, zv ] = ze; + return zv > 0 ? parseFloat(zk).round(5) : null; + }) + .filter(v => v !== null)))] + .sort((a,b) => b - a); + let slices = []; + slicer.slice(indices, { each: (data, index, total) => { + let slice = data.slice; + slice.camMode = PRO.TRACE; + slices.push(slice); + sliceAll.append(slice); + if (true) slice.output() + .setLayer("trace", {line: 0x88aa55}, false) + .addPolys(slice.topPolys()) + updateOp(index, total); + }, genso: true, emptyok: true, flatoff: 0, edges: true, openok: true }); } if (procDrill) {