add intra-top routing to minimize retractions when possible
This commit is contained in:
parent
e27aabc860
commit
5f36260772
5 changed files with 149 additions and 8 deletions
|
|
@ -471,7 +471,7 @@
|
|||
if (options.onfirst) {
|
||||
options.onfirst(point);
|
||||
}
|
||||
// move from startPoint to point
|
||||
// move to first output point on poly
|
||||
addOutput(output, point, 0, moveSpeed, tool);
|
||||
first = false;
|
||||
} else {
|
||||
|
|
@ -564,18 +564,134 @@
|
|||
}
|
||||
|
||||
function intersectsTop(p1, p2) {
|
||||
return retractRequired(p1, p2);
|
||||
let int = false;
|
||||
POLY.flatten(slice.topPolys().clone(true)).forEach(function(poly) {
|
||||
if (!int) poly.forEachSegment(function(s1, s2) {
|
||||
if (UTIL.intersect(p1,p2,s1,s2,BASE.key.SEGINT)) {
|
||||
int = true;
|
||||
return int;
|
||||
return int = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
return int;
|
||||
}
|
||||
|
||||
// returns true if no path around and retract required
|
||||
// returns false if routed around or no retract
|
||||
function retractRequired(p1, p2) {
|
||||
const dbug = false;
|
||||
|
||||
let ints = [];
|
||||
let tops = POLY.flatten(slice.topPolys().clone(true));
|
||||
for (let poly of tops) {
|
||||
poly.forEachSegment(function(s1, s2) {
|
||||
let ip = UTIL.intersect(p1,p2,s1,s2,BASE.key.SEGINT);
|
||||
if (ip) {
|
||||
ints.push({ip, poly});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// odd # of intersections ?!? do retraction
|
||||
if (ints.length && ints.length % 2 !== 0) {
|
||||
if (dbug === slice.index) console.log(slice.index, {odd_intersects: ints});
|
||||
return true;
|
||||
}
|
||||
|
||||
// sort by distance
|
||||
ints.sort((a, b) => {
|
||||
return a.ip.dist - b.ip.dist;
|
||||
});
|
||||
|
||||
let valid = ints.length;
|
||||
|
||||
// check pairs. eliminate too close points.
|
||||
// pairs must intersect same poly or retract.
|
||||
for (let i=0; i<ints.length; i += 2) {
|
||||
let i1 = ints[0];
|
||||
let i2 = ints[1];
|
||||
// different poly. force retract
|
||||
if (i1.poly !== i2.poly) {
|
||||
if (dbug === slice.index) console.log(slice.index, {int_diff_poly: ints, i});
|
||||
return true;
|
||||
}
|
||||
if (i1.ip.distTo2D(i2.ip) < retractDist) {
|
||||
if (dbug === slice.index) console.log(slice.index, {int_dist_too_small: i1.ip.distTo2D(i2.ip), retractDist});
|
||||
valid -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid > 2) {
|
||||
if (dbug === slice.index) console.log(slice.index, {complex_route: valid});
|
||||
return true;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
// can route around intersected top polys
|
||||
for (let i=0; i<ints.length; i += 2) {
|
||||
let i1 = ints[0];
|
||||
let i2 = ints[1];
|
||||
|
||||
// output first point
|
||||
addOutput(preout, i1.ip, 0, moveSpeed, extruder);
|
||||
|
||||
// create two loops around poly
|
||||
// find shortest of two paths and emit poly points
|
||||
let poly = i1.poly;
|
||||
let isCW = poly.isClockwise();
|
||||
let points = poly.points;
|
||||
|
||||
let p1p = isCW ? points : points.slice().reverse(); // CW
|
||||
let p2p = isCW ? points.slice().reverse() : points; // CCW
|
||||
|
||||
let r1s = p1p.indexOf(isCW ? i1.ip.p2 : i1.ip.p1);
|
||||
let r1e = p1p.indexOf(isCW ? i2.ip.p1 : i2.ip.p2);
|
||||
|
||||
let r1 = r1s === r1e ?
|
||||
[ p1p[r1s] ] : r1s < r1e ?
|
||||
[ ...p1p.slice(r1s,r1e+1) ] :
|
||||
[ ...p1p.slice(r1s), ...p1p.slice(0,r1e+1) ];
|
||||
|
||||
let r1d = 0;
|
||||
for (let i=1; i<r1.length; i++) {
|
||||
r1d += r1[i-1].distTo2D(r1[i]);
|
||||
}
|
||||
|
||||
let r2s = p2p.indexOf(isCW ? i1.ip.p1 : i1.ip.p2);
|
||||
let r2e = p2p.indexOf(isCW ? i2.ip.p2 : i2.ip.p1);
|
||||
|
||||
let r2 = r2s === r2e ?
|
||||
[ p2p[r2s] ] : r2s < r2e ?
|
||||
[ ...p2p.slice(r2s,r2e+1) ] :
|
||||
[ ...p2p.slice(r2s), ...p2p.slice(0,r2e+1) ];
|
||||
|
||||
let r2d = 0;
|
||||
for (let i=1; i<r2.length; i++) {
|
||||
r2d += r2[i-1].distTo2D(r2[i]);
|
||||
}
|
||||
|
||||
let route = r1d <= r2d ? r1 : r2;
|
||||
|
||||
if (dbug === slice.index) console.log(slice.index, {
|
||||
ints: ints.map(i=>i.ip.dist),
|
||||
i1, i2, same: i1.poly === i2.poly,
|
||||
route,
|
||||
r1, r1d, r1s, r1e,
|
||||
r2, r2d, r2s, r2e,
|
||||
isCW});
|
||||
|
||||
for (let p of route) {
|
||||
addOutput(preout, p, 0, moveSpeed, extruder);
|
||||
}
|
||||
|
||||
// output last point
|
||||
addOutput(preout, i2.ip, 0, moveSpeed, extruder);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function outputTraces(poly, opt = {}) {
|
||||
if (!poly) return;
|
||||
if (Array.isArray(poly)) {
|
||||
|
|
@ -631,8 +747,10 @@
|
|||
onfirst: function(firstPoint) {
|
||||
let from = seedPoint || startPoint;
|
||||
if (from.distTo2D(firstPoint) > retractDist) {
|
||||
if (intersectsTop(from, firstPoint)) {
|
||||
retract();
|
||||
}
|
||||
}
|
||||
seedPoint = null;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -119,6 +119,11 @@
|
|||
clearTimeout(int);
|
||||
}
|
||||
}, 50);
|
||||
// let slider = $('top-slider');
|
||||
// slider.style.display = 'flex';
|
||||
// slider.oninput = slider.onchange = (ev) => {
|
||||
// api.const.STACKS.setFraction(parseInt(ev.target.value)/100);
|
||||
// };
|
||||
});
|
||||
api.event.on("mode.set", mode => {
|
||||
isFdmMode = mode === 'FDM';
|
||||
|
|
|
|||
|
|
@ -587,6 +587,8 @@
|
|||
const headColor = 0x888888;
|
||||
const moveColor = opts.move >= 0 ? opts.move : 0xaaaaaa;
|
||||
const printColor = opts.print >= 0 ? opts.print : 0x777700;
|
||||
const arrowAll = false;
|
||||
const arrowSize = arrowAll ? 0.2 : 0.4;
|
||||
const layers = [];
|
||||
|
||||
const moveOpt = {
|
||||
|
|
@ -613,6 +615,7 @@
|
|||
let lastOut = null;
|
||||
let current = null;
|
||||
let retracted = false;
|
||||
let retractz = 0;
|
||||
|
||||
function color(point) {
|
||||
return FDM.rateToColor(point.speed, maxspd);
|
||||
|
|
@ -648,6 +651,7 @@
|
|||
if (out.retract) {
|
||||
retracts.push(out.point);
|
||||
retracted = true;
|
||||
retractz++;
|
||||
}
|
||||
if (!out.point) {
|
||||
// in cam mode, these are drilling or dwell ops
|
||||
|
|
@ -655,7 +659,7 @@
|
|||
}
|
||||
|
||||
if (lastOut) {
|
||||
if (lastOut.emit !== out.emit) {
|
||||
if (arrowAll || lastOut.emit !== out.emit) {
|
||||
heads.push({p1: lastOut.point, p2: out.point});
|
||||
}
|
||||
const op = out.point, lp = lastOut.point;
|
||||
|
|
@ -720,8 +724,8 @@
|
|||
const slope = p2.slopeTo(p1);
|
||||
const s1 = BASE.newSlopeFromAngle(slope.angle + 20);
|
||||
const s2 = BASE.newSlopeFromAngle(slope.angle - 20);
|
||||
const p3 = points.p2.projectOnSlope(s1, 0.8);
|
||||
const p4 = points.p2.projectOnSlope(s2, 0.8);
|
||||
const p3 = points.p2.projectOnSlope(s1, arrowSize);
|
||||
const p4 = points.p2.projectOnSlope(s2, arrowSize);
|
||||
return newPolygon().addPoints([p2,p3,p4]).setZ(p2.z + 0.01);
|
||||
}), { thin: true, outline: true });
|
||||
}
|
||||
|
|
@ -753,7 +757,7 @@
|
|||
|
||||
update(index / levels.length, output);
|
||||
});
|
||||
|
||||
console.log({retractz});
|
||||
return layers;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1244,6 +1244,17 @@ th, tr, td, label {
|
|||
width: 20px;
|
||||
}
|
||||
|
||||
#top-slider {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 60px;
|
||||
left: 50px;
|
||||
right: 50px;
|
||||
}
|
||||
#anim-slider {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#alert-area {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -461,6 +461,9 @@
|
|||
<div id="alert-text">alerts<br>alerts<br>alerts</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="top-slider" class="f-col grow">
|
||||
<input id="anim-slider" type="range" min="0" max="1000" value="0"></input>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in a new issue