fix: 히스토리 검증 훅 UTF-8 강제 + 측점 맵핑 문서 추가
- guard-history-fields.py: Windows cp949 stdin에서 한글 필드 정규식 미스매치로 발생하던 false block 및 에러 mojibake 수정 (stdin/stderr UTF-8 강제) - docs/geo-station-mapping.html: 지리정보·측점·프레임 맵핑 구조 + station 기준 재생 설계 문서 - docs/history: 2026-06-17 맵핑 구조 분석 기록 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
69
docs/history/2026-06-17_지리정보-측점-프레임-맵핑구조-분석.md
Normal file
69
docs/history/2026-06-17_지리정보-측점-프레임-맵핑구조-분석.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# 지리정보 + 측점 + 프레임 맵핑 구조 분석
|
||||
|
||||
**작업일**: 2026-06-17
|
||||
**작업명**: 지리정보·측점·프레임 맵핑 구조 소스 분석 + station 기준 재생 HTML 문서화
|
||||
**소요 시간**: 18분
|
||||
**Context 사용량**: input 60k / output 8k tokens
|
||||
**이슈**: #0
|
||||
|
||||
---
|
||||
|
||||
## 목적
|
||||
|
||||
영상 프레임 ↔ 측점 ↔ 지리정보(POI/중심선)가 현재 소스에서 어떻게 맵핑되는지 코드 기반으로 파악. 추가로 "시간 기준이 아닌 station(측점) 기준 재생"을 위한 맵핑 구조를 HTML 문서로 출력.
|
||||
|
||||
## 분석 대상 파일
|
||||
|
||||
- [server/src/services/geoMatch.ts](../../server/src/services/geoMatch.ts) — 서버 투영/매칭 (평면근사 ENU)
|
||||
- [server/src/routes/geo.ts](../../server/src/routes/geo.ts) — geo API 엔드포인트
|
||||
- [client/src/utils/geoProjection.ts](../../client/src/utils/geoProjection.ts) — 클라 투영 (EPSG:5186 TM, Python advanced_tuner_v2.py 동일)
|
||||
- [client/src/components/overlay/StationOverlay.tsx](../../client/src/components/overlay/StationOverlay.tsx) — 실시간 캔버스 오버레이
|
||||
- [client/src/components/geo/StationVerify.tsx](../../client/src/components/geo/StationVerify.tsx) — 측점→프레임 점프 검증 패널
|
||||
- [client/src/components/player/VideoPlayer.tsx](../../client/src/components/player/VideoPlayer.tsx) — frame↔time 변환
|
||||
|
||||
## 핵심 결론
|
||||
|
||||
### 맵핑 키 = 프레임 번호
|
||||
- 드론 CSV의 `frame_cnt` = 영상 프레임 ↔ GPS+자세 연결고리
|
||||
- `time = frame / fps`
|
||||
- **fps 불일치 발견**: 클라 `VIDEO_FPS = 30000/1001 = 29.97`, 서버 `DEFAULT_FPS = 30`. seek는 frame번호 기반이라 실害 적으나 서버 `FrameMatch.time` 부정확.
|
||||
|
||||
### 데이터 소스 (GEO_DATA_DIR 기본 samplevideo/)
|
||||
1. `*회덕*.csv` — 드론 비행로그 (frame_cnt, lat, lon, alt, yaw, pitch, roll, focal_len)
|
||||
2. `building/*POI*위경도*.csv` — 지장물 (타원체고 버전 우선)
|
||||
3. `building/*측점*위경도*.csv` — 측점
|
||||
4. `pythonsource/input/center.csv` — 선로 중심선 224점 (타원체고 col5)
|
||||
5. `*.srt` — terrain offset (로드만, 거의 미사용)
|
||||
|
||||
### 투영 파이프라인
|
||||
```
|
||||
geo(lat,lon,z) → ENU world(m) → 카메라 상대벡터 → 회전(yaw/pitch/roll) → 핀홀 투영 px,py(0~1)
|
||||
```
|
||||
- 월드 원점 = **첫 측점** (측량 기준점), 드론 frame[0] 아님 → 드론 GPS 오차 회피
|
||||
- 서버/클라 투영 **구현 2벌** (서버=cos(lat) 평면근사, 클라=EPSG:5186 TM proj4) — 정밀도 차이
|
||||
|
||||
### 두 방향 질의
|
||||
- `findFramesForPoi(name)`: 측점명 → 전 프레임 투영 → FOV 안 → 연속구간 그룹화(GAP=30) → 구간별 중심 프레임. (StationVerify 점프)
|
||||
- `findPoisForFrame(n)`: 프레임 → 보이는 POI 목록.
|
||||
|
||||
### 클라 실시간 오버레이
|
||||
- idle time에 `Map<frameNum, {stationLabels, poiMarkers}>` 사전계산
|
||||
- RAF 루프: Map 조회 + frameNum→+1 보간 + EMA 스무딩 → canvas
|
||||
- 측점은 투영 전 가장 가까운 중심선 점에 스냅 (nearestCL, z도 중심선값)
|
||||
- smoothFrame: 드론 자세 ±N프레임 이동평균으로 GPS/IMU 노이즈 제거
|
||||
|
||||
### 측점 순서
|
||||
- `stationOrder`: title `\d+K\d+` 파싱 = km측점 ("12K345" = 12.345km). 서버/클라 동일 함수.
|
||||
|
||||
## Station 기준 재생 관점
|
||||
|
||||
현재 구조는 "시간(프레임) → 지리정보" 단방향 표시 중심. station 기준 재생 = **측점 → 대표 프레임 → seek** 역방향이 핵심.
|
||||
|
||||
- 이미 존재하는 빌딩블록: `findFramesForPoi` (측점→최적 프레임), `onSeekToFrame` (프레임→`currentTime(frame/fps)`).
|
||||
- station 기준 타임라인을 만들려면: 전 측점에 대해 `findFramesForPoi` 1회 일괄 호출 → 측점별 대표 프레임 테이블 구성 → km 순 정렬 → 측점 간 이동 = seek.
|
||||
- 산출물: 맵핑 구조 + station 기준 재생 설계를 정리한 HTML (`docs/geo-station-mapping.html`).
|
||||
|
||||
## 후속 참고
|
||||
- fps 불일치(30 vs 29.97) 정리 검토 가치 있음
|
||||
- 서버/클라 투영 알고리즘 통일 여부 결정 필요 (현재 클라가 정밀)
|
||||
- station 기준 재생용 측점→프레임 테이블 API(`/api/geo/station-index` 등) 신설 검토
|
||||
Reference in New Issue
Block a user