업로드 잠금(결함 3)
- 종전에는 전처리(B04)만 끝나면 버튼이 풀려, 노선·횡단이 도는 동안 자료를 또 올릴 수
있었다. isInitialPipelineRunning()/pollInitialPipeline()을 두어 **횡단 단계가 열릴
때까지**(3단계가 NOT_STARTED를 벗어날 때까지) 잠근다.
- relockWhileInitialPipelineRuns(): 새로고침·재진입해도 계산이 도는 중이면 다시 잠그고
스피너를 붙인다. 잠금이 화면 상태로만 있으면 새로고침 한 번에 풀렸다.
- 보관함 연결 경로도 같은 대기 흐름을 탄다.
자료 없으면 대시보드(결함 6)
- b_missing_data_guard 신설 — 근거 자료가 없으면 한 줄 안내 후 B01로 보낸다. 새 자료가
올라오면 서버가 옛 산출물을 지우므로, 열어 둔 뒷단계 화면은 빈 화면이 아니라
대시보드로 나가야 한다(2026-08-08 사용자 지시).
- B05: 확정 지표면이 없으면 이동. B06: 노선 또는 종단면이 없으면 이동.
검증: 자료가 없는 신규 프로젝트로 B05 진입 → 안내 후 #/b01-account 로 이동함을
헤드리스 크롬으로 확인. typecheck·prettier 통과, 정적 번들 재빌드.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
앞선 두 커밋(c3f643b, 7d50ded)으로도 증상이 남아 헤드리스 크롬으로 실제 앱에 로그인해
B05 3D를 끌어 보며 측정했다. 원인은 회전 계산이 아니라 **탑뷰 카메라 자리**였다.
카메라를 정확히 수직으로 세우면(기존 top = [0, distance, 0.001], 극각 1e-6도) lookAt이
화면의 가로·세로 방향을 정하지 못한다. 그 자리에서 벗어나는 순간 화면 축이 180° 돌아간다.
실측(2px 드래그 6걸음):
before 극각 0.00° -> 0.86°, 1걸음째 화면축 반전, 이후 같은 방향 드래그 먹통
after 극각 2.00° -> 1.15°, 반전 0회, 반대 방향 20걸음도 반전 0회(1.15° -> 130°)
- TOP_VIEW_TILT(2°) 신설 — 화면상 위에서 내려다보는 그림과 구분되지 않으면서 여유각
(POLAR_EPSILON, 약 1.15°)보다 바깥이라 첫 드래그부터 회전이 이어진다.
- B05 노선 뷰어, B04 지형·포인트클라우드 뷰어의 탑뷰 세 곳에 모두 적용.
typecheck·prettier 통과, 정적 번들 재빌드.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
앞 커밋(53ab941)에서 "표고 없는 점은 안 그린다"를 넣었는데도 그대로 보였다.
restorePoints -> placed()가 마커에 넘기기 전에 z: point.z ?? 0으로 바꿔, 마커 쪽에서는
표고를 아는 점(0m)으로 보였기 때문이다. 판정이 걸릴 자리가 없었다.
- PlacedRoutePoint.z를 number | null로 바꿔 "모름"을 모름 그대로 들고 다닌다.
- placed()는 z ?? null, 서버로 보낼 때(routePoint)만 null -> undefined로 바꾼다.
- modelToScene은 표고가 정해진 점만 받는다(z: number) — 호출부에서 이미 해결한 값을 준다.
typecheck·prettier 통과. 백엔드가 정적으로 서빙하는 번들(config/node_modules/.build)도
다시 빌드했다 — :8000으로 보면 서버 기동 때 만든 옛 번들이 떠서 수정이 반영되지 않는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
계획노선 CSV로 만든 제어점에는 표고가 없다(z: null). modelToScene이 point.z - cz를
계산하는데 JS에서 null - 548.5 = -548.5이라, BP·EP·경유점 135개가 전부 지형 중심보다
548m 아래 수평면에 깔렸다. 화면에서는 노선 모양이 평면에 투영된 주황 구슬 커브로
보였고(경유점 색 0xf59e0b), 원근 때문에 지형 밖으로 밀려 나갔다.
- markerElevation() 신설: 표고가 있으면 그 값, 없으면 시·종점만 지형 표면을 찾아 얹는다.
표고 없는 경유점은 그리지 않는다 — 그 자리는 경로선으로 이미 보이고, CSV 정점
전부(여기선 133개)에 마커를 세우면 노선이 구슬에 덮인다.
- 뷰어에 terrainElevation() 추가: 지형 위에서 수직으로 광선을 쏴 표면 높이를 읽는다.
- renderRoute도 같은 함정을 막는다: z ?? 0 대신 지형 표고 → 직전 점 높이 순으로 채운다.
경고 구간이 인덱스로 점 배열을 다시 자르므로 점 개수는 그대로 둔다.
typecheck·prettier 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03(d21b0ec)에 곡선 기준을 R에서 L로 바꿨지만 배관 정착 계획선 산출부
한 곳에만 들어갔다. 공용 곡선 계산기와 정책값은 R 기준(측점간격 20m ×
curve_radius_ratio 0.40 = 8m)으로 남아, 사용자가 변화점을 새로 추가하면 그 자리만
R=8m가 적용됐다(대수차 3%면 L=0.24m — 도면에서 곡선이 사라진다). 화면 요약도
"기본 R 8.0 m"를 그대로 보여줘 오해를 키웠다.
- config: pipe_anchor_curve_length_m -> default_curve_length_m(15.0)로 승격.
배관 정착뿐 아니라 모든 변화점의 1차 기준값이다.
- AlignmentPolicy에 default_curve_length_m 추가, 정책 스냅샷에도 실어 보낸다.
옛 R 기준 값(default_curve_radius_m)은 옛 저장분 호환용으로 남긴다.
- build_curves(백엔드)와 buildCurves(프론트) 규칙 일원화:
사용자 지정 R > 기본 L > (옛 저장분) 기본 R × 대수차.
- 인접 직선이 짧아 목표 L을 못 넣으면 **넣을 수 있는 최대 L**까지만 줄이고 경고를
남긴다(2026-08-08 사용자 지시). 경고 문구도 길이 우선으로 고쳤다.
- 옛 저장분(정책에 L 없음)은 양쪽 모두 R 기준을 유지한다 — 서버만 L로 올리면
화면과 다른 곡선이 나온다. 새 기준은 계획선을 다시 산출할 때 적용된다.
- 패널 요약 라벨: "기본 R" -> "기본 곡선길이 L"(옛 저장분은 "기본 R(옛 저장분)").
검증(측점간격 20m, 대수차 3%): 기본 L=15.00m/R=500m, 사용자 R=300 지정 시
L=9.00m/R=300m, 인접 직선 10m면 L=9.00m로 잘리고 경고 1건, 옛 스냅샷은 종전대로
L=0.24m/R=8m. typecheck·ruff format·check 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
화면에서 막 찍은 경유점은 order가 아직 없어 None으로 온다. 정렬 키가
x.get("order", 0)이라 키가 있고 값만 None인 경우를 걸러내지 못해
TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'로
경로 탐색 전체가 실패했다(서버 로그 확인, project_id=fc86f247).
None을 0으로 눕힌다 — 파이썬 정렬이 안정적이라 번호가 없는 점들은 받은 순서를
유지한다. 같은 패턴을 쓰던 능선/계곡 탐색기(RidgeValley)도 함께 고쳤다.
ruff format·check 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- prettier 적용(편집 파일 14종), ruff format 무변경 확인
- B03 내부 백그라운드 태스크 라벨 b04-wf1-auto -> b04-preprocess-auto
- docs/raw/PLAN.md R1 체크리스트 Phase 1~7 완료 표시 (검증 대기 상태로 전환)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
자동 체인 상태 전이 분리:
- confirm_latest_route/confirm_sections에 mark_stage_complete 플래그 추가
- 자동 체인(신규·재확정)은 데이터만 확정하고 stage 2·3을 IN_PROGRESS로 남김
(스텝바 기존 노란 테두리 = 계산됨·확정 전 상태로 재사용)
- B06 [확정]이 stage 2+3 동시 완료 + 경로 상태 CONFIRMED 보강 후 B07 수량 이동
B05 좌측 패널 개편:
- 포인트 팔레트 + 임도 기준·옵션을 경로 계산 설정 한 컨테이너로 병합,
[최적 경로 계산] 버튼을 컨테이너 내부로 이동 (가끔 쓰는 무거운 재계산)
- 하단 액션 행 [초기화][임시저장][횡단 이동]으로 교체, 경로 단독 확정 폐지
- [임시저장] = 관로 + 계획선 델타 + 비정규 측점·상단측 저장(mark_stage_complete=false)
- [횡단 이동]/B06 [종단 이동] = 저장 없이 페이지 이동만 (B05·B06 캐시 공유 구조 유지)
- [초기화] = POST /route/reset 신설: 기존 경로 삭제 후 계획노선 CSV 기본값으로
자동 체인 재실행(파일입력 직후 상태 복원), 분석용 타임아웃 적용
B06 액션 행: [종단 이동][임시저장][확정] 3버튼 구성, locale 키 정비
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>