diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js index a73732e6..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,7 @@ CAM.init = function(kiri, api) { func.opAddDrill = () => { let rec = popOp.drill.new(); - rec.drills = { /* widget.id: [ drills... ] */ }; + rec.drills = { }; func.opAdd(rec); }; @@ -1245,11 +1248,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) @@ -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); @@ -1778,8 +1780,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"}), 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..aae4bfac 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,70 @@ 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) + + 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; }