try using xor to heal non-manifold / overlapping sliced polys. aka deathstar fix
This commit is contained in:
parent
cfa9eacbb2
commit
d7d136ad8c
5 changed files with 54 additions and 7 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue