# 스테이션바 측점거리(체이니지) 비례 축 전환 (B안)

**소요 시간**: 약 30분
**Context 사용량**: input ~150k / output ~14k tokens

## 결론
스테이션바 x축을 직전 A안(누적 이동거리) → **측점값(체이니지) 비례 축**으로 전환.
바 가로위치가 실제 측점거리에 비례하고, 커서는 드론의 현재 측점 위치를 표시한다(멈추면 정지, 후진하면 좌로 이동).
측점 10m 차이 구조물이 바에서도 가깝게 표시된다. 색: '진행색 + 커서색' 안 선택.

## 배경
- A안(누적 이동거리)은 두 구조물이 측점상 10m여도 그 사이 드론이 앞뒤로 많이 이동하면 누적거리가 커져 바에서 멀게 표시됨 → 사용자 지적.
- 요구: 바는 측점거리에 비례, 재생 중 실제 드론 위치를 바에 표시.

## 변경 내용 (client/src/stationbar/StationBar.tsx)
- `chainRef = {time, chain(평활), minC, maxC}` 생성(ready useEffect). chain 은 ±8프레임 이동평균(지터 제거).
- 매핑: `pxAtChain(측점) = START + clamp((c-minC)/(maxC-minC)) * timeTrackWidth`,
  `chainAtTime(t)`(이진탐색+보간), `pxAtTime(t) = pxAtChain(chainAtTime(t))`. 커서·구조물 공유.
- 커서: `progressPx = pxAtTime(currentTime)`, RAF 도 `pxAtTime(liveTime)`.
- 색(측점축은 방향 리본 표현 불가): `trackGradient`=주황 음영 단일, `trackGradientIdle`=회색 단일,
  `dividers=[]`. 방향은 `currentReverse`(측점값 0.4s 전 대비 감소=후진)로 커서 색만 구분.
- 구조물 중복 제거: `dedupeMarksByTitle`(title 당 1개) — 측점축에선 동명 다중통과가 한 자리에 겹침.
  → Timeline 다중통과 묶음 점선(브래킷)은 자연 소멸.
- seek: 클릭 px → 목표 측점 → 허용오차 내 프레임 중 현재 시간에 가장 가까운 통과로 onSeek.
- `barSegments` 는 렌더 미사용(쿼리 useMemo 는 kmLabels 위해 유지), `cumFracAtTime/timeAtFrac/progRef` 제거.

## 후속 수정 — 축 범위 '노선 고정' (데이터 무관 절대 측점)
- 문제: 축 범위를 드론 커버 구간 [minC,maxC] 로 잡아 영상마다 양끝 측점이 바뀜 → 같은 구조물이 다른
  위치/측점으로 표시됨(사용자 지적: "어떤 데이터로 재생하느냐에 따라 측점이 바뀌면 안돼").
- 수정:
  1. 축 범위 minC/maxC = stationLine(역 POI, km 오름차순) 첫/끝 측점값 → 노선 고정. 드론 chain 은
     projectChainage 로 이 범위 안에 들어옴.
  2. 구조물 px = pxAtChain(구조물 측점값) → 통과 시각이 아닌 '절대 측점'으로 배치(마일리지 라벨과 일치,
     영상 달라도 동일 위치). dedupeMarksByTitle 로 동명 1개.
- 효과: 좌(낮은 측점)→우(높은 측점) 고정 자. 구조물 위치 불변, 커서만 드론 현재 측점을 가리킴.

## 검증
- `tsc --noEmit` 통과 + client 빌드 완료.

## 알려진 한계 / 다음 단계
- 진짜 비례라 측점이 매우 가까운 라벨끼리 겹쳐 보일 수 있음(법동가도교/대전조차장역). 필요시 라벨 충돌회피 후처리.
- 방향 전진/후진 색 리본 제거됨(커서 색으로만 방향). endGapPx(미도착 종점역) 우측 밴드/표식은 유지.
- 이상 시 A안(누적거리 축) 또는 그 이전 시간선형으로 되돌릴 수 있음. 핵심 매핑은 pxAtChain/chainAtTime/pxAtTime 3개에 집중.
