checkpoint poly arc finding (for drilling op upgrade)
This commit is contained in:
parent
edf7a53d4c
commit
9f14ecf88a
3 changed files with 99 additions and 15 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<seq.length; pos++) {
|
||||
let next = util.circleCenter(...seq.slice(pos-3, pos));
|
||||
let prev = cand.peek();
|
||||
if (inside && !newPoint(next.x,next.y).inPolygon(this)) {
|
||||
// require point be inside current polygon
|
||||
next = null;
|
||||
}
|
||||
// console.log({ pos, next, prev, cand });
|
||||
if (next && !prev) {
|
||||
// seed candidate list
|
||||
cand.push(next);
|
||||
continue;
|
||||
}
|
||||
if (!next) {
|
||||
// next is a bust, reset candidate list
|
||||
cand.length = 0;
|
||||
continue;
|
||||
}
|
||||
// const dist = util.dist2D(next,prev);
|
||||
// console.log({ dist: dist.round(6) });
|
||||
if (util.dist2D(next,prev) < tolerance) {
|
||||
// add new candidate
|
||||
cand.push(next);
|
||||
continue;
|
||||
} else if (cand.length >= 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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue