improve gap routing. add adaptive shell fallback on failure
This commit is contained in:
parent
6c26dd0d81
commit
f53d6da12b
3 changed files with 42 additions and 13 deletions
|
|
@ -1323,15 +1323,15 @@ export class Polygon {
|
|||
pp2.pos = ip2;
|
||||
}
|
||||
});
|
||||
list.sort(function(p1, p2) {
|
||||
return util.distSq(lp1, p1) - util.distSq(lp1, p2);
|
||||
});
|
||||
if (deep && this.inner) {
|
||||
this.inner.forEach(p => {
|
||||
let ints = p.intersections(lp1, lp2);
|
||||
if (ints) list.appendAll(ints);
|
||||
});
|
||||
}
|
||||
list.sort(function(p1, p2) {
|
||||
return util.distSq(lp1, p1) - util.distSq(lp1, p2);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
@ -1392,6 +1392,23 @@ export class Polygon {
|
|||
return poly;
|
||||
}
|
||||
|
||||
/**
|
||||
* emit the shortest poly that connects two points on a closed CW poly
|
||||
* because traveling around the 'end point' may yield a shorter route.
|
||||
* if the poly is open, use emitSegment()
|
||||
*/
|
||||
emitShortestSegment(i1, i2) {
|
||||
if (this.open) {
|
||||
return this.emitSegment(i1, i2);
|
||||
}
|
||||
let start = i1.p2.pos,
|
||||
end = i2.p1.pos,
|
||||
points = this.points,
|
||||
seg0 = new Polygon([ i1, ...points.slice(start, end + 1), i2 ]).setOpen(),
|
||||
seg1 = new Polygon([ i2, ...points.slice(end +1 ), ...points.slice(0, start), i1 ]).setOpen();
|
||||
return seg0.perimeter() < seg1.perimeter() ? seg0 : seg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Polygon} poly
|
||||
* @param {number} [tolerance]
|
||||
|
|
|
|||
|
|
@ -487,6 +487,7 @@ function trace_noodle(noodle, noodleWidth, minR, midR, maxR, opt = {}) {
|
|||
// construct medial axis lines. this appears to produce duplicate
|
||||
// reverse segments in a subset of cases
|
||||
let ma = JSPoly.construct_medial_axis(out, inr);
|
||||
if (ma.length === 0) throw('cannot construct medial axis');
|
||||
// dedup the points so we can track them uniquely
|
||||
for (let { point0, point1 } of ma) {
|
||||
pointsToLine(point0, point1);
|
||||
|
|
@ -696,7 +697,8 @@ export function doTopShells(z, top, count, offset1, offsetN, fillOffset, opt = {
|
|||
if (dist < 1) p.open = false;
|
||||
} });
|
||||
let ret = { last, gaps };
|
||||
switch (opt.thinType) {
|
||||
let ttype = opt.thinType;
|
||||
switch (ttype) {
|
||||
case "legacy 1":
|
||||
ret = thin_type_1({ z, top, count, top_poly, offsetN, fillOffset });
|
||||
break;
|
||||
|
|
@ -704,13 +706,18 @@ export function doTopShells(z, top, count, offset1, offsetN, fillOffset, opt = {
|
|||
ret = thin_type_2({ z, top, count, top_poly, offset1, offsetN, fillOffset, gaps, wasm });
|
||||
break;
|
||||
case "adaptive":
|
||||
ret = thin_type_3({ z, top, count, offsetN });
|
||||
break;
|
||||
try {
|
||||
ret = thin_type_3({ z, top, count, offsetN });
|
||||
break;
|
||||
} catch (e) {
|
||||
console.log('adaptive layer failed. falling back to basic.', e);
|
||||
ttype = "basic";
|
||||
}
|
||||
case "basic":
|
||||
default:
|
||||
ret = offset_default({
|
||||
z, top, count, top_poly, offset1, offsetN, wasm,
|
||||
thin: opt.thinType === 'basic'
|
||||
thin: ttype === 'basic'
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -894,7 +894,7 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) {
|
|||
|
||||
// return true if move path from p1 to p2 intersects a
|
||||
// top and a path around the top (inside print) was not found
|
||||
function intersectsTop(p1, p2) {
|
||||
function requiresRetract(p1, p2) {
|
||||
if (slice.index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -919,15 +919,20 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) {
|
|||
if (dbug === slice.index) console.log(slice.index, {p1, p2, d: p1.distTo2D(p2)});
|
||||
|
||||
let ints = [];
|
||||
let intk = new Set();
|
||||
let tops = slice.topRouteFlat();
|
||||
for (let poly of tops) {
|
||||
poly.forEachSegment((s1, s2) => {
|
||||
let ip = util.intersect(p1,p2,s1,s2,base.key.SEGINT);
|
||||
if (ip) {
|
||||
if (ip) ip._key = undefined;
|
||||
if (ip && !intk.has(ip.key)) {
|
||||
ints.push({ip, poly});
|
||||
intk.add(ip.key);
|
||||
ip.p1.poly.hits = (ip.p1.poly.hits ?? 0) + 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
ints = ints.filter(i => i.poly.hits === 2);
|
||||
|
||||
// no intersections
|
||||
if (ints.length === 0) {
|
||||
|
|
@ -1101,7 +1106,7 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) {
|
|||
onfirst: (firstPoint, preout) => {
|
||||
let from = seedPoint || startPoint;
|
||||
if (from.distTo2D(firstPoint) > retractDist) {
|
||||
if (intersectsTop(from, firstPoint)) {
|
||||
if (requiresRetract(from, firstPoint)) {
|
||||
retract();
|
||||
}
|
||||
}
|
||||
|
|
@ -1183,7 +1188,7 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) {
|
|||
poly.forEachPoint((p, i) => {
|
||||
let dist = lp.distTo2D(p);
|
||||
let rdst = dist > retractDist;
|
||||
let itop = rdst && intersectsTop(lp,p);
|
||||
let itop = rdst && requiresRetract(lp,p);
|
||||
let emit = extrude;
|
||||
// retract if dist trigger and crosses a slice top polygon
|
||||
if (i === 0) {
|
||||
|
|
@ -1227,7 +1232,7 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) {
|
|||
}
|
||||
let first = points[0];
|
||||
let last = first;
|
||||
if (startPoint && startPoint.distTo2D(first) > thinWall && intersectsTop(startPoint, first)) {
|
||||
if (startPoint && startPoint.distTo2D(first) > thinWall && requiresRetract(startPoint, first)) {
|
||||
retract();
|
||||
}
|
||||
print.addOutput(preout, first, 0, moveSpeed, extruder);
|
||||
|
|
@ -1376,7 +1381,7 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) {
|
|||
print.addOutput(preout, p2, fill, fillSpeed, extruder);
|
||||
} else {
|
||||
// retract if dist trigger or crosses a slice top polygon
|
||||
if (!fast && dist > retractDist && (zhop || intersectsTop(startPoint, p1))) {
|
||||
if (!fast && dist > retractDist && (zhop || requiresRetract(startPoint, p1))) {
|
||||
retract();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue