feat(B06): 종단 구조물 표시를 B05 와 통일 — 같은 알약 레인

PLAN 2-5 (2026-09-07 사용자 지시 4 「구조물 표시 통일」). B06 종단에는 구조물 마크가
아예 없었고 배수관·세월교만 다른 계통으로 그려졌음.

- B05 가 쓰는 **같은 부품**(`buildStructureLane`)을 B06 종단 그래프 아래에 붙임.
  이름·중복 번호·툴팁·약호가 전부 B05 규칙 그대로 따라옴.
- 종단 차트가 `toX`(누가거리 → px)를 내보내 레인이 그래프와 같은 자리를 씀.
- 좌측 「구조물 배치」가 목록을 받을 때마다 `setStructureMarks` 로 넘김(구조물 정본 +
  관 정본). 관을 가상 구조물로 바꾸는 `pipesToStructureMarks` 는 B05 안에 있던 것을
  공용 자리(`B05_Profile_Api_Structures`)로 올려 **한 벌만** 둠.
- 알약을 누르면 그 자리에 가장 가까운 측점 카드를 고름(좌측 목록 클릭과 같은 규칙).
  끌기는 B05 몫이라 여기서는 자리만 보임(배수유역 재분할이 걸림).
- 검증 훅 `window.__b06Marks` 추가(`__corridorBuild` 등과 같은 용도).

자체검증 — 실화면 B06 종단에 레인 1줄·알약 10개(「배수관 1~8 · 세월교 1~2」)가 B05 와
같은 표기로 뜸. 훅 값 `{structures:10, types:36}`. tsc 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-07 08:20:59 +09:00
co-authored by Claude Opus 5
parent 6b76a3f273
commit 679726124b
5 changed files with 117 additions and 1 deletions
@@ -37,6 +37,8 @@ export interface LongitudinalChartResult {
axis: { padLeft: number; ticks: Array<{ y: number; label: string }> } | null;
/** 화면 x(px) → 누가거리(m). 스크롤 갱신이 보이는 구간을 다시 잴 때 쓴다. */
toChainage: (px: number) => number;
/** 누가거리(m) → 화면 x(px). 구조물 알약 레인이 그래프와 같은 자리를 쓰게 한다. */
toX: (chainageM: number) => number;
maxChainageM: number;
viewFromM: number;
viewToM: number;
@@ -78,6 +80,8 @@ export function buildLongitudinalChart(input: LongitudinalChartInput): Longitudi
const maxChainageM = longitudinalMaxChainage(detail.longitudinal);
const plotWidth = Math.max(1, input.chartWidth - LONG_PAD.left - LONG_PAD.right);
const toChainage = (px: number): number => ((px - LONG_PAD.left) / plotWidth) * maxChainageM;
const toX = (chainageM: number): number =>
LONG_PAD.left + (maxChainageM > 0 ? (chainageM / maxChainageM) * plotWidth : 0);
const { fromM, toM } = visibleChainageRange(
toChainage,
maxChainageM,
@@ -112,5 +116,5 @@ export function buildLongitudinalChart(input: LongitudinalChartInput): Longitudi
visibleElevationRange(detail, fromM, toM) ?? undefined,
),
);
return { node, axis, toChainage, maxChainageM, viewFromM: fromM, viewToM: toM };
return { node, axis, toChainage, toX, maxChainageM, viewFromM: fromM, viewToM: toM };
}