feat(rebar): 단면·폐합 section shows only C1–C8 and C12·C13, with the top spacing labelled

- 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 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-26 15:09:38 +09:00
1 parent d5bf02e36b
commit 64539c63d6
2 files changed
+11 -10

No files matched your search

+5 -8
View File
@@ -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<string>();
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(`<line x1="${d.from}" y1="${dimTop}" x2="${d.to}" y2="${dimTop}" stroke="#18212B" stroke-width="8"></line><text x="${(d.from + d.to) / 2}" y="${dimTop - 90}" text-anchor="middle" font-size="160" fill="#18212B">${d.text}</text>`);
}
parts.push(`<text x="${(-halfW + halfW) / 2}" y="${dimTop - 260}" text-anchor="middle" font-size="150" fill="#55606E">상면 간격</text>`);
// 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));
+6 -2
View File
@@ -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('상면 간격');
});
});