From 174a026cc19f26c10e4c57eccfbb3ae4d4232fef Mon Sep 17 00:00:00 2001 From: ypshim Date: Fri, 23 Oct 2026 16:15:39 +0900 Subject: [PATCH] =?UTF-8?q?feat(view):=20dimension=20lines=20on=20the=20pl?= =?UTF-8?q?an=20=E2=80=94=20overall=20length=20and=20width,=20and=20the=20?= =?UTF-8?q?pile=20chains=20(=EB=81=9D=EB=8B=A8=20=EA=B1=B0=EB=A6=AC=20700,?= =?UTF-8?q?=20=EA=B0=84=EA=B2=A9=202250)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/view/footing-svg.ts | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/view/footing-svg.ts b/src/view/footing-svg.ts index 7cbfa5e..6e9306f 100644 --- a/src/view/footing-svg.ts +++ b/src/view/footing-svg.ts @@ -37,6 +37,27 @@ function svgOf(x0: number, y0: number, w: number, h: number, label: string, body return `${body}`; } +/** 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(``); } parts.push(``); - parts.push(`${mm(f.length)}`); - parts.push(`${mm(f.width)}`); + // 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('')); }