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 v * v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return distance between two points
|
||||||
|
*/
|
||||||
|
function dist2D(p1, p2) {
|
||||||
|
return Math.sqrt(distSq(p1, p2));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return distance squared between two points
|
* return distance squared between two points
|
||||||
*/
|
*/
|
||||||
|
|
@ -569,6 +576,7 @@ base.util = {
|
||||||
pwait,
|
pwait,
|
||||||
ptimer,
|
ptimer,
|
||||||
flatten,
|
flatten,
|
||||||
|
dist2D,
|
||||||
distSq,
|
distSq,
|
||||||
distSqv2,
|
distSqv2,
|
||||||
center2d,
|
center2d,
|
||||||
|
|
@ -577,6 +585,7 @@ base.util = {
|
||||||
orderClosest,
|
orderClosest,
|
||||||
doCombinations,
|
doCombinations,
|
||||||
offsetPrecision,
|
offsetPrecision,
|
||||||
|
circleCenter,
|
||||||
numOrDefault,
|
numOrDefault,
|
||||||
thetaDiff,
|
thetaDiff,
|
||||||
intersect,
|
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
|
* @returns {Point} center of a polygon assuming it's a circle
|
||||||
*/
|
*/
|
||||||
circleCenter() {
|
calcCircleCenter() {
|
||||||
let pe = this.perimeter(),
|
let pe = this.perimeter(),
|
||||||
pe1 = pe / 3,
|
pe1 = pe / 3, // point 2
|
||||||
pe2 = pe1 * 2,
|
pe2 = pe1 * 2, // point 3
|
||||||
p = this.points,
|
p = this.points,
|
||||||
l = p.length,
|
l = p.length,
|
||||||
i = 1,
|
i = 1,
|
||||||
td = 0,
|
td = 0,
|
||||||
lp = p[0],
|
lp = p[0], // first point
|
||||||
ap = [ lp ];
|
ap = [ lp ]; // array of 3 points
|
||||||
while (i < l) {
|
while (i < l) {
|
||||||
let np = p[i++];
|
let np = p[i++];
|
||||||
let d = lp.distTo2D(np);
|
let d = lp.distTo2D(np);
|
||||||
|
|
@ -629,6 +631,67 @@ class Polygon {
|
||||||
return newPoint(center.x, center.y, p[0].z, null);
|
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
|
* 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
|
// for each slice, look for polygons with 98.5% circularity whose
|
||||||
// area is within the tolerance of a circle matching the tool diameter
|
// area is within the tolerance of a circle matching the tool diameter
|
||||||
tslices.forEach(function(slice) {
|
for (let slice of tslices) {
|
||||||
if (slice.z < zBottom) return;
|
if (slice.z < zBottom) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let inner = slice.topPolyInners([]);
|
let inner = slice.topPolyInners([]);
|
||||||
inner.forEach(function(poly) {
|
for (let poly of inner) {
|
||||||
if (poly.circularity() >= 0.985 && Math.abs(poly.area() - area) <= areaDelta) {
|
if (poly.circularity() >= 0.985 && Math.abs(poly.area() - area) <= areaDelta) {
|
||||||
let center = poly.circleCenter(),
|
let center = poly.calcCircleCenter(),
|
||||||
merged = false,
|
merged = false,
|
||||||
closest = Infinity,
|
closest = Infinity,
|
||||||
dist;
|
dist;
|
||||||
// TODO reject if inside camShellPolys (means there is material above)
|
// TODO reject if inside camShellPolys (means there is material above)
|
||||||
if (center.isInPolygon(slice.shadow)) return;
|
if (center.isInPolygon(slice.shadow)) {
|
||||||
drills.forEach(function(drill) {
|
continue;
|
||||||
if (merged) return;
|
}
|
||||||
|
for (let drill of drills) {
|
||||||
|
if (merged) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ((dist = drill.last().distTo2D(center)) <= centerDiff) {
|
if ((dist = drill.last().distTo2D(center)) <= centerDiff) {
|
||||||
merged = true;
|
merged = true;
|
||||||
drill.push(center);
|
drill.push(center);
|
||||||
}
|
}
|
||||||
closest = Math.min(closest,dist);
|
closest = Math.min(closest,dist);
|
||||||
});
|
}
|
||||||
if (!merged) {
|
if (!merged) {
|
||||||
drills.push(newPolygon().append(center));
|
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
|
// drill points to use center (average of all points) of the polygon
|
||||||
drills.forEach(function(drill) {
|
drills.forEach(function(drill) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue