try using xor to heal non-manifold / overlapping sliced polys. aka deathstar fix

This commit is contained in:
Stewart Allen 2024-07-13 16:51:22 -04:00
commit d7d136ad8c
5 changed files with 54 additions and 7 deletions

View file

@ -30,6 +30,7 @@ const POLY = polygons,
EndType = ClipperLib.EndType,
JoinType = ClipperLib.JoinType,
PolyTree = ClipperLib.PolyTree,
ClipXOR = ClipType.ctXor,
ClipDiff = ClipType.ctDifference,
ClipUnion = ClipType.ctUnion,
ClipIntersect = ClipType.ctIntersection,
@ -1769,9 +1770,30 @@ class Polygon {
if (clip.Execute(ClipDiff, tree, FillEvenOdd, FillEvenOdd)) {
poly = POLY.fromClipperTree(tree, poly.getZ());
poly.forEach(p => {
p.fillang = fillang;
})
poly.forEach(p => p.fillang = fillang);
return poly;
} else {
return null;
}
}
/**
* @param {Polygon} poly poly to xor against this one
* @returns {?Polygon[]}
*/
xor(poly) {
let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang,
clip = new Clipper(),
tree = new PolyTree(),
sp1 = this.toClipper(),
sp2 = poly.toClipper();
clip.AddPaths(sp1, PathSubject, true);
clip.AddPaths(sp2, PathClip, true);
if (clip.Execute(ClipXOR, tree, FillNonZero, FillNonZero)) {
poly = POLY.fromClipperTree(tree, poly.getZ());
poly.forEach(p => p.fillang = fillang);
return poly;
} else {
return null;

View file

@ -388,9 +388,21 @@ async function sliceZ(z, points, options = {}) {
if (groupFn) {
let groups = groupFn(lines, z, options);
if (options.union) {
let points = groups.map(p => p.length).reduce((a,b) => a + b);
// simplistic healing of non-manifold meshes
let opt = { x: 1 };
let union = POLY.union(POLY.nest(groups), 0.1, true, opt);
// fall back to xor'ing polygons that might overlap
// when one does not cleanly contain the other and we lose lots of points
// trigger when 2 polygons and we lose > 40% of points in the union
let delta = opt.changes < 0 ? Math.abs(opt.changes / points) : 0;
if (groups.length === 2 && delta >= 0.4) {
let xor = groups[0].xor(groups[1]);
console.log({ points, pct: (opt.changes / points).round(3), xor: xor.length });
if (xor.length) {
union = xor;
}
}
// track total poly length changes to determine if healed
rval.changes = opt.changes;
groups = POLY.flatten(union, null, true);
@ -749,7 +761,7 @@ function sliceConnect(input, z, opt = {}) {
emit(newPolygon().addPoints(array));
}
if (debug) console.log({ emitted });
if (debug) console.log({ emitted, output });
if (debug && emitted < points.length) console.log({ leftovers:points.length - emitted });
return output;

View file

@ -828,7 +828,13 @@ FDM.export = function(print, online, ondone, ondebug) {
}
// update time and distance (should calc in moveTo() instead)
time += (dist / speedMMM) * 60 * timeFactor;
if (dist && speedMMM) {
time += (dist / speedMMM) * 60 * timeFactor;
}
// if (isNaN(time)) {
// console.log({ layer, path, dist, speedMMM, timeFactor });
// throw "NaN";
// }
distance += dist;
subst.progress = progress = Math.round((distance / totaldistance) * 100);

View file

@ -323,7 +323,7 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
healed = true;
slice.changes = changes;
if (self.debug) {
console.log('slice healed', slice.index, slice.z);
console.log('slice healed', slice.index, slice.z, changes);
}
}
if (process.xray) {

View file

@ -264,6 +264,7 @@ class Print {
height = 0,
factor = 1,
tool = 0,
time = 0,
minf = Infinity,
maxf = 0,
seq = [],
@ -458,11 +459,13 @@ class Print {
(Math.pow(pos.X - lastPos.X, 2)) +
(Math.pow(pos.Y - lastPos.Y, 2))
);
// debug print time
time += (dV * pos.F) / 1000;
// filament per mm
let dR = (dE / dV);
if (dV > 2 && dE > 0.001) {
let lab = (absE ? 'aA' : 'rR')[scope.debugE++ % 2];
// console.log(lab, height.toFixed(2), dV.toFixed(2), dE.toFixed(3), dR.toFixed(4), pos.F.toFixed(0));
console.log(lab, height.toFixed(2), dV.toFixed(2), dE.toFixed(3), dR.toFixed(4), pos.F.toFixed(0));
}
}
// add point to current sequence
@ -578,6 +581,10 @@ class Print {
scope.maxSpeed = Math.floor(maxf / 60);
scope.belt = belt;
if (scope.debugE) {
console.log({ print_time: time.round(2) });
}
done({ output: scope.output });
}
}