wedges: tines follow the layer height -- a wedge's tines were always 0.2 tall with the 0.2 reach, a third of a 0.6 layer, which the slicer drops or merges (portal X45 at 0.6: 32 tines, now 0.6 tall)

This commit is contained in:
matthewtrahan authored and Matthew Trahan committed 2026-10-14 13:15:08 -05:00
1 parent 4a819355b3
commit 97c6c65b30
4 files changed
+36 -2

No files matched your search

+3
View File
@@ -359,6 +359,9 @@ reach-to-layer ratio brings thick layers back to the 0.2 count (228 / 220; buste
10). 0.2 and thinner are unchanged. The ends still kiss the surface; a thick layer's
tine top, snapped to the layer line, can sit up to half a layer above the underside,
above the mid-layer a slicer samples.
A wedge's tines follow the layer too: they were always 0.2 tall with the 0.2 reach, a
third of a 0.6 layer, which the slicer drops or merges (portal X45 at 0.6: 32 tines, all
0.2 tall, now 0.6).
### Wall lines
+27
View File
@@ -172,3 +172,30 @@ Deno.test('tines: a thick-layer tine is clear of the part at its mid-layer', asy
}
}
});
// A wedge's tines are one layer tall too (local issue 043's follow-up): they were
// always 0.2, a third of a 0.6 layer, which the slicer drops or merges. And like a
// wall's, each is clear of the part at its mid-layer, where the slicer reads it.
Deno.test('tines: a wedge tine is one layer tall and clear of the part at its mid-layer', async () => {
const { analyze } = await import('../web/overhangs.js');
const { buildFins } = await import('../web/fins.js');
const { loadModel, rotX } = await import('./_util.js');
const topo = loadModel('portal'), rot = rotX(45), res = analyze(topo, 45, rot);
for (const lh of [0.2, 0.6]) {
const b = buildFins(topo, res, rot, { mode: 'auto', bedPad: true, tines: true, layerHeight: lh });
// a tine is a small box; the wedge's blade and foot are not
const tines = b.fins.filter((f) => f.kind === 'wedge')
.flatMap((w) => w.triRanges.flatMap(([s, e]) => tineBoxes(b.triangles.slice(s, e)).tines))
.filter((t) => t.hi[2] - t.lo[2] < 1 && Math.max(t.hi[0] - t.lo[0], t.hi[1] - t.lo[1]) < 3);
assert(tines.length >= 10, `${lh}: portal X45 wedges have ${tines.length} tines`);
for (const t of tines) {
assertClose(t.hi[2] - t.lo[2], lh, 1e-6, `${lh}: a wedge tine is ${(t.hi[2] - t.lo[2]).toFixed(2)} tall`);
const mid = (t.lo[2] + t.hi[2]) / 2, cx = (t.lo[0] + t.hi[0]) / 2, cy = (t.lo[1] + t.hi[1]) / 2;
for (const v of t.verts.filter((q) => q[2] > t.hi[2] - 1e-6)) {
const dx = cx - v[0], dy = cy - v[1], d = Math.hypot(dx, dy) || 1;
assert(!insidePart(topo, rot, res.offset, v[0] + (dx / d) * 0.02, v[1] + (dy / d) * 0.02, mid),
`${lh}: a wedge tine top corner is inside the part at its mid-layer (z ${mid.toFixed(2)})`);
}
}
}
});
+2 -1
View File
@@ -236,7 +236,8 @@ function buildFinsCore(topo, result, rot, opts = {}) {
// (wedgeVeto).
const wedgeable = findWallPatches(topo, rot, result.offset).filter((p) =>
p.n.z < -0.05 && p.area >= PERP.minArea && (p.u1 - p.u0) >= PERP.minWidth);
const wedgeOpts = { tines: withTines, pitch: covPitch, tineDensity: opts.tineDensity };
const wedgeOpts = { tines: withTines, pitch: covPitch, tineDensity: opts.tineDensity,
layerHeight: opts.layerHeight };
const base = buildFinsCore(topo, result, rot, { ...opts, mode: 'prop', tines: withTines,
rasterVeto: wedgeVeto(wedgeable, topo, rot, result.offset, wedgeOpts) });
+4 -1
View File
@@ -317,7 +317,10 @@ export function buildPerpFins(p, topo, rot, offset, opts = {}) {
if (crest) emitCrest(crest, out);
partTris ??= seatedPartTris(topo, rot, offset);
emitFoot([top[0][0], top[0][1], 0], [top[top.length - 1][0], top[top.length - 1][1], 0], uDir, out, partTris);
if (opts.tines !== false) tineTotal += emitTines(contact, null, topo, rot, offset, out, tineStepFor(opts.tineDensity));
// a tine is one layer tall, as a wall's (prop.js): at 0.2 on a 0.6 layer the
// slicer drops it or merges it, and the reach grows with it (prop/tines.js)
if (opts.tines !== false) tineTotal += emitTines(contact, null, topo, rot, offset, out,
tineStepFor(opts.tineDensity), undefined, opts.layerHeight ?? PROP.tineH);
if (out.length > before) {
count++;
// One wedge = ring + foot + its tines, all pushed contiguously since