Placement plan: table outline with dimension labels + table layer toggle

This commit is contained in:
2026-07-23 15:22:39 +10:00
parent e23c308249
commit d8c218c855
+18 -3
View File
@@ -36,7 +36,7 @@ const PAPER = { A4: [210, 297], A3: [297, 420] };
const MARGIN = 10; // mm printable margin
const OVERLAP = 10; // mm tile overlap for joining
const opts = { scale: '1', paper: 'A4', anchors: true, buildings: true, spawns: true, paths: true };
const opts = { scale: '1', paper: 'A4', table: true, anchors: true, buildings: true, spawns: true, paths: true };
document.getElementById('controls').innerHTML = `
<label>Scale <select id="scale">
@@ -46,13 +46,13 @@ document.getElementById('controls').innerHTML = `
<option value="fit">Fit one page</option>
</select></label>
<label>Paper <select id="paper"><option>A4</option><option>A3</option></select></label>
${['anchors','buildings','spawns','paths'].map(k =>
${['table','anchors','buildings','spawns','paths'].map(k =>
`<label><input type="checkbox" id="ly-${k}" checked> ${k}</label>`).join('')}
<span style="flex:1"></span>
<button class="primary" onclick="print()">Print…</button>
<span id="pgCount" style="opacity:.7;font-size:.85rem"></span>`;
['scale','paper'].forEach(id => document.getElementById(id).onchange = e => { opts[id] = e.target.value; build(); });
['anchors','buildings','spawns','paths'].forEach(k =>
['table','anchors','buildings','spawns','paths'].forEach(k =>
document.getElementById('ly-' + k).onchange = e => { opts[k] = e.target.checked; build(); });
// ---------- geometry ----------
@@ -62,6 +62,8 @@ function extent() {
minX = Math.min(minX, x - pad); maxX = Math.max(maxX, x + pad);
minZ = Math.min(minZ, z - pad); maxZ = Math.max(maxZ, z + pad);
};
const t = scene.table;
if (t && t.show !== false) { eat(t.offsetX || 0, t.offsetZ || 0, 6); eat((t.offsetX || 0) + t.width, (t.offsetZ || 0) + t.depth, 6); }
for (const a of scene.anchors || []) eat(a.position[0], a.position[2]);
for (const b of scene.buildings || []) eat(b.position[0], b.position[2], Math.max(b.size[0], b.size[2]) / 2 + 5);
for (const s of scene.spawns || []) eat(s.position[0], s.position[2]);
@@ -101,6 +103,19 @@ function planSVG(ex, k) {
<text y="-9.5" font-size="4" text-anchor="middle" font-weight="bold">N (+Z, back)</text>
<text y="13" font-size="3" text-anchor="middle" fill="#444">grid 10 cm</text></g>`;
if (opts.table && scene.table && scene.table.show !== false) {
const t = scene.table;
const x0 = t.offsetX || 0, z0 = t.offsetZ || 0;
const tx = X(x0), ty = Y(z0 + t.depth), tw = t.width * S, th = t.depth * S;
g += `<rect x="${px(tx)}" y="${px(ty)}" width="${px(tw)}" height="${px(th)}"
fill="none" stroke="#e67e00" stroke-width="0.7"/>`;
// dimension labels with arrows: width along the front (bottom) edge, depth along the left edge
g += `<text x="${px(tx + tw / 2)}" y="${px(ty + th + 5)}" font-size="4" text-anchor="middle" fill="#e67e00" font-weight="bold">← ${t.width} cm →</text>`;
g += `<text x="${px(tx - 3)}" y="${px(ty + th / 2)}" font-size="4" text-anchor="middle" fill="#e67e00" font-weight="bold"
transform="rotate(-90 ${px(tx - 3)} ${px(ty + th / 2)})">← ${t.depth} cm →</text>`;
g += `<text x="${px(tx + tw / 2)}" y="${px(ty - 2)}" font-size="3" text-anchor="middle" fill="#e67e00">TABLE ${t.width} × ${t.depth} cm — back edge (N)</text>`;
}
if (opts.paths) for (const p of scene.paths || []) {
const pts = (p.points || []);
if (pts.length < 2) continue;