diff --git a/notes.md b/notes.md index 73b5babc..a9e6aa45 100644 --- a/notes.md +++ b/notes.md @@ -45,13 +45,10 @@ # CAM * `B` fails in pancaking (clone) when there are no sliced layers (like z bottom too high) -* `B` linear finishing should extend beyond part boundaries by tool radius +* `B` contouring should extend beyond part boundaries by tool radius * `B` outside cutting direction in roughing mode inverted * `F` z bounded slices (extension of z bottom offset feature) * `F` use arcs to connect hard angles -* `F` do not rough areas that go all the way through the part - https://github.com/GridSpace/grid-apps/issues/20 -* `F` send gcode to cncjs * `F` lead-in milling * `F` trapezoidal tabs (in the Z axis) * `F` ease-in and ease-out especially on tab cut-out start/stop @@ -62,9 +59,9 @@ * `F` warn when part > stock or cuts go outside bed * `F` add M03 tool feedrate support * `P` refactor slicing around flats w/ interpolation instead of culling -* `P` disable topo generation when no linear xy and no depth first +* `P` disable topo generation when no contour xy and no depth first * `P` store tab and camshell polys in widget.topo to minimize z on edge moves -* `P` linear finishing is going back to z top too often +* `P` contouring is going back to z top too often * `P` option to skip milling holes that would be drilled * `P` crossing open space check point is outside camshell before returning max z * `P` background worker to speculatively generate topo maps (and maybe pre-slicing) diff --git a/src/kiri/init.js b/src/kiri/init.js index f773bf9f..19834fda 100644 --- a/src/kiri/init.js +++ b/src/kiri/init.js @@ -1360,7 +1360,7 @@ camRough: UC.newGroup(LANG.cr_menu, null, {modes:CAM, marker:true}), camRoughTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), - camRoughSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM}), + camRoughSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM, visible:spindleShow}), camRoughOver: UC.newInput(LANG.cc_sovr_s, {title:LANG.cc_sovr_l, convert:UC.toFloat, bound:UC.bound(0.1,1.0), modes:CAM}), camRoughDown: UC.newInput(LANG.cc_sdwn_s, {title:LANG.cc_sdwn_l, convert:UC.toFloat, modes:CAM}), camRoughSpeed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, modes:CAM}), @@ -1372,7 +1372,7 @@ camRoughOn: UC.newBoolean(LANG.enable, onBooleanClick, {modes:CAM}), camOutline: UC.newGroup(LANG.co_menu, null, {modes:CAM, marker:true}), camOutlineTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), - camOutlineSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM}), + camOutlineSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM, visible:spindleShow}), camOutlineOver: UC.newInput(LANG.cc_sovr_s, {title:LANG.cc_sovr_l, convert:UC.toFloat, bound:UC.bound(0.05,1.0), modes:CAM}), camOutlineDown: UC.newInput(LANG.cc_sdwn_s, {title:LANG.cc_sdwn_l, convert:UC.toFloat, modes:CAM}), camOutlineSpeed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, modes:CAM}), @@ -1382,7 +1382,7 @@ camOutlineOn: UC.newBoolean(LANG.cf_watr_s, onBooleanClick, {title:LANG.cf_watr_l, modes:CAM}), camContour: UC.newGroup(LANG.cn_menu, null, {modes:CAM, marker:true}), camContourTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), - camContourSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM}), + camContourSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM, visible:spindleShow}), camContourSpeed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, modes:CAM}), camContourAngle: UC.newInput(LANG.cf_angl_s, {title:LANG.cf_angl_l, convert:UC.toFloat, bound:UC.bound(45,90), modes:CAM}), camContourCurves: UC.newBoolean(LANG.cf_curv_s, onBooleanClick, {title:LANG.cf_curv_l, modes:CAM}), @@ -1391,11 +1391,12 @@ 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"}), - // camTraceEnable: UC.newBoolean(LANG.enable, onBooleanClick, {title:'todo', modes:CAM}), + // 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}), + camDrillSpindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, modes:CAM, visible:spindleShow}), camDrillDown: UC.newInput(LANG.cd_plpr_s, {title:LANG.cd_plpr_l, convert:UC.toFloat, modes:CAM}), camDrillDownSpeed: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:UC.toFloat, modes:CAM}), camDrillDwell: UC.newInput(LANG.cd_dwll_s, {title:LANG.cd_dwll_l, convert:UC.toFloat, modes:CAM}), @@ -1530,6 +1531,10 @@ layerMoves: UC.newBoolean(LANG.la_move, onLayerToggle, {modes:GCODE}) }); + function spindleShow() { + return settings().device.spindleMax > 0; + } + // slider setup const slbar = 30; const slbar2 = slbar * 2; diff --git a/src/kiri/ui.js b/src/kiri/ui.js index a2270df7..e7898cd6 100644 --- a/src/kiri/ui.js +++ b/src/kiri/ui.js @@ -305,7 +305,7 @@ } function addModeControls(el, options) { - options = options || {}; + let opt = options || {}; el.__show = true; el.__modeSave = null; el.showMe = function() { @@ -325,16 +325,17 @@ else el.hideMe(); }; el.setMode = function(mode) { - let show = options.expert === undefined || (options.expert === letExpert); - el.setVisible(el.hasMode(mode) && show); + let show = opt.expert === undefined || (opt.expert === letExpert); + let disp = opt.visible ? opt.visible() : true; + el.setVisible(el.hasMode(mode) && show && disp); } el.hasMode = function(mode) { if (mode === NOMODE) return false; if (!el.modes) return true; return el.modes.contains(mode); } - if (options.modes) { - el.modes = options.modes; + if (opt.modes) { + el.modes = opt.modes; hasModes.push(el); } } diff --git a/src/mode/cam/driver.js b/src/mode/cam/driver.js index d7ea7d3b..b4e146ac 100644 --- a/src/mode/cam/driver.js +++ b/src/mode/cam/driver.js @@ -236,6 +236,7 @@ if (!union) { union = tops; } else { + // replace slice's tops with unioned tops tops.appendAll(union); union = POLY.union(tops); slice.tops = []; @@ -261,11 +262,13 @@ let holes = slice.gatherTopPolyInners([]).clone(); if (last) { let inter = []; + // find intersection of hole below and hole in this layer holes.forEach(hole => { - last.forEach(poly => { - inter.appendAll(hole.intersect(poly)); + last.forEach(hole_under => { + inter.appendAll(hole.intersect(hole_under)); }); }); + // filter dup polygons (which intersect can produce) last = inter.filter((poly, index, arr) => { for (let i=index+1, il=arr.length; i zMin + tabHeight) return; - // no tops / traces + // skip if no tops | traces if (slice.tops.length === 0) return; let trace, index, maxArea = 0, tmpArea; @@ -911,22 +916,23 @@ // required to match computed order of cutouts trace.setClockwise(); - let count = proc.camTabsCount; - let angle = proc.camTabsAngle; - let angle_inc = 360 / count; - let center = BASE.newPoint(0,0,slice.z); - let offset = (tabWidth + toolDiam) / 2; - let ints = []; - let segs = []; + let count = proc.camTabsCount, + angle = proc.camTabsAngle, + angle_inc = 360 / count, + center = BASE.newPoint(0,0,slice.z), + offset = (tabWidth + toolDiam) / 2, + ints = [], + segs = []; + while (count-- > 0) { - let slope = BASE.newSlopeFromAngle(angle); - let normal = BASE.newSlopeFromAngle(angle + 90); - let c1 = center.projectOnSlope(normal, offset); - let c2 = center.projectOnSlope(normal, -offset); - let o1 = c1.projectOnSlope(slope, 10000); - let o2 = c2.projectOnSlope(slope, 10000); - let int1 = trace.intersections(c1, o1).pop(); - let int2 = trace.intersections(c2, o2).pop(); + let slope = BASE.newSlopeFromAngle(angle), + normal = BASE.newSlopeFromAngle(angle + 90), + c1 = center.projectOnSlope(normal, offset), + c2 = center.projectOnSlope(normal, -offset), + o1 = c1.projectOnSlope(slope, 10000), + o2 = c2.projectOnSlope(slope, 10000), + int1 = trace.intersections(c1, o1).pop(), + int2 = trace.intersections(c2, o2).pop(); if (int1 && int2) { ints.push(int1); ints.push(int2); @@ -935,6 +941,7 @@ // segs.push(newPolygon([c1,o1])); // segs.push(newPolygon([c2,o2])); } + if (ints.length) { ints.push(ints.shift()); for (let i=0; i