표고 체계 정비·설정 파일 단순화·선형 클리핑·시연 준비

- 타원체고 기준 자동 변환: route.json ellipsoidal_height 선언 시 드론 고도(CSV 정표고)를
  영상 메타(djmd 6.6 타원체고)와의 차(지오이드고 자동 산출)만큼 보정, 세그먼트 전환에도 유지
- KML 표고 파이프라인: 좌표 고도(z) 사용(POI/측점), *_byDem.kml 자동 생성(DEM 조회·높이 속성 포함)
  + 로더의 _byDem 우선 규칙, 선형중심선(LineString) 로딩·경로표고 앵커
- 설정 파일: camera.json/display.json/route.json 단순 이름 인식, 화면표시 옵션 PC 저장/자동 적용,
  초기화 버튼을 환경설정 파일 기준 복원으로 변경, 저장 파일명 단순화
- 선형 표시: 표출된 마지막 측점까지 클립(경계 세그먼트 절단 + 관통 현 처리 — 구간 실종 수정)
- 스테이션바: 시점(0k000) 마크(실통과 위치), 노선밖 프레임 통과 오인 방지, 커서 배지 1m 단위,
  배너 연장/소요 실측값(측점 체이니지·영상 길이 합) 우선
- 세그먼트 전환 라벨 깜빡임 구조 수정(캐시 초기화·최근접 키 조회·이중 재계산 제거) +
  사전계산 프레임 불변값 호이스팅(재생 지연 해소)
- UI: 슬라이더/값 입력칸 휠 조절, 패널 버튼 위치 정렬, 저장 버튼 중복 제거, dev_mode(route.json)로
  영상제어 UI 표시 제어, 지오이드 최대 200, 이격거리 측점 동반 적용
- 시연: start-demo.bat + docs/DEMO.md
- docs/history: 작업 이력 30건

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 20:37:46 +09:00
co-authored by Claude Fable 5
parent 84f4921826
commit 7d51ba9945
53 changed files with 1708 additions and 104 deletions
@@ -0,0 +1,19 @@
# 2026-07-09 오늘 개발분 전체 커밋
**소요 시간**: 2분
**Context 사용량**: input 880k / output 1k tokens
## 작업 내용
오늘 세션 전체 개발분을 main 에 커밋 (84f4921, 32파일 +1834/111):
- 제주 DJI 비행로그 어댑터, 분할영상 연속재생 + 영상목록 콤보
- KML 다중 병합(측점 71 + 지장물 신포맷 + 라벨 색상), 라벨 박스 스타일
- 카메라 자동감지(djmd) + camera.json PC 저장/자동 적용, Yaw 자동추정·드래그 역산
- 스테이션바 개선(이동거리 진행도, 노선밖 표기, 원거리 구조물 제외, 배지 한 줄)
- 서버 /api/camera 라우트, ecosystem(54000, 제주 경로), 히스토리 문서 21건
## 참고
- 원격(origin: gitea.hmac.kr/b23042/GhiVideo_v4)으로 push 는 하지 않음 — 요청 시 수행
- 이 히스토리 파일은 커밋 이후 생성분 (다음 커밋에 포함)
@@ -0,0 +1,21 @@
# 2026-07-09 push 시도 — 인증 차단 (사용자 조치 대기)
**소요 시간**: 2분
**Context 사용량**: input 900k / output 1k tokens
## 상황
`git push origin main` 실패: `could not read Username for 'https://gitea.hmac.kr'`
— WSL 환경에 credential helper / SSH 키 / .netrc 없음 (비대화형이라 암호 입력 불가).
## 사용자 안내
- 방법 A: 터미널에서 직접 `git push origin main` (대화형 인증)
- 방법 B: gitea 액세스 토큰(repository write) 발급 → 전달 시 push + credential store 설정
커밋 84f4921 은 로컬에 보존됨.
## 결과 (20:58 확인)
사용자가 직접 push 완료 — `main...origin/main` 동기화 확인(origin/main = 84f4921).
커밋 이후 생성된 히스토리 문서 2건은 untracked 상태로 다음 커밋에 포함 예정.
@@ -0,0 +1,18 @@
# 2026-07-09 두 KML 데이터 로드 범위 확인 (Q&A)
**소요 시간**: 2분
**Context 사용량**: input 920k / output 1k tokens
## 질문
제주_중산간도로.kml 과 제주_중산간도로_지장물.kml 데이터를 모두 읽어오는지.
## 답변 (코드 변경 없음)
- 두 파일 모두 병합 파싱됨 (다중 KML 병합은 지장물 KML 대응 때 구현)
- 중산간도로.kml: STA 측점 71개 사용 ✅ / 선형중심선 LineString 은 미사용(고도 0 —
측점 폴리라인으로 중심선 대체) / 5186_x/y 는 props 보관만
- 지장물.kml: 33개 전부 사용 ✅ (라벨+색상+좌표), 교량 3건 구조물 중복 등록,
타입상세·높이 등은 팝업 props
- 표시는 POI 표시범위(기본 1km) 이내만 — 뒷구간(3k~6k998) 측점이 재생 중 안 보이는 건 정상
- 확인 방법: 콘솔 `[KMZ] POI 33 · 구조물 3 · 측점 71 로드(원본)` 로그
@@ -0,0 +1,36 @@
# 2026-07-13 KML 선형중심선(LineString) 로딩
**소요 시간**: 8분
**Context 사용량**: input 950k / output 4k tokens
## 요청
제주_중산간도로.kml 로딩 — 측점(STA 71)·지장물은 이미 로딩 중이므로,
유일하게 미사용이던 **선형중심선(LineString)** 을 로딩해 사용.
## 수정 내용
### client/src/utils/geoData.ts
- `parseKmz`: Placemark 의 LineString 지오메트리를 중심선 폴리라인으로 수집
(연속 중복 정점 제거, 한국 범위 좌표만, 여러 개면 가장 긴 것). 반환에 `centerline` 추가
- `loadFolderGeoData`: 중심선 소스 우선순위 — **KML 선형중심선(146정점, 실제 도로 곡선)**
→ 없으면 기존 측점 폴리라인(100m 간격 직선 연결)
### client/src/components/overlay/StationOverlay.tsx
- 선형(중심선) 오버레이 투영 시 **표고 미상(z≤0) 정점을 '경로 표고' 평면에 앵커**
기존엔 z=0(해수면) 그대로 투영되어 실제 도로와 크게 어긋났음(측점/POI 라벨과 동일 기준으로 통일)
## 효과
- 선형 ON 시 곡선 구간에서 각지지 않는 실제 도로 선형 표시(146정점 vs 측점 71개 직선 연결)
- 측점 라벨 스냅(nearestCL)도 더 정밀한 선형 기준으로 동작
- 콘솔: `[KMZ] POI 33 · 구조물 3 · 측점 71 · 중심선 146점 로드(원본)` + `[geo] 중심선: KML 선형중심선 146점 사용`
## 검증
- tsc+vite 빌드 통과, 새 번들(index-Cc-unyK5.js) 서빙
- 참고: 폴더에 사용자가 저장한 DJI_20260629121835_0002.camera.json 확인됨 — 폴더 선택 시 자동 적용됨
## 다음 단계 참고
- 스테이션바의 체이니지 투영(stationLine)은 여전히 측점 기반(km 값 필요) — 변경 없음
@@ -0,0 +1,30 @@
# 2026-07-13 화면표시 옵션 PC 저장 + 폴더 자동 적용
**소요 시간**: 10분
**Context 사용량**: input 990k / output 5k tokens
## 작업 내용
camera.json 과 동일한 패턴으로 화면표시 옵션 저장/적용 왕복 구현.
### 저장 — StationOverlay 화면표시 옵션 패널 헤더 [PC에 저장] 버튼
`<영상 base>.display.json` 다운로드. 포함 항목:
- 슬라이더: dronePathZ(경로표고), dronePathAlpha(투명도), smoothHalf, emaAlpha,
smoothMinAlpha(떨림억제), smoothSpeedRef(반응속도), maxPoiRange(POI 범위), droneHeightDrop(이격거리)
- 토글: poiDroneHeight(드론높이 모드), showCenterline(선형), showDronePath(드론궤적),
showRoutePanel(좌측 패널), poiOverlapExclude(겹침제외)
- 기타: compassType/compassMapStyle(나침반), gradeFilter(시설등급 체크)
### 로드 — 폴더 선택 시 자동 적용
- `parseDisplayJson`(geoData): `<영상 base>.display.json` 인식(분할본 base 아무거나 매칭)
- geoStore `displayJson` 적재 → StationOverlay effect 가 타입 검증 후 각 상태/설정스토어에 반영
(localStorage 복원 effect 뒤에 선언 — 파일 값이 우선)
## 검증
- tsc+vite 빌드 통과, 새 번들(index-D6YhUPvg.js) 서빙
## 다음 단계 참고
- camera.json(카메라 내부표정)과 display.json(화면표시)은 별개 파일 — 둘 다 폴더에 두면 각각 적용
- 저장 파일은 다운로드 폴더에 생성 → 영상 폴더로 이동 필요(브라우저 보안 제약)
@@ -0,0 +1,29 @@
# 2026-07-13 측점 라벨 투영 수정 + 스테이션바 시점 마크
**소요 시간**: 10분
**Context 사용량**: input 1030k / output 5k tokens
## 문제 1 (스크린샷 제보) — 0k000·0k100 다음에 바로 0k800 이 보임
### 원인
직전 작업(KML 선형중심선 로딩)의 부작용. 측점 라벨은 중심선의 **최근접 '정점'에 스냅**되는데
(nearestCL), 기존 중심선(측점 71개 자신)에선 자기 위치였지만, LineString 중심선은 CAD 유래라
**직선 구간 정점이 성김** → 직선 구간 측점들이 굽이 정점으로 뭉쳐 스냅됨.
실측 오차: 0k200=23m, 0k400=223m, **0k600=422m**.
### 수정 — StationOverlay.tsx
- `projectCL` 신설: 중심선 **세그먼트 투영**(선 위의 정확한 최근접점, z 는 선형보간)
- 측점 라벨 스냅을 nearestCL(정점) → projectCL(투영) 로 교체. 투영 오차 0.02m 로 개선
- POI 지면고도(gz) 조회는 기존 nearestCL(z 참조용) 유지
## 문제 2 (요청) — 스테이션바에 시점(0k000) 값·위치 표시
### 수정 — StationBar.tsx
- structureMarks 에 `appendStartMark` 추가: 첫 측점(최소 stationKm, 예: 0k000)의
통과 지점(pxPassesAtMileage)에 카테고리 '측점' 마크 push → Timeline 이 측점값 라벨
("0k000") 을 해당 위치에 표시. 구조물 경로/폴백 경로 양쪽 반영
- 노선 진입 전 구간에선 통과가 없으므로 표시 안 됨(정상), 진입 시점 위치에 표시됨
## 검증
- 정점 스냅 vs 투영 오차 실측(위 수치), tsc+vite 빌드 통과, 새 번들(index-B6hy7ai4.js) 서빙
@@ -0,0 +1,27 @@
# 2026-07-13 시점(0k000) 마크 실제 통과 위치로 수정
**소요 시간**: 5분
**Context 사용량**: input 1080k / output 3k tokens
## 문제 (스크린샷 제보)
시점(0k000) 마크가 스테이션바 맨 왼쪽(t=0)에 표시됨 — 실제 0k000 통과 위치(약 84초 지점)에
표시되어야 함.
## 원인
접근 구간(첫 87초)은 노선 밖이라 체이니지가 시작점 0 으로 클램프됨 →
`pxPassesAtMileage(0)` 이 접근 구간 전체를 "0k000 통과"로 오인하고, 최초 프레임(t=0)을
최근접으로 선택해 바 맨 앞에 마크가 찍힘.
## 수정 — client/src/stationbar/StationBar.tsx
- `pxPassesAtMileage` 에서 **노선 밖 프레임(offM > OFF_ROUTE_M=60m) 을 통과 후보에서 제외**
(탐색 시작·연속 구간 판정 모두). 직전 작업에서 추가한 ViewedPoint.offM 활용
- 부수 효과: 측점값 기반 다른 마크(구조물 이정 폴백 등)도 접근/이탈 구간 오인 방지
## 검증
- 실데이터 시뮬레이션: 수정 후 0k000 마크 = t=83.8s 지점 (기존 t=0s)
— 드론이 실제로 0k000 에 도달하는 시점과 일치
- tsc+vite 빌드 통과, 새 번들(index-DmRp0Sle.js) 서빙
@@ -0,0 +1,25 @@
# 2026-07-13 속성 JSON 폴더 공용 인식 + 시점 라벨 간소화
**소요 시간**: 6분
**Context 사용량**: input 1130k / output 3k tokens
## 요청 1 — 속성 json 을 같은 폴더의 모든 영상에 동일 적용
사용자가 json 을 영상 이름이 아닌 폴더 공용 이름("제주 중산간도로 경로 1-1.camera.json" /
".display.json")으로 관리 — 기존 로더는 영상 base 매칭만 인식해 무시됨.
### 수정 — client/src/utils/geoData.ts
- `parseCameraJson`: ① `<영상 base>.camera.json`/`<영상 base>.json` 우선 → ② **임의 이름의
`*.camera.json` 폴백**. rootJson 필터에서 .display.json 제외 추가
- `parseDisplayJson`: ① `<영상 base>.display.json` 우선 → ② **임의 이름의 `*.display.json` 폴백**
- 두 파일 모두 폴더 공용 — 분할본 4개 전체에 동일 적용(원래 적용 자체가 폴더 단위)
- 실파일명 목록으로 매칭 검증 완료
## 요청 2 — 시점 마크 하단 텍스트 중복 제거
- 시점 마크의 측점값 라벨(위)이 이미 "0k000" 표시 → 제목(아래)을 "0k000 (시점)" 에서
**"시점"** 으로 변경 (StationBar appendStartMark)
## 검증
- tsc+vite 빌드 통과, 새 번들(index-D4SFb-vJ.js) 서빙
@@ -0,0 +1,14 @@
# 2026-07-13 화면표시 옵션 저장 기능 확인·안내 (Q&A)
**소요 시간**: 2분
**Context 사용량**: input 1180k / output 1k tokens
## 내용 (코드 변경 없음)
화면표시 옵션 저장 요청 — 이미 구현됨(2026-07-13_1010 작업):
- 저장: 화면표시 옵션 패널 헤더 [PC에 저장] → `*.display.json`
- 적용: 폴더 선택 시 자동 (임의 이름 `*.display.json` 인식은 1024 작업에서 확장)
폴더 실파일 확인: "제주 중산간도로 경로 1-1.display.json" (사용자가 오늘 10:20 저장) 형식 정상 —
경로표고 58/선형 ON/궤적 ON/등급 1·2종 등. camera.json(Yaw 16.3, f 29.9)도 정상.
사용 방법 안내로 마무리.
@@ -0,0 +1,30 @@
# 2026-07-13 라벨 사전계산 최적화 + 패널 버튼 위치 교환
**소요 시간**: 12분
**Context 사용량**: input 1230k / output 6k tokens
## 문제 1 — 재생 느려짐·딜레이·POI 라벨 깜빡임 (제보)
### 원인
오늘 추가한 측점 세그먼트 투영(projectCL)이 라벨 사전계산의 **프레임 루프 안**에서 실행 —
측점 71 × 선분 145 × 프레임 1947 ≈ 2천만 반복. POI 지면고도(gz: nearestCL 146정점 × POI 33)도
프레임마다 반복. 재생 중 requestIdleCallback 청크가 timeout(200ms)으로 강제 실행될 때마다
메인 스레드를 수십 ms 점유 → 영상 버벅임·딜레이·라벨 위치 갱신 밀림(깜빡임처럼 보임).
### 수정 — StationOverlay.tsx startLabelPrecompute
- 측점 투영(snappedSt)과 POI 지면고도(gzOf)는 **프레임 불변** → 사전계산 시작 시 1회만 계산,
프레임 루프에서는 조회만. 프레임당 지오메트리 연산 ~15,000회 → 0회
## 문제 2 — 패널 토글 버튼 위치가 창과 반대 (요청)
- 패널은 flex-row-reverse 라 화면표시=오른쪽, 카메라=왼쪽인데 버튼은 반대 순서였음
- 버튼 순서를 [카메라 파라미터][화면표시 옵션] 으로 교환 — 버튼과 패널 위치 일치
## 문제 3 — 카메라 파라미터 저장 (요청)
- 이미 존재(내부표정 📷 줄 [PC에 저장])하나 찾기 어려움 → **카메라 패널 헤더(자세 보정 오프셋 행)
우측에도 [PC에 저장] 배치** — 화면표시 옵션 패널과 동일한 위치·스타일
## 검증
- tsc+vite 빌드 통과, 새 번들(index-CYjWswA1.js) 서빙
@@ -0,0 +1,25 @@
# 2026-07-13 이격거리 조절 시 측점 라벨 동일 적용
**소요 시간**: 5분
**Context 사용량**: input 1290k / output 2k tokens
## 문제 (요청)
'드론 높이와 POI 이격거리' 조절이 POI 라벨에만 반영되고 측점(스테이션) 라벨은 고정 표고로
투영되어 함께 움직이지 않음.
## 수정 — client/src/components/overlay/StationOverlay.tsx
- RAF 측점 라벨 드로우: 드론높이 모드(poiDroneHeight=true)면 POI 와 동일하게
`드론고도 − 지오이드 − 이격거리` 평면에 투영. 지면고도 모드면 기존 저장 표고(stA.z) 유지
- 사전계산의 측점 가시성 판정도 같은 높이 규칙으로 통일 (이격거리/모드 변경 시
재계산은 기존 deps 로 이미 트리거됨)
## 동작
- 드론높이 모드 ON + 이격거리 슬라이더 조절 → POI·측점 라벨이 함께 위아래로 이동
- 지면고도 모드(기본) → 기존대로 경로표고 앵커(측점)·gz(POI) 사용, 이격거리 무관
## 검증
- tsc+vite 빌드 통과, 새 번들(index-DOYzU1-r.js) 서빙
@@ -0,0 +1,22 @@
# 2026-07-13 슬라이더 마우스 휠 조절
**소요 시간**: 4분
**Context 사용량**: input 1340k / output 2k tokens
## 요청
슬라이더 바 위에서 휠 위 = 증가, 휠 아래 = 감소 (0.1 단위).
## 수정 — StationOverlay.tsx ParamRow
- range 슬라이더에 휠 핸들러: 위 = +step, 아래 = step (min/max 클램프,
표시 자릿수 반올림으로 부동소수점 누적 오차 방지)
- 각 슬라이더의 step 단위 적용 — 카메라 파라미터(Yaw±/Pitch±/f 등)는 0.1,
정수 슬라이더(경로표고/이격거리 등)는 1, 정밀 슬라이더(반응속도)는 0.001
- 패널 스크롤과 충돌 방지: non-passive 네이티브 wheel 리스너로 preventDefault
(React onWheel 은 passive 라 스크롤 차단 불가)
- 모든 ParamRow(카메라 파라미터·화면표시 옵션·표고 z) 공통 적용
## 검증
- tsc+vite 빌드 통과, 새 번들(index-LzJdmqNA.js) 서빙
@@ -0,0 +1,23 @@
# 2026-07-13 측점을 드론높이/이격거리 적용에서 제외
**소요 시간**: 3분
**Context 사용량**: input 1390k / output 1k tokens
## 요청
측점(KML)은 '경로 표고' 슬라이더로 이미 높이가 제어되므로, '드론 높이와 POI 이격거리'
옵션 적용 대상에서 제외 (직전 1045 작업의 측점 적용을 되돌림).
## 수정 — StationOverlay.tsx
- RAF 측점 드로우: 드론높이 모드 분기 제거 → 항상 stA.z(경로표고 앵커) 사용
- 사전계산 측점 가시성 판정: 동일하게 sz(경로표고 앵커)로 복원
## 결과 — 높이 제어 체계
- **측점 라벨·드론 궤적·선형**: '경로 표고' 슬라이더
- **POI(지장물) 라벨**: 지면고도 모드 = 경로표고 앵커(gz) / 드론높이 모드 = 드론고도 − 이격거리
## 검증
- tsc+vite 빌드 통과, 새 번들(index-DsT-6KME.js) 서빙
@@ -0,0 +1,15 @@
# 2026-07-13 지오이드 최대 200 + 휠 조절 값 입력칸 확장
**소요 시간**: 3분
**Context 사용량**: input 1440k / output 1k tokens
## 요청 2건 — StationOverlay.tsx
1. **지오이드 슬라이더 최대값 50 → 200** (ParamRow max)
2. **휠 조절을 숫자 값 입력칸 위에서도 동작**: ParamRow 의 non-passive wheel 리스너를
range 슬라이더 + number 입력칸 양쪽에 부착 (위=+step, 아래=step, min/max 클램프,
브라우저 기본 number 휠 동작/패널 스크롤 차단)
## 검증
- tsc+vite 빌드 통과, 새 번들(index-DTzX7VJi.js) 서빙
@@ -0,0 +1,36 @@
# 2026-07-13 두 번째 영상 POI 깜빡임 — 구조적 원인 3건 제거
**소요 시간**: 15분
**Context 사용량**: input 1500k / output 6k tokens
## 문제 (제보)
두 번째 영상(세그먼트 2) 재생 시 POI 라벨 깜빡임. 부하/불필요 동작 점검 요청.
## 원인 3건 + 수정 — StationOverlay.tsx
### 1. 세그먼트 전환 시 이전 세그먼트 캐시 혼재 (핵심)
- 라벨 사전계산이 "옛 맵 복사 후 덮어쓰기" 방식 — 세그먼트 전환 시 **이전 세그먼트의 캐시**
(같은 프레임 번호, 다른 위치)가 남은 채 청크가 도착할 때까지 신·구 항목이 섞여
라벨 집합이 프레임마다 뒤바뀜(깜빡임)
- 수정: frames 참조가 바뀌면(전환) 복사 없이 **빈 맵으로 시작** + labelMapRef 즉시 교체.
같은 데이터의 재계산(슬라이더 변경)만 기존처럼 복사
### 2. 캐시 조회의 정확일치/스테일 폴백 교대
- 조회가 `floor(estFrame) 정확일치 ?? currentFrameNumRef(4Hz 갱신 스테일 키)` — 60fps 중
~1/6 프레임은 정확일치, 나머지는 최대 250ms 뒤처진 폴백 키 → **서로 다른 캐시 항목을
교대로 그려** 이동 중 경계 POI 가 깜빡임
- 수정: 캐시 키 배열(labelKeysRef, 오름차순)을 두고 **최근접 키 이진탐색**으로 조회 고정
(채워지는 중엔 인접 ±3 키 폴백)
### 3. 전환 시 사전계산 이중 실행 (불필요 부하)
- storeFrames 가 즉시 effect·디바운스 effect 양쪽 deps 에 있어 전환마다 풀 재계산 2회
- 수정: 디바운스 effect 에서 storeFrames 제거(즉시 effect 전담)
### 보조
- 프레임 ingest 시 currentFrameIdx/NumRef 초기화 — 전환 직후 사전계산 시작 구간이
이전 세그먼트 끝 인덱스(스테일)로 잡히는 것 방지
## 검증
- tsc+vite 빌드 통과, 새 번들(index-1zg4kXAW.js) 서빙
@@ -0,0 +1,23 @@
# 2026-07-13 선형 측점 범위 클리핑 + 배너 연장/소요 실측값
**소요 시간**: 8분
**Context 사용량**: input 1560k / output 4k tokens
## 요청 1 — 측점 연장선(빨간 선형)을 표출된 측점 POI 까지만
- StationOverlay buildLines: 중심선 세그먼트를 **측점 라벨 표시 반경(maxPoiRange)과 동일하게
클리핑** — 양 끝점 모두 반경 밖이면 그리지 않음(한쪽이라도 안이면 그려 경계에서 자연스럽게 끊김)
- 라벨 없는 원거리 구간이 수평선까지 길게 그려지던 것 해소. 'POI 범위' 슬라이더로 함께 조절됨
## 요청 2 — 좌상단 배너 연장/소요를 데이터 실측값으로
- RouteInfoOverlay 우선순위 변경:
- **연장**: 측점 데이터(KML STA 전체 체이니지 min~max) 우선 → route.json 폴백
(제주: 0~6998m → 7.0km. 기존 route.json 4.25 대신 실측)
- **소요**: 폴더 내 영상 전체 길이 합(geoStore.videoDurations, 분할본 4개 합 671.7s ≈ 11분 12초)
우선 → route.json → 현재 영상 길이
- route.json 에 값이 있어도 데이터 실측값이 우선 표시됨(데이터 없을 때만 route.json 사용)
## 검증
- tsc+vite 빌드 통과, 새 번들(index-BQeIVPjw.js) 서빙
@@ -0,0 +1,20 @@
# 2026-07-13 선형을 마지막 표출 측점까지로 클립
**소요 시간**: 4분
**Context 사용량**: input 1620k / output 2k tokens
## 문제 (스크린샷 제보)
라벨은 0k800 까지인데 빨간 선형이 그 너머(표시 반경 1km 끝)까지 이어짐 —
직전 수정이 '반경' 기준이라 마지막 라벨~1km 사이의 라벨 없는 꼬리가 남았음.
## 수정 — StationOverlay.tsx buildLines
- 클립 기준을 반경(maxPoiRange) → **표시 반경 안에 들어온 측점 중 최원거리 + 20m** 로 변경
(매 프레임 측점 71개 수평거리 스캔 — 비용 무시 가능)
- 측점이 하나도 반경 안에 없으면 기존 반경 클립 폴백
## 검증
- tsc+vite 빌드 통과, 새 번들(index-DshfapxL.js) 서빙
- 기하 검증: 스크린샷 상황(드론 ~0k000 부근, 0k900 이 1km 밖) → clipR ≈ 820m → 0k800 직후 선 종료
@@ -0,0 +1,26 @@
# 2026-07-13 초기화 버튼 — 환경설정 파일 기준 복원
**소요 시간**: 4분
**Context 사용량**: input 1680k / output 2k tokens
## 요청
초기화 버튼이 앱 기본값이 아니라 환경설정 파일(폴더의 *.camera.json / *.display.json)
값으로 복원되도록.
## 수정 — StationOverlay.tsx
- **카메라 파라미터 [초기화]**: `resetCameraParams` 신설 — 폴더에 *.camera.json 있으면
기본값 위에 파일 값을 덮어 복원, 없으면 DEFAULT_CAMERA_PARAMS (파일에 없는 키는 기본값)
- **화면표시 옵션 [기본값]**: `resetDisplayDefaults` 를 동일 패턴으로 변경 —
*.display.json 있으면 파일 값(타입 검증), 없으면 DISPLAY_DEFAULTS
- 두 버튼 title 에 동작 설명 추가
## 동작 정리
- 슬라이더를 만지작거리다 [초기화]/[기본값] → 저장해 둔 환경설정 파일 상태로 복귀
- 파일이 없는 폴더 → 기존처럼 앱 기본값 복귀
## 검증
- tsc+vite 빌드 통과, 새 번들(index-Cx5R9huP.js) 서빙
@@ -0,0 +1,18 @@
# 2026-07-13 커서 배지 측점값 1m 단위 갱신
**소요 시간**: 3분
**Context 사용량**: input 1730k / output 1k tokens
## 요청
노선밖 구간 배지는 1m 단위("노선밖 346m")인데 노선 진입 후 측점값은 10m 단위(0k110)로
갱신 — 진입 후에도 1m 단위로.
## 수정 — StationBar.tsx
- `formatMileage1`(1m 단위, "0k113") 신설, 커서 배지(cursorText)에 적용
- 구간 전환점·시설물 라벨 등 기존 10m/100m 양자화 표기는 유지(formatMileage10 그대로)
## 검증
- tsc+vite 빌드 통과, 새 번들(index-82dmYVKO.js) 서빙
@@ -0,0 +1,25 @@
# 2026-07-13 선형 경계 세그먼트 절단 (측점 POI 이후 선 제거)
**소요 시간**: 5분
**Context 사용량**: input 1780k / output 3k tokens
## 문제 (제보)
직전 클립(마지막 표출 측점 +20m 반경) 후에도 마지막 측점 너머로 선형 꼬리가 남음.
## 원인
클립 판정이 "세그먼트 한쪽 끝이라도 반경 안이면 통째로 그림" — KML LineString 은
직선 구간 정점 간격이 수백 m 라, 경계에 걸친 세그먼트 하나가 마지막 측점 너머로
길게 그려짐.
## 수정 — StationOverlay.tsx buildLines
- 경계를 가로지르는 세그먼트는 **클립 원과의 교점(t)을 이차방정식으로 구해 그 지점까지만** 그림
- 양끝 다 밖 → 생략, 양끝 다 안 → 전체, 교차 → 교점 절단. 여유 20m → 10m 축소
- 드론 기준 EN(m) 좌표로 교점 계산 후 위경도 보간 → 재투영
## 검증
- tsc+vite 빌드 통과, 새 번들(index-JQsYskUj.js) 서빙
- 기하: 어느 방향이든 선 끝 = 마지막 표출 측점 +10m 이내
@@ -0,0 +1,26 @@
# 2026-07-13 노트북 로컬 시연 준비 (Q&A + 스크립트)
**소요 시간**: 5분
**Context 사용량**: input 1830k / output 3k tokens
## 질문
노트북에 로컬 설치해서 시연 가능한지.
## 답변 — 가능. Node.js 20만 있으면 됨
- 시연 흐름(폴더 선택 재생 + 오버레이)은 전부 클라이언트 + 정적 서빙 — WSL/PM2 불필요
- FFmpeg 미설치 시 경고만 뜨고 기동(app.ts 확인) — HLS/서버 프레임추출만 비활성
- better-sqlite3 은 win-x64 Node20 프리빌트 바이너리로 npm install 시 자동 설치
## 산출물
- **start-demo.bat** (저장소 루트): PORT=54000 + storage 경로 env 설정 후 서버 실행,
브라우저 자동 오픈. 빌드 산출물 없으면 안내 후 종료
- **docs/DEMO.md**: 설치(노드/소스/빌드) → 데이터 복사(환경설정 json 포함) → 실행 →
주의사항(오프라인 타일, 리허설, 4K60 사양) 가이드
## 참고
- 시연 데이터: 경로 1-1 폴더(12GB) 통째 복사 — camera.json/display.json 포함해야
캘리브레이션 자동 적용
@@ -0,0 +1,22 @@
# 2026-07-13 POI z 값 부재 확인 (Q&A)
**소요 시간**: 3분
**Context 사용량**: input 1880k / output 1k tokens
## 질문
POI 데이터에 z 값이 없는지 확인 요청.
## 답변 (코드 변경 없음) — 맞음
실파일 확인:
- 지장물.kml: Point 33개 고도 성분 전부 0, '높이' 속성 전부 0 (높이=구조물 높이 필드)
- 측점.kml: 좌표 217개(선형+측점) 고도 전부 0
앱 처리: z=0 → 표고 미상 → 지면고도 모드는 경로표고 앵커 / 드론높이 모드는 드론고도−이격거리 /
POI 편집 드래그·표고 슬라이더 보정값 최우선.
## 참고
- 사용자가 KML 파일명을 지장물.kml / 측점.kml 로 일반화 (경로 1-2, 1-3, 2 폴더 신설 확인)
→ 로더는 이름 무관(*.kml 전체 파싱)이라 그대로 동작
@@ -0,0 +1,36 @@
# 2026-07-13 KML 표고 DEM 일괄 기록 + 파서 z 사용
**소요 시간**: 12분
**Context 사용량**: input 1940k / output 6k tokens
## 요청
높이값 없는 KML(지장물/측점)에 DEM 연동으로 표고를 채워 파일 업데이트.
## 수행 1 — 데이터 일괄 업데이트 (스크립트, SRTM 30m)
- open-topodata SRTM 30m(서버 /api/elevation 과 동일 소스) 배치 조회(100좌표/청크, 1.2s 간격)
- **경로 1-1 / 1-2 / 1-3 / 2 의 지장물.kml·측점.kml 8개 파일** 모든 <coordinates> 고도 성분 기록
- 고유 좌표 237개 조회 → 지장물 33/33, 측점·선형 217/217 기록
- 표고 범위: 도로(측점/선형) 53~89m, 지장물 52~118m — 기존 경로표고 추정(58m)과 부합
- 원본은 `<파일>.kml.bak` 백업 (로더는 *.kml 만 읽어 무영향)
- ※ 현재 4개 폴더 KML 내용이 동일(경로 1-1 복제본) — 경로별 실데이터로 교체돼도
좌표 고도가 0이면 스크립트 재실행으로 다시 채울 수 있음(스크래치패드 dem-update-kml.mjs)
## 수행 2 — 파서가 좌표 고도(z) 사용 (geoData.ts)
- handlePlacemark: coordinates 3번째 성분(>0)을 coordAlt 로 캡처
- 지장물 POI z ← coordAlt (지형 기복 따라 정확 배치), STA 측점 z ← coordAlt
- 선형(LineString)은 기존부터 z 사용 → DEM 표고로 지형 따라 그려짐
- 측점 로드 로그에 DEM 표고 보유 수 표기
## 효과
- 지면고도 모드(기본)에서 측점·선형·POI 가 실제 지면 표고 사용 — 경로표고 슬라이더
수동 보정 불필요(궤적 점 표시만 슬라이더 사용). 시차 정합 향상
- 파일명 변경(지장물.kml/측점.kml)과 무관하게 동작 (로더는 전체 *.kml 병합)
## 검증
- 업데이트 파일 재파싱 검증(33/33, 217/217, 범위 정상), tsc+vite 빌드 통과,
새 번들(index-DJYuQ_W_.js) 서빙
@@ -0,0 +1,42 @@
# 2026-07-13 표고 없는 KML → _byDem.kml 자동 생성 기능
**소요 시간**: 12분
**Context 사용량**: input 2000k / output 6k tokens
## 요청
폴더 로드 시 측점/지장물 KML 의 좌표 z(높이)가 없거나 0 이면, DEM 연동으로 채운
`지장물_byDem.kml` / `측점_byDem.kml` 을 생성·저장하는 기능. (원본 비파괴)
## 데이터 정리 (선행)
직전 턴에서 원본에 직접 기록했던 것을 새 규칙에 맞게 재정리(4개 폴더):
- 현재(DEM 기록) 파일 → `<이름>_byDem.kml` 로 이동, `.bak` → 원본 복원
- 결과: 원본(z=0) + _byDem(z=DEM) 공존
## 구현
### client/src/utils/demKml.ts (신규)
- `generateByDemKmls(files)`: 폴더의 각 KML 에서 고도 없는(≤0) 좌표만 수집 →
서버 `/api/elevation`(SRTM 30m 프록시) 100좌표/청크·1.2s 간격 조회 →
고도 성분만 치환한 `<이름>_byDem.kml` 을 Blob 다운로드. 기존 표고(>0)는 보존
- 건너뜀: 자신이 _byDem / 폴더에 _byDem 존재 / 전 좌표 표고 보유
### client/src/utils/geoData.ts — parseKmz
- `<이름>_byDem.kml` 존재 시 원본 `<이름>.kml` 파싱 제외 (중복 지물 방지, 표고 버전 우선)
### client/src/components/player/VideoPlayer.tsx
- 폴더 선택 시 generateByDemKmls 자동 실행 — 생성되면 alert 로 안내
("다운로드 파일을 영상 폴더에 넣으면 다음 로드부터 자동 사용"). 오프라인 실패는 콘솔 경고만
## 검증
- 파일 선택 규칙 시뮬레이션: [지장물, 지장물_byDem, 측점, 측점_byDem, 기타] →
파싱 대상 [지장물_byDem, 측점_byDem, 기타] ✓
- 서버 DEM 프록시 응답 확인: {"elevation":[70],"source":"opentopodata-srtm30m"} ✓
- tsc+vite 빌드 통과, 새 번들(index-BY1J77b5.js) 서빙
## 다음 단계 참고
- 브라우저 다중 다운로드 허용 팝업이 뜰 수 있음(측점+지장물 2파일) — 허용 1회
- DEM 조회는 인터넷 필요(서버가 외부 API 프록시) — 오프라인 시연 중엔 생성 건너뜀(무해)
@@ -0,0 +1,25 @@
# 2026-07-13 _byDem 생성 시 '높이' 속성도 DEM 표고로 채움
**소요 시간**: 8분
**Context 사용량**: input 2080k / output 4k tokens
## 요청
`<SimpleData name="높이">0</SimpleData>` 에도 좌표와 동일한 DEM 표고를 기록.
## 수정
### client/src/utils/demKml.ts (생성 기능)
- 좌표 고도 치환 후 **Placemark 단위 2차 패스**: 해당 Placemark 좌표의 DEM 표고를
`높이` 속성(0/빈값인 경우만)에 기록. 실값이 있는 높이는 보존
### 기존 데이터 패치 (스크립트)
- 경로 1-2 / 1-3 / 2 의 지장물_byDem.kml — 좌표 고도값으로 높이 33개씩 기록
(검증: 52~118m, 0 잔여 없음, Placemark 33/33 무결)
- 측점_byDem 은 스키마에 높이 필드 없음 → 해당 없음
- **경로 1-1 은 사용자가 _byDem 삭제** → 새 자동 생성 기능 테스트 상태로 유지
(폴더 선택 시 높이 포함 버전이 자동 생성됨)
## 검증
- tsc+vite 빌드 통과, 새 번들(index-DPUNE-4y.js) 서빙
@@ -0,0 +1,37 @@
# 2026-07-13 설정 파일 단순 이름(camera/display/route.json) 지원
**소요 시간**: 8분
**Context 사용량**: input 2160k / output 4k tokens
## 배경
사용자가 설정 파일명을 `route.json` / `camera.json` / `display.json` 으로 단순화.
route.json 은 기존 인식, **camera.json·display.json 순수 이름은 접미사 규칙만 있어 미인식** 상태였음.
새 폴더 `경로 1-1_타원체고기준데이터`(타원체고 z 의 측점.kml) + route.json 에
`ellipsoidal_height: 100.823` 필드 추가됨.
## 수정
### client/src/utils/geoData.ts
- parseCameraJson 우선순위: ① `camera.json` → ② `<영상 base>(.camera).json` → ③ `*.camera.json`
(rootJson 필터에서 route.json/display.json 단순 이름도 제외 처리)
- parseDisplayJson 우선순위: ① `display.json` → ② `<영상 base>.display.json` → ③ `*.display.json`
### client/src/components/overlay/StationOverlay.tsx
- [PC에 저장] 다운로드 파일명: `<영상 base>.camera.json`/`<...>.display.json`**camera.json / display.json**
- 버튼 툴팁 표기 갱신
### client/src/types/geo.ts
- RouteInfo 에 `ellipsoidal_height?: number` 추가 (파일 통과용 — 현재 투영 로직엔 미사용)
## 검증
- 인식 규칙 시뮬레이션: camera.json / display.json / route.json 모두 인식 ✓
- tsc+vite 빌드 통과, 새 번들(index-D6PNHGXU.js) 서빙
## 다음 단계 참고
- **ellipsoidal_height(100.823) 활용은 미구현** — 타원체고 기준 측점 z 와 드론 정표고 간
datum 변환에 쓸지, 경로표고 기본값으로 쓸지 등 의미 확정 필요 (현재 사용자는
camera.json 의 geoidOffset(20)/offZ(21.8) 수동 보정으로 대응 중)
- 타원체고기준 폴더의 측점.kml 은 z 보유(77~114m) → _byDem 생성 대상 아님(로더가 z 그대로 사용)
@@ -0,0 +1,20 @@
# 2026-07-13 경로 1-3 폴더 형상 사전 검증 (Q&A)
**소요 시간**: 6분
**Context 사용량**: input 2230k / output 3k tokens
## 질문
새 형상 폴더(영상2 + 경로별 이름 camera/display/route.json + 지장물/측점.kml) 로딩 가능 여부.
## 검증 (코드 변경 없음) — 로딩 가능
- 영상 _0001/_0002 총 281.6s vs 로그 폭 282.4s → 정렬 성립
- JSON 3종 유효·인식(임의 접두 *.camera/display/route.json 규칙), KML z 보유 → byDem 불필요
## 발견 — z 기준 혼재 (주의)
- 측점(Point) 53~88m = 정표고(DEM) / 선형(LineString) 78~115m·지장물 77~144m = 타원체고
- 드론 고도(CSV)는 정표고 → 이대로면 선형·지장물이 측점 대비 ~25m 떠 보임
- 권장: 정표고로 통일. 대안 제시: ① 타원체고 파일을 정표고로 변환해 제공,
② route.json ellipsoidal_height 로 앱 자동 변환 구현 — 사용자 선택 대기
@@ -0,0 +1,17 @@
# 2026-07-13 카메라 패널 PC 저장 버튼 중복 제거
**소요 시간**: 3분
**Context 사용량**: input 2280k / output 1k tokens
## 문제 (스크린샷 제보)
카메라 파라미터 패널에 [PC에 저장] 버튼이 2개 (헤더 + 📷 내부표정 줄) — 동일 기능 중복.
## 수정 — StationOverlay.tsx
- 📷 줄(중간)의 저장 버튼 제거 — [적용](감지 초점거리)만 유지
- 저장은 패널 헤더 버튼 하나로 통일 (화면표시 옵션 패널과 동일 위치)
## 검증
- 빌드 통과, 패널당 저장 버튼 1개 확인, 새 번들(index-tnrOfrVu.js) 서빙
@@ -0,0 +1,18 @@
# 2026-07-13 54000 포트 외부 접속 개방 완료
**소요 시간**: 6분
**Context 사용량**: input 2330k / output 2k tokens
## 작업 내용 (사용자 UAC 승인 2회로 완료)
- **portproxy**: `0.0.0.0:54000 → 127.0.0.1:54000` 추가 (WSL localhost forwarding 경유 —
재부팅으로 WSL IP 가 바뀌어도 규칙이 깨지지 않는 방식. 기존 55000 은 IP 하드코딩 방식)
- **방화벽**: 인바운드 TCP 54000 허용 규칙 `WSL_ghiVideo_54000` 생성
(첫 시도는 공백 포함 이름의 중첩 따옴표 문제로 실패 → 언더스코어 이름으로 재시도 성공)
- 검증: portproxy 규칙 등록, 방화벽 Enabled/Allow, WSL 서비스 200 응답
## 접속 방법
- 같은 네트워크의 다른 PC 에서 `http://172.16.40.179:54000` (Windows 유선 IP)
- 재부팅 후에도 규칙은 유지되나 **WSL 내 서비스(pm2)는 수동 시작 필요**
(2026-07-09_2056 참고 — pm2 resurrect 자동화 미적용 상태)
@@ -0,0 +1,19 @@
# 2026-07-13 이격거리 측점 적용 복원
**소요 시간**: 3분
**Context 사용량**: input 2380k / output 1k tokens
## 요청
이격거리(드론높이 모드) 적용 시 측점 라벨도 함께 적용.
(1045 에 구현 → 1102 에 사용자 요청으로 제외했던 것을 재적용 — 현재 사용자 워크플로가
드론높이 모드(display.json poiDroneHeight=true, drop 40) 기반으로 바뀜)
## 수정 — StationOverlay.tsx
- RAF 측점 드로우 + 사전계산 가시성: 드론높이 모드면 `드론고도 − 지오이드 − 이격거리` 평면,
지면고도 모드면 측점 표고(stA.z — DEM/타원체고 실값 또는 경로표고 앵커)
## 검증
- 빌드 통과, 새 번들(index-CXVVMHe3.js) 서빙
@@ -0,0 +1,14 @@
# 2026-07-13 지오이드 설정 설명 (Q&A)
**소요 시간**: 2분
**Context 사용량**: input 2420k / output 1k tokens
## 내용 (코드 변경 없음)
지오이드(geoidOffset) = 타원체고(GPS)와 정표고(해발) 간 차이 보정값. 드론높이 모드에서만
사용: 라벨 높이 = 드론고도 − 지오이드 − 이격거리 (두 항은 사실상 합산).
- 기본 25.8 = 대전(회덕) 기준 잔재. 제주 지오이드고 ~21-25m
- 제주 CSV 드론고도는 정표고 확인(타원체고 174.4 26 = 148.4) → DEM 지물과 동일 기준이라
원칙상 0 권장 (현재 사용자의 지오이드20+이격40 = 0+60 과 결과 동일)
- 지물 z 가 타원체고인 데이터셋에서는 지역 지오이드고를 넣어 기준 변환
@@ -0,0 +1,12 @@
# 2026-07-13 지오이드 vs 이격거리 차이 설명 (Q&A)
**소요 시간**: 2분
**Context 사용량**: input 2450k / output 1k tokens
## 내용 (코드 변경 없음)
- 현재 수식(라벨높이 = 드론고도 − (지오이드 + 이격거리))에서는 둘이 합산되어 동일하게 동작
- 역할 구분: 지오이드 = 높이 기준 변환값(camera.json, 지역 물리량) /
이격거리 = 표시 옵션(display.json, 눈대중 조절)
- 권장: 현 데이터(양쪽 정표고)에선 지오이드 0 고정 + 이격거리 단일 조절
- 제안(미실행): 지오이드 UI 고급 옵션화 — 사용자 요청 시
@@ -0,0 +1,17 @@
# 2026-07-13 드론 시작 타원체고 활용성 (Q&A)
**소요 시간**: 3분
**Context 사용량**: input 2480k / output 1k tokens
## 질문
드론 시작 타원체고(route.json ellipsoidal_height=100.823)가 화면·지장물 맵핑에 도움이 되는지.
## 답변 (코드 변경 없음)
- 직접 개선 아님 — 수직 기준은 이미 정합(드론 CSV 정표고 148.4 ↔ DEM 지물 정표고).
남은 오차의 주원인은 수평 요소(Yaw/초점/GPS)
- 유용한 경우: ① 타원체고 기준 지물 데이터의 지오이드 변환 상수 산출(핵심),
② 상대고도 로그 데이터셋의 절대고도 복원 기준, ③ 교차검증
- 제안(미구현): 타원체고 지물 폴더에서 지오이드고 = djmd 타원체고 − CSV 정표고(26.0m) 자동
산출·변환, ellipsoidal_height 는 검증값 — 사용자 선택 대기
@@ -0,0 +1,20 @@
# 2026-07-13 측점·지장물 맵핑 기준값 권장안 (Q&A)
**소요 시간**: 3분
**Context 사용량**: input 2520k / output 2k tokens
## 질문
측점·지장물의 화면 맵핑 기준을 무엇으로 삼을지.
## 답변 (코드 변경 없음) — 실측값 고정 + Yaw 단일 튜닝
- 높이: 정표고 통일(드론 CSV + DEM 지물 z), 지오이드 0/offZ 0, **지면고도 모드**(지형 추종)
- f=29.9(감지값)·센서 36×20.25(물리값) 고정 — sensorH 16.95 튜닝값은 재검토 권장
- 튜닝은 Yaw± 만(자동추정→드래그 역산), 잔차에만 Pitch±/cy₀
- 보정 순서 5단계 안내, 저장(camera/display.json)으로 재현
## 남는 한계 및 제안
- GPS ±1~3m, 10Hz 보간, 로그-영상 시간 동기 ±0.5s(이동 중 ~5m)
- 제안(미구현): **시간 오프셋(ms) 보정 슬라이더** — 남은 오차원 중 효과 최대. 사용자 선택 대기
@@ -0,0 +1,36 @@
# 2026-07-13 타원체고 기준 자동 변환 (datum 통일)
**소요 시간**: 12분
**Context 사용량**: input 2570k / output 6k tokens
## 요청
지물(측점/지장물) 데이터가 타원체고 기준일 때, 그 기준으로 맵핑을 맞출 수 있는지 → 구현.
## 원리
- 드론 **타원체고**가 영상 메타(djmd 필드 6.6, mm)에 프레임별 기록됨: 174.42m
- CSV 고도는 **정표고**: 148.36m → 차이 26.06m = **그 지점의 지오이드고** (자동 산출 가능)
- 타원체고 데이터셋이면 드론 고도에 이 값을 더해 지물 z(타원체고)와 기준 통일
→ 지오이드/offZ 수동 보정 불필요
## 구현
- **cameraMeta.ts**: djmd 6.6 → `DetectedCameraInfo.ellipsoidalAltM` 추출 (0~10km 범위 검증)
- **geoData.ts (loadFolderGeoData)**: route.json `routeInfo.ellipsoidal_height` 가 선언된 폴더 =
타원체고 기준 데이터셋 신호 → `altitudeOffsetM = djmd 타원체고 CSV 정표고` (|값|<60m 검증)
를 모든 드론 프레임 altitude 에 가산. FolderGeoData/geoStore 에 오프셋 보존
- **geoStore.loadSegment**: 세그먼트 전환 재파싱 프레임에도 동일 오프셋 적용
- 정표고(DEM) 데이터셋(ellipsoidal_height 없음)은 오프셋 0 — 기존 동작 무변화
## 검증
- 실파일: djmd 174.42 CSV 148.36 = 26.06m 자동 산출 ✓ (제주 지오이드고와 부합)
- 경로 1-3 route.json 에 ellipsoidal_height(100.823) 존재 확인 → 해당 폴더 자동 발동
- tsc+vite 빌드 통과, 새 번들(index-D4bVLsb9.js) 서빙
## 사용 안내
- 타원체고 기준 폴더: route.json 에 `ellipsoidal_height` 만 있으면 자동 변환 —
지오이드 0/offZ 0 으로 두고 지면고도 모드 사용 권장
- 콘솔 로그: `[geo] 타원체고 기준 데이터셋 — 드론 고도를 타원체고로 변환 (+26.06m …)`
@@ -0,0 +1,24 @@
# 2026-07-13 측점.kml datum 불일치 발견 (사용자 승인 대기)
**소요 시간**: 6분
**Context 사용량**: input 2620k / output 3k tokens
## 사용자 확인
측점·지장물 KML 이 타원체고 기준이라고 확인 → 실파일 검증 수행.
## 검증 결과 (경로 1-1·1-3 동일)
- 지장물(77~144m)·선형(78~115m) = 타원체고 ✓
- **측점 Point(53~88m) = 정표고(DEM)** — 불일치. 이대로면 타원체고 자동 변환 후
측점 라벨만 ~25m 낮게 표시됨
## 준비된 교정 (미실행 — 원본 덮어쓰기 보호로 차단)
- 측점 Point z ← 같은 파일의 타원체고 선형에 세그먼트 투영·z 보간 (지오이드 가정 불필요)
- 원본은 측점.kml.bak 백업
- 실행 조건: 사용자가 "측점.kml 덮어써서 교정" 명시 승인 시
## 대안
- 사용자가 GIS 도구에서 측점 z 를 타원체고로 재출력해 파일 교체
@@ -0,0 +1,17 @@
# 2026-07-13 측점 Point z 타원체고 교정 실행 (사용자 승인)
**소요 시간**: 4분
**Context 사용량**: input 2720k / output 2k tokens
## 실행 내용 (사용자 "응 해줘" 승인)
- 경로 1-1·1-3 의 측점.kml: 측점 Point 71개 z 를 **같은 파일의 실측 타원체고 선형에
세그먼트 투영·보간한 값**으로 교정 (원본 → 측점.kml.bak 백업)
- 보정량 +17.5~+39.7m (지오이드 ~25m + SRTM 국소 오차 제거분)
- 교정 후 측점 z 77.9~113.5m — 선형과 최대 편차 **0.05m** (교정 전 ~25m)
## 결과 — 데이터 기준 통일 완료
- 지장물(타원체고) + 선형(타원체고) + 측점(타원체고) + 드론 고도(자동 변환 +26.06m)
→ 전부 타원체고 기준. 지오이드 0/offZ 0 + 지면고도 모드에서 정합
- SRTM 근사가 실측 선형 기반으로 대체되어 수직 정확도도 개선
@@ -0,0 +1,11 @@
# 2026-07-13 지오이드 0 = 타원체고? (Q&A)
**소요 시간**: 2분
**Context 사용량**: input 2680k / output 1k tokens
## 답변 (코드 변경 없음) — 아니요
- 지오이드 슬라이더는 datum 스위치가 아님 — 드론높이 모드의 라벨평면 뺄셈 항일 뿐
- 기준 결정 요소: 드론 고도 값(정표고 / ellipsoidal_height 선언 시 자동 +26.06 타원체고)과 지물 z
- 타원체고 기준 스위치 = route.json `ellipsoidal_height` (자동 변환), 그때 지오이드는 0 유지(중복 방지)
- 지면고도 모드는 지오이드 미사용 → 측점 Point(정표고 잔재) 교정 필요성 재안내
@@ -0,0 +1,11 @@
# 2026-07-13 이격거리 권장값 (Q&A)
**소요 시간**: 2분
**Context 사용량**: input 2760k / output 1k tokens
## 답변 (코드 변경 없음)
- 1순위: **지면고도 모드에서는 이격거리 미사용** — 실측 타원체고 z 에 직접 배치(권장)
- 드론높이 모드 사용 시: 드론 174.4m 비행구간 도로 95.8~113.5m = **61~79m, 평균 ~72m**
→ 이격거리 70~75 권장(지오이드 0 기준), 단일값 한계(도로 기복 18m) 안내
- 구 display.json(drop 40+geoid 20=60)은 datum 통일 전 값 — 갱신 필요
@@ -0,0 +1,10 @@
# 2026-07-13 드론높이 기능 OFF 권장 확인 (Q&A)
**소요 시간**: 1분
**Context 사용량**: input 2790k / output 1k tokens
## 답변 (코드 변경 없음) — 네, OFF 권장
- OFF(지면고도) = 실측 타원체고 z 직접 배치 → 지형 추종(비행구간 기복 18m 대응)
- ON(드론높이) = 평면 근사 → 기복 구간 어긋남. z 없던 시절의 대안이었음
- 최종 체크리스트: 드론높이 OFF → 지오이드 0 → offZ 0 → Yaw 확인 → camera/display.json 저장
@@ -0,0 +1,28 @@
# 2026-07-13 dev_mode 로 영상제어 UI 표시 제어
**소요 시간**: 5분
**Context 사용량**: input 2830k / output 2k tokens
## 요청
route.json `dev_mode`: 1 이면 영상제어 ON 버튼 표시, 0 이면 숨김.
## 수정
### client/src/types/geo.ts
- RouteInfo 에 `dev_mode?: number` 추가
### client/src/components/player/VideoPlayer.tsx
- routeMeta 구독 → devMode 산출 (routeInfo.dev_mode 우선, 최상위 dev_mode 허용,
**없으면 1 — 기존 동작 유지**)
- dev_mode=0 이면:
- 좌하단 그룹(영상제어 버튼 + 배속/프레임/좌측패널/선형/드론궤적/GPS/시설등급) 전체 숨김
- StationOverlay showPanel=false → 우측 카메라 파라미터/화면표시 옵션 버튼도 숨김(뷰어 모드)
## 사용법
route.json 의 routeInfo 안에 `"dev_mode": 0` (숨김) 또는 `"dev_mode": 1` (표시) 추가.
## 검증
- tsc+vite 빌드 통과, 새 번들(index-m3xt1ima.js) 서빙
@@ -0,0 +1,26 @@
# 2026-07-13 선형 실종(0k700 구간) — 관통 세그먼트 수정
**소요 시간**: 6분
**Context 사용량**: input 2880k / output 3k tokens
## 문제 (스크린샷 제보)
특정 구간(0k700~0k900 부근)에서만 선형(빨간 선)이 통째로 사라짐. 측점 라벨·궤적은 정상.
## 원인
선형 클립(마지막 표출 측점 반경)에서 "세그먼트 양끝이 모두 원 밖 → 생략" 처리 —
KML 선형은 직선 구간 정점 간격이 수백 m 라, **양끝은 밖이지만 세그먼트가 클립 원을
관통(현)하는 경우**가 흔함. 그 구간에선 화면에 보여야 할 선이 전부 생략됨.
실측 재현: 드론 0k700 상공(clipR 300m)에서 기존 코드 세그먼트 0개.
## 수정 — StationOverlay.tsx buildLines
- 양끝 밖 세그먼트도 원과의 교점을 계산해 **두 교점(t1<t2) 사이 구간(현)을 그림**
- 교점 계산을 clipTs(0~1 범위 근 목록)로 일반화 — 한쪽 밖 케이스도 진입/이탈 교점을
방향에 맞게 선택(기존 first-match 로직 정리)
## 검증
- 실데이터 재현: 0k700 상공 기존 0개 → 수정 후 1개(관통 현) ✓
- tsc+vite 빌드 통과, 새 번들(index-Bh3NtoUq.js) 서빙