move thin wall code into functions

This commit is contained in:
Stewart Allen 2025-02-23 09:55:20 -05:00
commit bf5f783c7a
4 changed files with 118 additions and 87 deletions

View file

@ -73,6 +73,96 @@ base.slicePost.FDM = function(data, options) {
delete data.groups; delete data.groups;
}; };
function offset_default(params) {
let { z, top, count, top_poly, offset1, offsetN, wasm, last, gaps } = params;
// standard wall offsetting strategy
POLY.offset(
top_poly,
[-offset1, -offsetN],
{
z,
wasm,
count,
outs: top.shells,
flat: true,
call: (polys, onCount) => {
last = polys;
// mark each poly with depth (offset #) starting at 0
for (let p of polys) {
p.depth = count - onCount;
if (p.fill_off) p.fill_off.forEach(function(pi) {
// use negative offset for inners
pi.depth = -(count - onCount);
});
// mark inner depth to match parent
if (p.inner) {
for (let pi of p.inner) {
pi.depth = p.depth;
}
}
}
}
}
);
return { last, gaps };
}
function thin_type_1(params) {
let { z, top, count, top_poly, offsetN, last, gaps } = params;
top.thin_fill = [];
top.fill_sparse = [];
let layers = POLY.inset(top_poly, offsetN, count, z, true);
last = layers.last().mid;
top.shells = layers.map(r => r.mid).flat();
top.gaps = layers.map(r => r.gap).flat();
let off = offsetN;
let min = off * 0.75;
let max = off * 4;
for (let poly of layers.map(r => r.gap).flat()) {
let centers = poly.centers(off/2, z, min, max, {lines:false});
top.fill_sparse.appendAll(centers);
}
return { last, gaps };
}
function thin_type_2(params) {
let { z, top, count, top_poly, offset1, offsetN, last, gaps, wasm } = params;
top.gaps = gaps;
top.thin_fill = [];
let oso = {z, count, gaps: [], outs: [], minArea: 0.05, wasm};
POLY.offset(top_poly, [-offset1, -offsetN], oso);
oso.outs.forEach((polys, i) => {
polys.forEach(p => {
p.depth = i;
if (p.fill_off) {
p.fill_off.forEach(pi => pi.depth = i);
}
if (p.inner) {
for (let pi of p.inner) {
pi.depth = p.depth;
}
}
top.shells.push(p);
});
last = polys;
});
// slice.solids.trimmed = slice.solids.trimmed || [];
oso.gaps.forEach((polys, i) => {
let off = (i == 0 ? offset1 : offsetN);
polys = POLY.offset(polys, -off * 0.8, {z, minArea: 0, wasm});
top.thin_fill.appendAll(cullIntersections(
fillArea(polys, 45, off/2, [], 0.01, off*2),
fillArea(polys, 135, off/2, [], 0.01, off*2),
));
gaps.push(...polys);
});
return { last, gaps };
}
/** /**
* may run in minion or worker context. performs shell offsetting * may run in minion or worker context. performs shell offsetting
* including thin wall detection when enabled * including thin wall detection when enabled
@ -112,87 +202,20 @@ FDM.doTopShells = function(z, top, count, offset1, offsetN, fillOffset, opt = {}
let dist = p.first().distTo2D(p.last()); let dist = p.first().distTo2D(p.last());
if (dist < 1) p.open = false; if (dist < 1) p.open = false;
} }); } });
let ret = { last, gaps };
switch (opt.thinType) { switch (opt.thinType) {
case "type 1": case "type 1":
top.thin_fill = []; ret = thin_type_1({ z, top, count, top_poly, offsetN, fillOffset });
top.fill_sparse = [];
let layers = POLY.inset(top_poly, offsetN, count, z, true);
last = layers.last().mid;
top.shells = layers.map(r => r.mid).flat();
top.gaps = layers.map(r => r.gap).flat();
let off = offsetN;
let min = off * 0.75;
let max = off * 4;
for (let poly of layers.map(r => r.gap).flat()) {
let centers = poly.centers(off/2, z, min, max, {lines:false});
top.fill_sparse.appendAll(centers);
// top.fill_lines.appendAll(centers);
}
break; break;
case "type 2": case "type 2":
top.thin_fill = []; ret = thin_type_2({ z, top, count, top_poly, offset1, offsetN, fillOffset, gaps, wasm });
let oso = {z, count, gaps: [], outs: [], minArea: 0.05, wasm};
POLY.offset(top_poly, [-offset1, -offsetN], oso);
oso.outs.forEach((polys, i) => {
polys.forEach(p => {
p.depth = i;
if (p.fill_off) {
p.fill_off.forEach(pi => pi.depth = i);
}
if (p.inner) {
for (let pi of p.inner) {
pi.depth = p.depth;
}
}
top.shells.push(p);
});
last = polys;
});
// slice.solids.trimmed = slice.solids.trimmed || [];
oso.gaps.forEach((polys, i) => {
let off = (i == 0 ? offset1 : offsetN);
polys = POLY.offset(polys, -off * 0.8, {z, minArea: 0, wasm});
top.thin_fill.appendAll(cullIntersections(
fillArea(polys, 45, off/2, [], 0.01, off*2),
fillArea(polys, 135, off/2, [], 0.01, off*2),
));
gaps = polys;
});
break; break;
default: default:
// standard wall offsetting strategy ret = offset_default({ z, top, count, top_poly, offset1, offsetN, wasm });
POLY.offset(
top_poly,
[-offset1, -offsetN],
{
z,
wasm,
count,
outs: top.shells,
flat: true,
call: (polys, onCount) => {
last = polys;
// mark each poly with depth (offset #) starting at 0
for (let p of polys) {
p.depth = count - onCount;
if (p.fill_off) p.fill_off.forEach(function(pi) {
// use negative offset for inners
pi.depth = -(count - onCount);
});
// mark inner depth to match parent
if (p.inner) {
for (let pi of p.inner) {
pi.depth = p.depth;
}
}
}
}
}
);
break; break;
} }
last = ret.last || last;
gaps = ret.gaps || gaps;
} }
} else { } else {
// no shells, just infill, is permitted // no shells, just infill, is permitted

View file

@ -1000,6 +1000,7 @@ function doRender(slice, isSynth, params, opt = {}) {
if (slice.tops) // missing for supports if (slice.tops) // missing for supports
slice.tops.forEach(top => { slice.tops.forEach(top => {
console.log({ render: top });
if (isThin) output if (isThin) output
.setLayer('part', Color.part) .setLayer('part', Color.part)
.addPolys([top.poly]); .addPolys([top.poly]);
@ -1024,7 +1025,7 @@ function doRender(slice, isSynth, params, opt = {}) {
.setLayer("thin fill", Color.thin) .setLayer("thin fill", Color.thin)
.addLines(top.thin_fill, vopt({ offset, height })); .addLines(top.thin_fill, vopt({ offset, height }));
if (top.gaps) output if (top.gaps && devel) output
.setLayer("gaps", Color.gaps) .setLayer("gaps", Color.gaps)
.addPolys(top.gaps, vopt({ offset, height, thin: true })); .addPolys(top.gaps, vopt({ offset, height, thin: true }));

View file

@ -296,6 +296,7 @@ kiri.Top.prototype.encode = function(state) {
}; };
if (state.full) { if (state.full) {
// obj.gaps = encode(this.gaps, state);
obj.last = encode(this.last, state); obj.last = encode(this.last, state);
obj.shells = encode(this.shells, state); obj.shells = encode(this.shells, state);
obj.fill_off = encode(this.fill_off, state); obj.fill_off = encode(this.fill_off, state);
@ -308,6 +309,7 @@ kiri.Top.prototype.encode = function(state) {
registerDecoder(TYPE.TOP, function(v, state) { registerDecoder(TYPE.TOP, function(v, state) {
let top = kiri.newTop(decode(v.poly, state)); let top = kiri.newTop(decode(v.poly, state));
if (state.full) { if (state.full) {
// top.gaps = decode(v.gaps, state);
top.last = decode(v.last, state); top.last = decode(v.last, state);
top.shells = decode(v.shells, state); top.shells = decode(v.shells, state);
top.fill_off = decode(v.fill_off, state); top.fill_off = decode(v.fill_off, state);

View file

@ -139,22 +139,27 @@ class Slice {
return this; return this;
} }
addTop(poly) { /**
if (poly.length) { * @param {Object | Polygon} data
* @returns Slice.Top
*/
addTop(data) {
if (data.length) {
// standard legacy polygon // standard legacy polygon
let top = new Top(poly); let top = new Top(data);
this.tops.push(top); this.tops.push(data);
top.simple = poly; top.simple = data;
return top; return top;
} else { } else {
// frop top object passed back by slicePost() // create top object from object bundle passed back by slicePost()
let top = new Top(poly.poly); let top = new Top(data.poly);
top.thin_fill = poly.thin_fill ? poly.thin_fill.map(p => base.newPoint(p.x,p.y,p.z)) : undefined; top.thin_fill = data.thin_fill ? data.thin_fill.map(p => base.newPoint(p.x,p.y,p.z)) : undefined;
top.fill_lines = poly.fill_lines; top.fill_lines = data.fill_lines;
top.fill_off = poly.fill_off; top.fill_off = data.fill_off;
top.last = poly.last; top.last = data.last;
top.shells = poly.shells; top.gaps = data.gaps;
top.simple = poly.simple; top.shells = data.shells;
top.simple = data.simple;
this.tops.push(top); this.tops.push(top);
return top; return top;
} }