From 64539c63d6b434947d6fbc3fdb44e6cd065c0160 Mon Sep 17 00:00:00 2001 From: ypshim Date: Mon, 26 Oct 2026 15:09:38 +0900 Subject: [PATCH] =?UTF-8?q?feat(rebar):=20=EB=8B=A8=EB=A9=B4=C2=B7?= =?UTF-8?q?=ED=8F=90=ED=95=A9=20section=20shows=20only=20C1=E2=80=93C8=20a?= =?UTF-8?q?nd=20C12=C2=B7C13,=20with=20the=20top=20spacing=20labelled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Other bars (C9–C11, C14–C16) are left out of the section; bubbles only for C1–6, C7·8, C12·13. - The top-row chain carries the label 상면 간격. Co-Authored-By: Claude Haiku 5.5 --- src/view/coping-rebar-svg.ts | 13 +++++-------- tests/coping-rebar-svg.test.ts | 8 ++++++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/view/coping-rebar-svg.ts b/src/view/coping-rebar-svg.ts index aab646c..5844258 100644 --- a/src/view/coping-rebar-svg.ts +++ b/src/view/coping-rebar-svg.ts @@ -189,9 +189,11 @@ export function copingSectionSvg(records: BarRecord[], s0: number, copingTopEl?: crossings.push({ name: r.name, x: a[2] + (b[2] - a[2]) * t, y: a[1] + (b[1] - a[1]) * t, group: copingBarGroup(r.name) }); } } + // Only the top row (C1–C8) and the side rows (C12·C13) are shown in this section (승인 2026-10-26). + const shownGroups = new Set(['main', 'side']); // The same bar is recorded in several pieces, so draw each spot once. const seen = new Set(); - const unique = crossings.filter((c) => { + const unique = crossings.filter((c) => shownGroups.has(c.group)).filter((c) => { const key = `${Math.round(c.x * 1e4)}|${Math.round(c.y * 1e4)}|${c.name}`; if (seen.has(key)) return false; seen.add(key); @@ -219,6 +221,7 @@ export function copingSectionSvg(records: BarRecord[], s0: number, copingTopEl?: for (const d of topChain) { parts.push(`${d.text}`); } + parts.push(`상면 간격`); // 4: the side rows (C12·C13) along the EL, from the coping top EL down to the lowest side bar. const side = unique.filter((c) => c.group === 'side' && c.x < 0); @@ -234,14 +237,8 @@ export function copingSectionSvg(records: BarRecord[], s0: number, copingTopEl?: // 3 (bubbles): one bubble per bar group, with a leader to the centre of the group's crossings. const groupLabels: { label: string; names: string[] }[] = [ { label: 'C1–6', names: ['C1', 'C2', 'C3', 'C4', 'C5', 'C6'] }, - { label: 'C12·13', names: ['C12', 'C13'] }, - { label: 'C9', names: ['C9'] }, - { label: 'C10', names: ['C10'] }, - { label: 'C11', names: ['C11'] }, { label: 'C7·8', names: ['C7', 'C8'] }, - { label: 'C14', names: ['C14'] }, - { label: 'C15', names: ['C15'] }, - { label: 'C16', names: ['C16'] }, + { label: 'C12·13', names: ['C12', 'C13'] }, ]; for (const g of groupLabels) { const hit = unique.filter((c) => g.names.includes(c.name)); diff --git a/tests/coping-rebar-svg.test.ts b/tests/coping-rebar-svg.test.ts index 547a302..f6ec916 100644 --- a/tests/coping-rebar-svg.test.ts +++ b/tests/coping-rebar-svg.test.ts @@ -36,10 +36,14 @@ describe('코핑 배근 정면 · 단면 (승인 2026-10-26)', () => { describe('단면 · 폐합 글자 겹침 (승인 2026-10-26)', () => { it('writes each bubble label once', () => { const svg = copingSectionSvg(scene.records, 6, model.copingRefTop, model.copingB * 1000); - // A bubble is drawn for each group that is cut at this station, and only once. - for (const label of ['C1–6', 'C12·13', 'C10', 'C7·8', 'C14', 'C16']) { + // Only the top row and the side rows are shown here: their bubbles, once each. + for (const label of ['C1–6', 'C7·8', 'C12·13']) { expect(svg.split(`>${label}<`).length - 1).toBe(1); } + for (const label of ['C10', 'C14', 'C16']) { + expect(svg).not.toContain(`>${label}<`); + } + expect(svg).toContain('상면 간격'); }); });