From 32cf01a29f3d82af6b335d98b39b976dcfc236bd Mon Sep 17 00:00:00 2001 From: ypshim Date: Mon, 26 Oct 2026 14:28:33 +0900 Subject: [PATCH] fix(rebar): section labels once per bar and spots once - The coping section listed every piece of a bar as its own crossing, so the same spot and name were drawn many times. Each spot is drawn once and each bar name is written once. Co-Authored-By: Claude Haiku 5.5 --- src/view/coping-rebar-svg.ts | 19 +++++++++++++++++-- tests/coping-rebar-svg.test.ts | 9 +++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/view/coping-rebar-svg.ts b/src/view/coping-rebar-svg.ts index 881f34e..450d6c8 100644 --- a/src/view/coping-rebar-svg.ts +++ b/src/view/coping-rebar-svg.ts @@ -55,9 +55,24 @@ export function copingSectionSvg(records: BarRecord[], s0: number): string { 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) }); } } - const xs = crossings.map((c) => c.x * 1000); + // The same bar is recorded in several pieces, so the same spot can be crossed more than once: draw each spot once, + // and write each bar name once (at its first crossing), so the labels do not pile up. + const seen = new Set(); + const named = new Set(); + const unique = crossings.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); + return true; + }); + const xs = unique.map((c) => c.x * 1000); const minX = Math.min(...xs, 0); const maxX = Math.max(...xs, 0); - const parts: string[] = crossings.map((c) => `${c.name}`); + const parts: string[] = unique.map((c) => { + const dot = ``; + if (named.has(c.name)) return dot; + named.add(c.name); + return `${dot}${c.name}`; + }); return `${parts.join('')}`; } diff --git a/tests/coping-rebar-svg.test.ts b/tests/coping-rebar-svg.test.ts index 87d5818..6a08fa8 100644 --- a/tests/coping-rebar-svg.test.ts +++ b/tests/coping-rebar-svg.test.ts @@ -32,3 +32,12 @@ describe('코핑 배근 정면 · 단면 (승인 2026-10-26)', () => { expect((svg.match(/ { + it('writes each bar name once, and each spot once', () => { + const svg = copingSectionSvg(scene.records, 6); + const labels = (svg.match(/]*>(C\d+) s.replace(/.*>/, ''))); + expect(labels).toBe(names.size); + }); +});