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;
};
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
* 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());
if (dist < 1) p.open = false;
} });
let ret = { last, gaps };
switch (opt.thinType) {
case "type 1":
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);
// top.fill_lines.appendAll(centers);
}
ret = thin_type_1({ z, top, count, top_poly, offsetN, fillOffset });
break;
case "type 2":
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 = polys;
});
ret = thin_type_2({ z, top, count, top_poly, offset1, offsetN, fillOffset, gaps, wasm });
break;
default:
// 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;
}
}
}
}
}
);
ret = offset_default({ z, top, count, top_poly, offset1, offsetN, wasm });
break;
}
last = ret.last || last;
gaps = ret.gaps || gaps;
}
} else {
// no shells, just infill, is permitted

View file

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

View file

@ -296,6 +296,7 @@ kiri.Top.prototype.encode = function(state) {
};
if (state.full) {
// obj.gaps = encode(this.gaps, state);
obj.last = encode(this.last, state);
obj.shells = encode(this.shells, 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) {
let top = kiri.newTop(decode(v.poly, state));
if (state.full) {
// top.gaps = decode(v.gaps, state);
top.last = decode(v.last, state);
top.shells = decode(v.shells, state);
top.fill_off = decode(v.fill_off, state);

View file

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