From 345db082e39aa7a5112cc0cd1fdb15d562f58261 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Wed, 25 Nov 2020 22:50:44 -0500 Subject: [PATCH] add entirely new manual tab system and disable the old auto system because it's incompatible --- src/geo/polygon.js | 45 +++++++++++++++++++++++++++++++++ src/kiri/init.js | 10 ++++---- src/mode/cam/client.js | 6 ++--- src/mode/cam/slice.js | 56 +++++++++++++++++++++++++++++++++++++----- src/mode/cam/topo.js | 10 ++++++-- 5 files changed, 111 insertions(+), 16 deletions(-) diff --git a/src/geo/polygon.js b/src/geo/polygon.js index 48fdf98b..a51d576c 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -1414,6 +1414,51 @@ } }; + PRO.cut = function(polys) { + let target = this; + + if (!target.open) { + target = this.clone(true).setOpen(); + target.push(target.first()); + if (target.inner) { + target.inner.forEach(ip => { + ip.setOpen(); + ip.push(ip.first()); + }); + } + } + + let clib = self.ClipperLib, + ctyp = clib.ClipType, + ptyp = clib.PolyType, + cfil = clib.PolyFillType, + clip = new clib.Clipper(), + ctre = new clib.PolyTree(), + sp1 = target.toClipper(), + sp2 = POLY().toClipper(polys); + + clip.AddPaths(sp1, ptyp.ptSubject, false); + clip.AddPaths(sp2, ptyp.ptClip, true); + + if (clip.Execute(ctyp.ctDifference, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { + let cuts = POLY().fromClipperTree(ctre, target.getZ(), null, null, 0); + cuts.forEach(no => { + // heal open but really closed polygons because cutting + // has to open the poly to perform the cut. but the result + // may have been no intersection leaving an open poly + if (no.open && no.first().distTo2D(no.last()) < 0.001) { + no.open = false; + no.points.pop(); + no.length--; + } + }); + return cuts; + } else { + return this; + } + }; + + PRO.intersect = function(poly, min) { if (!this.overlaps(poly)) return null; diff --git a/src/kiri/init.js b/src/kiri/init.js index 4409b7a5..641ee053 100644 --- a/src/kiri/init.js +++ b/src/kiri/init.js @@ -1544,13 +1544,13 @@ camDrillingOn: UC.newBoolean(LANG.enable, onBooleanClick, {modes:CAM}), camDrillSep: UC.newBlank({class:"pop-sep"}), camDrillReg: UC.newSelect(LANG.cd_regi_s, {modes:CAM, title:LANG.cd_regi_l}, "drillreg"), - camTabs: UC.newGroup(LANG.ct_menu, null, {modes:CAM, marker:true}), + camTabs: UC.newGroup(LANG.ct_menu, null, {modes:CAM, marker:false}), camTabsWidth: UC.newInput(LANG.ct_wdth_s, {title:LANG.ct_wdth_l, convert:UC.toFloat, bound:UC.bound(0.005,100), modes:CAM, units:true}), camTabsHeight: UC.newInput(LANG.ct_hght_s, {title:LANG.ct_hght_l, convert:UC.toFloat, bound:UC.bound(0.005,100), modes:CAM, units:true}), - camTabSep: UC.newBlank({class:"pop-sep"}), - camTabsAngle: UC.newInput(LANG.ct_angl_s, {title:LANG.ct_angl_l, convert:UC.toInt, bound:UC.bound(0,360), modes:CAM}), - camTabsCount: UC.newInput(LANG.ct_numb_s, {title:LANG.ct_numb_l, convert:UC.toInt, bound:UC.bound(1,20), modes:CAM}), - camTabsOn: UC.newBoolean(LANG.ct_nabl_s, onBooleanClick, {title:LANG.ct_nabl_l, modes:CAM}), + // camTabSep: UC.newBlank({class:"pop-sep"}), + // camTabsAngle: UC.newInput(LANG.ct_angl_s, {title:LANG.ct_angl_l, convert:UC.toInt, bound:UC.bound(0,360), modes:CAM}), + // camTabsCount: UC.newInput(LANG.ct_numb_s, {title:LANG.ct_numb_l, convert:UC.toInt, bound:UC.bound(1,20), modes:CAM}), + // camTabsOn: UC.newBoolean(LANG.ct_nabl_s, onBooleanClick, {title:LANG.ct_nabl_l, modes:CAM}), camTabSep: UC.newBlank({class:"pop-sep"}), camTabsManual: UC.newRow([ (UI.tabAdd = UC.newButton(undefined, onButtonClick, {icon:''})), diff --git a/src/mode/cam/client.js b/src/mode/cam/client.js index 9b8f166d..e15f126b 100644 --- a/src/mode/cam/client.js +++ b/src/mode/cam/client.js @@ -48,7 +48,7 @@ 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.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'; @@ -148,7 +148,7 @@ tabs.forEach(rec => { let { id, pos, rot } = rec; let tab = widget.tabs[id]; - let m4 = new THREE.Matrix4().makeRotationFromEuler(new THREE.Euler(x || 0, y || 0, z || 0)); + let m4 = new THREE.Matrix4().makeRotationFromEuler(new THREE.Euler(0, 0, z || 0)); // update position vector let vc = new THREE.Vector3(pos.x, pos.y, pos.z).applyMatrix4(m4); // update rotation quaternion @@ -258,7 +258,7 @@ pos, 0x0000dd, id, dim, { group: widget.mesh, rotate: rot } ); - pos.box.tab = Object.assign({widget}, pos); + pos.box.tab = Object.assign({widget, id}, pos); widget.adds.push(pos.box); tabs[id] = pos; } diff --git a/src/mode/cam/slice.js b/src/mode/cam/slice.js index cb92de62..89324824 100644 --- a/src/mode/cam/slice.js +++ b/src/mode/cam/slice.js @@ -62,7 +62,31 @@ camRoughDown = proc.camRoughDown, minStepDown = Math.min(1, roughDown/3, outlineDown/3), maxToolDiam = 0, - thruHoles; + thruHoles, + tabs = settings.widget[widget.id].tab; + + // force off for testing + proc.camTabsOn = false; + + if (tabs) { + // make tab polygons + tabs.forEach(tab => { + let zero = BASE.newPoint(0,0,0); + let point = BASE.newPoint(tab.pos.x, tab.pos.y, tab.pos.z); + let poly = BASE.newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y); + let tslice = KIRI.newSlice(0); + let m4 = new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion(tab.rot._x, tab.rot._y, tab.rot._z, tab.rot._w) + ); + poly.points = poly.points + .map(p => new THREE.Vector3(p.x,p.y,p.z).applyMatrix4(m4)) + .map(v => BASE.newPoint(v.x, v.y, v.z)); + poly.move(point); + tab.poly = poly; + // tslice.output().setLayer("tabs", 0xff0000).addPoly(poly); + // sliceAll.push(tslice); + }); + } if (stock.x && stock.y && stock.z) { if (stock.x + 0.00001 < bounds.max.x - bounds.min.x) { @@ -277,8 +301,14 @@ const outside = POLY.offset(shadow.clone(), roughToolDiam * proc.camRoughOver, {z: slice.z}); if (outside) { offset.appendAll(outside); - if (addTabsOutline && slice.z <= zMin + tabHeight) { - offset = addCutoutTabs(offset, slice.z, center, roughToolDiam, tabWidth, proc.camTabsCount, proc.camTabsAngle); + // if (addTabsOutline && slice.z <= zMin + tabHeight) { + // offset = addCutoutTabs(offset, slice.z, center, roughToolDiam, tabWidth, proc.camTabsCount, proc.camTabsAngle); + // } + if (tabs) { + tabs.forEach(tab => { + tab.off = POLY.expand([tab.poly], roughToolDiam / 2).flat(); + }); + offset = cutTabs(tabs, offset, slice.z); } } } @@ -387,8 +417,14 @@ } } - if (addTabsOutline && slice.z <= zMin + tabHeight) { - offset = addCutoutTabs(offset, slice.z, center, outlineToolDiam, tabWidth, proc.camTabsCount, proc.camTabsAngle); + // if (addTabsOutline && slice.z <= zMin + tabHeight) { + // offset = addCutoutTabs(offset, slice.z, center, outlineToolDiam, tabWidth, proc.camTabsCount, proc.camTabsAngle); + // } + if (tabs) { + tabs.forEach(tab => { + tab.off = POLY.expand([tab.poly], outlineToolDiam / 2).flat(); + }); + offset = cutTabs(tabs, offset, slice.z); } // offset.xout(`slice ${slice.z}`); @@ -419,7 +455,8 @@ sliceAll.appendAll(slices); }, shadow: tshadow, - center: center + center: center, + tabs }); } @@ -539,6 +576,13 @@ } } + function cutTabs(tabs, offset, z) { + let noff = []; + tabs = tabs.filter(tab => z < tab.pos.z + tab.dim.z/2).map(tab => tab.off).flat(); + offset.forEach(op => noff.appendAll( op.cut(tabs) )); + return noff; + } + // cut outside traces at the right points function addCutoutTabs(polys, z, center, toolDiam, tabWidth, tabCount, tabAngle, slice) { // skip if no tops | traces diff --git a/src/mode/cam/topo.js b/src/mode/cam/topo.js index 6734053f..75e374d5 100644 --- a/src/mode/cam/topo.js +++ b/src/mode/cam/topo.js @@ -58,8 +58,10 @@ widget: widget }, newslices = [], - tabsOn = proc.camTabsOn, - tabHeight = proc.camTabsHeight + zBottom, + tabs = opt.tabs, + tabsMax = tabs ? Math.max(...tabs.map(tab => tab.dim.z)) : 0, + tabsOn = proc.camTabsOn || tabs, + tabHeight = Math.max(proc.camTabsHeight + zBottom, tabsMax), clipTab = tabsOn ? [] : null, clipTo = inside ? shadow : POLY.expand(shadow, toolDiameter/2 + resolution * 3), partOff = inside ? 0 : toolDiameter / 2 + resolution, @@ -71,6 +73,10 @@ debug_topo_lines = debug && false, debug_topo_shells = debug && false; + if (tabs) { + clipTab.appendAll(tabs.map(tab => POLY.expand([tab.poly], toolDiameter/2)).flat()); + } + if (proc.camTabsOn) { CAM.createTabLines( center,