From 9f14ecf88ad2a0ad8c47eb9309d0fd87603fde52 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 2 Jul 2024 13:28:13 -0400 Subject: [PATCH] checkpoint poly arc finding (for drilling op upgrade) --- src/geo/base.js | 9 +++++ src/geo/polygon.js | 73 +++++++++++++++++++++++++++++++++++++--- src/kiri-mode/cam/ops.js | 32 ++++++++++++------ 3 files changed, 99 insertions(+), 15 deletions(-) diff --git a/src/geo/base.js b/src/geo/base.js index 6956ad9b..e84b0f49 100644 --- a/src/geo/base.js +++ b/src/geo/base.js @@ -109,6 +109,13 @@ function sqr(v) { return v * v } +/** + * return distance between two points + */ +function dist2D(p1, p2) { + return Math.sqrt(distSq(p1, p2)); +} + /** * return distance squared between two points */ @@ -569,6 +576,7 @@ base.util = { pwait, ptimer, flatten, + dist2D, distSq, distSqv2, center2d, @@ -577,6 +585,7 @@ base.util = { orderClosest, doCombinations, offsetPrecision, + circleCenter, numOrDefault, thetaDiff, intersect, diff --git a/src/geo/polygon.js b/src/geo/polygon.js index a99d38b2..362bc3d3 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -601,18 +601,20 @@ class Polygon { } /** + * using perimeter length, find 3 equally spaced points to + * return a more accruate center point. * @returns {Point} center of a polygon assuming it's a circle */ - circleCenter() { + calcCircleCenter() { let pe = this.perimeter(), - pe1 = pe / 3, - pe2 = pe1 * 2, + pe1 = pe / 3, // point 2 + pe2 = pe1 * 2, // point 3 p = this.points, l = p.length, i = 1, td = 0, - lp = p[0], - ap = [ lp ]; + lp = p[0], // first point + ap = [ lp ]; // array of 3 points while (i < l) { let np = p[i++]; let d = lp.distTo2D(np); @@ -629,6 +631,67 @@ class Polygon { return newPoint(center.x, center.y, p[0].z, null); } + /** + * iterate over poly points and find sequences of 5 or more points + * with a common center point and collect as a midpoint/radius + */ + findArcCenters(opt = {}) { + if (this.length < 6) return []; + let tolerance = opt.tolerance || 1e-2, + inside = opt.inside ?? true, + seq = this.points.slice(), + util = base.util; + if (this.isClosed()) seq.appendAll(seq.slice(0,5)); + let recs = [], // accumulated arc points + cand = []; // candidate center array + for (let pos=3; pos= 3) { + // emit record on 5 points + recs.push(cand.peek()); + } + // reset candidate array + cand = [ next ]; + } + if (cand.length >= 3) { + recs.push(cand.peek()); + } + // filter dups + recs.sort((a,b) => { + return util.dist2D(a,b); + }); + recs = recs.filter((r,i) => { + if (i > 0) { + return util.dist2D(r, recs[i-1]) < tolerance*10 ? null : r; + } else { + return r; + } + }); + return recs; + } + /** * add points forming a rectangle around a center point * diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index 9882d72e..8eb28db9 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -1418,31 +1418,43 @@ class OpDrill extends CamOp { // for each slice, look for polygons with 98.5% circularity whose // area is within the tolerance of a circle matching the tool diameter - tslices.forEach(function(slice) { - if (slice.z < zBottom) return; + for (let slice of tslices) { + if (slice.z < zBottom) { + continue; + } let inner = slice.topPolyInners([]); - inner.forEach(function(poly) { + for (let poly of inner) { if (poly.circularity() >= 0.985 && Math.abs(poly.area() - area) <= areaDelta) { - let center = poly.circleCenter(), + let center = poly.calcCircleCenter(), merged = false, closest = Infinity, dist; // TODO reject if inside camShellPolys (means there is material above) - if (center.isInPolygon(slice.shadow)) return; - drills.forEach(function(drill) { - if (merged) return; + if (center.isInPolygon(slice.shadow)) { + continue; + } + for (let drill of drills) { + if (merged) { + continue; + } if ((dist = drill.last().distTo2D(center)) <= centerDiff) { merged = true; drill.push(center); } closest = Math.min(closest,dist); - }); + } if (!merged) { drills.push(newPolygon().append(center)); } + } else if (op.arcs) { + // find arcs + let arcs = poly.findArcCenters(); + for (let arc of arcs) { + drills.push(newPolygon().add(arc.x,arc.y,arc.z||0)); + } } - }); - }); + } + } // drill points to use center (average of all points) of the polygon drills.forEach(function(drill) {