From b165822badb2f83eba1ad34f7510d957918e49c9 Mon Sep 17 00:00:00 2001 From: bakedpotatolord Date: Tue, 6 May 2025 11:49:50 -0600 Subject: [PATCH 1/8] add outline ordering for wide cut --- src/kiri-mode/cam/ops.js | 42 ++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index 5c48a916..d2cd4d90 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -628,12 +628,18 @@ class OpOutline extends CamOp { } else { if (op.wide) { let stepover = toolDiam * op.step; - for (let c = (op.steps || 1); c > 0; c--) - offset.slice().forEach(op => { - // clone removes inners but the real solution is - // to limit expanded shells to through holes - POLY.expand([op.clone(true)], stepover, slice.z, offset, 1); - }); + for (let c = (op.steps || 1); c > 0; c--){ + offset.slice().forEach(op => { + // clone removes inners but the real solution is + // to limit expanded shells to through holes + let wideCut = POLY.expand([op.clone(true)], stepover, slice.z, [], 1); + wideCut.forEach(cut =>{ //set order of cuts when wide + cut.order = c + cut.inner.forEach(inn =>{ inn.order = c }) + }); + offset.push(...wideCut) + }); + } } } @@ -697,7 +703,9 @@ class OpOutline extends CamOp { for (let slice of sliceOut) { let polys = [], t = [], c = []; - POLY.flatten(slice.camLines).forEach(function (poly) { + let lines =POLY.flatten(slice.camLines) + lines.forEach(l =>{ if(l.order == undefined) l.order = 0; }); + lines.forEach(function (poly) { let child = poly.parent; if (depthFirst) { poly = poly.clone(); poly.parent = child ? 1 : 0 } if (child) c.push(poly); else t.push(poly); @@ -713,11 +721,21 @@ class OpOutline extends CamOp { if (depthFirst) { depthData.push(polys); } else { - printPoint = poly2polyEmit(polys, printPoint, function(poly, index, count) { - poly.forEachPoint(function(point, pidx, points, offset) { - camOut(point.clone(), offset !== 0); - }, poly.isClosed(), index); - }, { swapdir: false }); + let orderSplit = {} + polys.forEach(poly => { + if(poly.order in orderSplit) orderSplit[poly.order].push(poly); + else orderSplit[poly.order] = [poly]; + }) + Object.entries(orderSplit) //split the polys by order + .sort((a,b) => -(a[0] - b[0] )) //sort by order (highest first) + .forEach(([order, orderPolys]) => { // emit based on closest for each order + // console.log({order, orderPolys}); + printPoint = poly2polyEmit(orderPolys, printPoint, function(poly, index, count) { + poly.forEachPoint(function(point, pidx, points, offset) { + camOut(point.clone(), offset !== 0); + }, poly.isClosed(), index); + }, { swapdir: false }); + }) newLayer(); } } From 4daa14416f9f2d3797dfa68e5eeb290a5a116be0 Mon Sep 17 00:00:00 2001 From: bakedpotatolord Date: Tue, 6 May 2025 12:30:50 -0600 Subject: [PATCH 2/8] fix edge cases --- src/kiri-mode/cam/ops.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index d2cd4d90..92ba93dd 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -628,18 +628,20 @@ class OpOutline extends CamOp { } else { if (op.wide) { let stepover = toolDiam * op.step; + let wideCuts = [] //accumulator for wide cuts for (let c = (op.steps || 1); c > 0; c--){ offset.slice().forEach(op => { // clone removes inners but the real solution is // to limit expanded shells to through holes - let wideCut = POLY.expand([op.clone(true)], stepover, slice.z, [], 1); + let wideCut = POLY.expand([op.clone(true)], stepover*c, slice.z, [], 1); wideCut.forEach(cut =>{ //set order of cuts when wide cut.order = c - cut.inner.forEach(inn =>{ inn.order = c }) + if(cut.inner) cut.inner.forEach(inn =>{ inn.order = c }) }); - offset.push(...wideCut) + wideCuts.push(...wideCut) }); } + offset.appendAll(wideCuts); } } @@ -704,6 +706,7 @@ class OpOutline extends CamOp { for (let slice of sliceOut) { let polys = [], t = [], c = []; let lines =POLY.flatten(slice.camLines) + console.log(lines); lines.forEach(l =>{ if(l.order == undefined) l.order = 0; }); lines.forEach(function (poly) { let child = poly.parent; @@ -729,7 +732,7 @@ class OpOutline extends CamOp { Object.entries(orderSplit) //split the polys by order .sort((a,b) => -(a[0] - b[0] )) //sort by order (highest first) .forEach(([order, orderPolys]) => { // emit based on closest for each order - // console.log({order, orderPolys}); + console.log({order, orderPolys}); printPoint = poly2polyEmit(orderPolys, printPoint, function(poly, index, count) { poly.forEachPoint(function(point, pidx, points, offset) { camOut(point.clone(), offset !== 0); From 663810b2ac79b7d62c62cc35abb509a352c810fd Mon Sep 17 00:00:00 2001 From: bakedpotatolord Date: Tue, 6 May 2025 12:31:28 -0600 Subject: [PATCH 3/8] get rid of console.logs --- src/kiri-mode/cam/ops.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index 92ba93dd..c4f4e8b0 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -706,7 +706,7 @@ class OpOutline extends CamOp { for (let slice of sliceOut) { let polys = [], t = [], c = []; let lines =POLY.flatten(slice.camLines) - console.log(lines); + // console.log(lines); lines.forEach(l =>{ if(l.order == undefined) l.order = 0; }); lines.forEach(function (poly) { let child = poly.parent; @@ -732,7 +732,7 @@ class OpOutline extends CamOp { Object.entries(orderSplit) //split the polys by order .sort((a,b) => -(a[0] - b[0] )) //sort by order (highest first) .forEach(([order, orderPolys]) => { // emit based on closest for each order - console.log({order, orderPolys}); + // console.log({order, orderPolys}); printPoint = poly2polyEmit(orderPolys, printPoint, function(poly, index, count) { poly.forEachPoint(function(point, pidx, points, offset) { camOut(point.clone(), offset !== 0); From 9290b7f7a75847ea1addf25b52054257e9aafa34 Mon Sep 17 00:00:00 2001 From: bakedpotatolord Date: Tue, 6 May 2025 20:56:57 -0600 Subject: [PATCH 4/8] condensed poly loops into one --- src/kiri-mode/cam/ops.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index c4f4e8b0..a209bffe 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -707,8 +707,8 @@ class OpOutline extends CamOp { let polys = [], t = [], c = []; let lines =POLY.flatten(slice.camLines) // console.log(lines); - lines.forEach(l =>{ if(l.order == undefined) l.order = 0; }); - lines.forEach(function (poly) { + lines.forEach((poly)=> { + poly.order = poly.order ?? 0; let child = poly.parent; if (depthFirst) { poly = poly.clone(); poly.parent = child ? 1 : 0 } if (child) c.push(poly); else t.push(poly); From d2e502d7631814b11df16b617239f7fbcbbb98ae Mon Sep 17 00:00:00 2001 From: bakedpotatolord Date: Thu, 8 May 2025 11:12:15 -0600 Subject: [PATCH 5/8] comment out console log --- src/kiri-mode/cam/client.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js index a73732e6..e9340655 100644 --- a/src/kiri-mode/cam/client.js +++ b/src/kiri-mode/cam/client.js @@ -401,7 +401,8 @@ CAM.init = function(kiri, api) { func.opAddDrill = () => { let rec = popOp.drill.new(); - rec.drills = { /* widget.id: [ drills... ] */ }; + console.log("drill created",rec) + rec.drills = { }; func.opAdd(rec); }; @@ -1245,11 +1246,10 @@ CAM.init = function(kiri, api) { alert = api.show.alert("Some holes are shadowed by part and are not shown."); } centers = centers ?? [] - //flattened list of all hole centers and if they are selected + // list of all hole centers and if they are selected kiri.api.widgets.for(widget => { const {holes} = centers.find(center=>center.id = widget.id) - - console.log(holes) + // console.log(holes) if (!holes.length) unselectHoles(holes); holes.forEach(hole => { createHoleMesh(widget, hole) @@ -1778,8 +1778,8 @@ CAM.init = function(kiri, api) { lift: 'camDrillLift', mark: 'camDrillMark', thru: 'camDrillThru', + }) - drillOp.inputs = { tool: UC.newSelect(LANG.cc_tool, {}, "tools"), sep: UC.newBlank({class:"pop-sep"}), From 97e4b640b6ee9db1ee679107a66829646a4cd0c3 Mon Sep 17 00:00:00 2001 From: bakedpotatolord Date: Thu, 8 May 2025 11:13:14 -0600 Subject: [PATCH 6/8] rewrite drill finding code to be more robust --- src/kiri-mode/cam/driver.js | 2 +- src/kiri-mode/cam/slice.js | 73 +++++++++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/kiri-mode/cam/driver.js b/src/kiri-mode/cam/driver.js index f10b3783..12882077 100644 --- a/src/kiri-mode/cam/driver.js +++ b/src/kiri-mode/cam/driver.js @@ -167,7 +167,7 @@ kiri.load(api => { // const fresh = widgets.filter(widget => CAM.traces(settings, widget, single)); send.done(kiri.codec.encode(fresh.map(widget => { return { id: widget.id, - holes: widget.holes, + holes: widget.drills, shadowed:widget.shadowedDrills } } ))); } diff --git a/src/kiri-mode/cam/slice.js b/src/kiri-mode/cam/slice.js index 5624940f..00c98e02 100644 --- a/src/kiri-mode/cam/slice.js +++ b/src/kiri-mode/cam/slice.js @@ -474,12 +474,14 @@ CAM.holes = async function(settings, widget, diam) { .map(kv => parseFloat(kv).round(5)) .filter(z => z !== null) )] + let individual = (diam <= 0); + + diam = individual ? 1 : diam; // sets default diameter when select individual used + let centerDiff = diam * 0.1, area = (diam/2) * (diam/2) * Math.PI, - areaDelta = area * 0.05, - drills = [], - slices = [], - individual = (diam <= 0); + circles = [], + slices = []; function onEach(slice) { slices.push(slice); @@ -499,38 +501,71 @@ CAM.holes = async function(settings, widget, diam) { for (let poly of inner) { let center = poly.calcCircleCenter(); center.area = poly.area(); + center.overlapping = [center] + center.depth = 0; // console.log("center",center) - center.selected = (!individual && poly.circularity() >= 0.985 && Math.abs(center.area - area) <= areaDelta ); + if ( poly.circularity() < 0.985 ){ + // if not circular, don't add to holes + continue; + } if (center.isInPolygon(slice.shadow)) { // if shadowed, don't add, and inform client shadowedDrills = true; continue; } let overlap = false; - for (let [i,drill] of drills.entries()) { - let dist = drill.distTo2D(center) - //if on the same xy point, and both have the same selection value - if (dist <= centerDiff && drill.selected == center.selected) { - // console.log("overlap",center,drill); - if(center.z > drill.z) { //if current is higher than old - drills[i] = center; //replace with top point - drills[i].depth = center.z-drill.z - }else if(center.z <= drill.z-drill.depth){// if current is lower or same as old - drills[i].depth = drill.z-center.z - } + for (let [i,circle] of circles.entries()) { + let dist = circle.distTo2D(center) + + // //if on the same xy point, + if (dist <= centerDiff ) { + + // console.log("overlap",center,circle); + circle.overlapping.push(center); // if overlapping, don't add and continue overlap = true; continue; } } - center.depth = 0; - if(!overlap) drills.push(center); + if (!overlap) circles.push(center); } } } + + let drills = [] + + for (let c of circles) { + let overlapping = c.overlapping + .sort((a,b) => b.z - a.z) + + console.log("overlapping",structuredClone(overlapping)) + let last = overlapping.shift(); + while (overlapping.length) { + let circ = overlapping.shift(); + let aveArea = (circ.area + last.area) / 2; + let areaDelta = Math.abs(circ.area -last.area) + if (areaDelta < aveArea * 0.05){ // if area delta less than 5% of average area + //keep top circle selected + last.depth = last.z - circ.z; + }else{ // if not the same area + //push and move on + drills.push(last); + last = circ; + } + } + if (last.depth != 0) drills.push(last) //add last circle + } + + drills.forEach( h=>{ + delete h.overlapping //for encoding + h.selected = (!individual && Math.abs(h.area - area) <= area * 0.05 ); //for same size selection + }) + + // console.log("unfiltered circles",circles) + console.log("drills",drills) drills = drills.filter(drill => drill.depth > 0) widget.shadowedDrills = shadowedDrills - widget.holes = drills; + widget.drills = drills; return drills; } From a7b55b52bd44cbe3dcb2caefb0102486e9d1944f Mon Sep 17 00:00:00 2001 From: bakedpotatolord Date: Thu, 8 May 2025 11:29:29 -0600 Subject: [PATCH 7/8] remove console logs --- src/kiri-mode/cam/slice.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/kiri-mode/cam/slice.js b/src/kiri-mode/cam/slice.js index 00c98e02..aae4bfac 100644 --- a/src/kiri-mode/cam/slice.js +++ b/src/kiri-mode/cam/slice.js @@ -538,7 +538,6 @@ CAM.holes = async function(settings, widget, diam) { let overlapping = c.overlapping .sort((a,b) => b.z - a.z) - console.log("overlapping",structuredClone(overlapping)) let last = overlapping.shift(); while (overlapping.length) { let circ = overlapping.shift(); @@ -562,7 +561,7 @@ CAM.holes = async function(settings, widget, diam) { }) // console.log("unfiltered circles",circles) - console.log("drills",drills) + // console.log("drills",drills) drills = drills.filter(drill => drill.depth > 0) widget.shadowedDrills = shadowedDrills widget.drills = drills; From 2ad3196073f7831799ab5d261b092bab48982767 Mon Sep 17 00:00:00 2001 From: bakedpotatolord Date: Thu, 8 May 2025 11:29:50 -0600 Subject: [PATCH 8/8] invalidate on selection scale or rotate --- src/kiri-mode/cam/client.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js index e9340655..4b1bf706 100644 --- a/src/kiri-mode/cam/client.js +++ b/src/kiri-mode/cam/client.js @@ -258,7 +258,7 @@ CAM.init = function(kiri, api) { "selection.rotate" ], updateStock); - // invalidate trace ops on scale or rotate + // invalidate trace and drill ops on scale or rotate api.event.on([ "selection.scale", "selection.rotate" @@ -268,6 +268,9 @@ CAM.init = function(kiri, api) { if (op.type === 'trace' && !flipping) { op.areas = {}; } + else if( op.type === 'drill' && !flipping){ + op.drills = {}; + } } }); @@ -401,7 +404,6 @@ CAM.init = function(kiri, api) { func.opAddDrill = () => { let rec = popOp.drill.new(); - console.log("drill created",rec) rec.drills = { }; func.opAdd(rec); }; @@ -1403,12 +1405,12 @@ CAM.init = function(kiri, api) { func.traceDone(); } unselectTraces(widget); - if (flipping) { - return; - } if (holeSelOn) { func.selectHolesDone(); } + if (flipping) { + return; + } func.clearHolesRec(widget) if (x || y) { clearTabs(widget);