feat(view): dimension lines on the plan — overall length and width, and the pile chains (끝단 거리 700, 간격 2250)

The plan has overall dimension lines (length along the top, width at the right) and two chains: along the length, the
distances from the footing edge to the first pile and between piles; across the width, the same for the pile rows. The
chains are read from the pile positions, so they follow the layout.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-23 16:15:39 +09:00
1 parent 6050435af1
commit 174a026cc1
1 file changed
+32 -2
+32 -2
View File
@@ -37,6 +37,27 @@ function svgOf(x0: number, y0: number, w: number, h: number, label: string, body
return `<svg viewBox="${x0} ${y0} ${w} ${h}" width="${pw}" height="${ph}" role="img" aria-label="${label}">${body}</svg>`;
}
/** Distinct values (to 1 mm), sorted ascending. */
function uniq(values: number[]): number[] {
return [...new Set(values.map((v) => Math.round(v * 1000) / 1000))].sort((a, b) => a - b);
}
/**
* A chain of dimensions between the footing edges and the pile lines: from the edge to the first pile, between piles, and to the
* far edge. Horizontal when `horizontal` (at height y), otherwise vertical (at x = y argument).
*/
function chain(lines: number[], edgeA: number, edgeB: number, at: number, horizontal: boolean): string {
const pts = [edgeA, ...lines, edgeB];
return pts
.slice(0, -1)
.map((a, i) => {
const b = pts[i + 1];
const label = mm(Math.abs(b - a)).toString();
return horizontal ? dimH(a, b, at, label) : dimV(at, a, b, label);
})
.join('');
}
/** Plan view: the footing rectangle (length along the 교축, width across), the pile circles, the column circle, the axis. */
export function footingPlanSvg(model: PierModel): string {
const f = model.footings[0];
@@ -56,8 +77,17 @@ export function footingPlanSvg(model: PierModel): string {
parts.push(`<circle cx="${c.s}" cy="0" r="${c.diameter / 2}" fill="none" stroke="#0f5c66" stroke-width="0.03" stroke-dasharray="0.1 0.06"/>`);
}
parts.push(`<line x1="${x0}" y1="0" x2="${x0 + w}" y2="0" stroke="#b4531f" stroke-width="0.02" stroke-dasharray="0.3 0.1 0.05 0.1"/>`);
parts.push(`<text x="${f.s}" y="${-f.width / 2 - 0.35}" font-size="0.5" text-anchor="middle">${mm(f.length)}</text>`);
parts.push(`<text x="${f.s + f.length / 2 + 0.35}" y="0" font-size="0.5" text-anchor="start">${mm(f.width)}</text>`);
// Overall dimensions (전체 길이, 폭) and the pile chains (끝단 거리와 말뚝 간격), as in the 삽도 (승인 2026-10-23).
const left = f.s - f.length / 2;
const right = f.s + f.length / 2;
const top = -f.width / 2;
const bottom = f.width / 2;
parts.push(dimH(left, right, top - 0.9, String(mm(f.length))));
parts.push(dimV(right + 0.9, top, bottom, String(mm(f.width))));
const xs = uniq(piles.map((p) => p.s));
const ys = uniq(piles.map((p) => p.n));
parts.push(chain(xs, left, right, bottom + 0.8, true));
parts.push(chain(ys, top, bottom, left - 0.8, false));
return svgOf(x0, y0, w, h, '확대기초·말뚝 평면', parts.join(''));
}