절토부의 토사·암반 구분은 환산계수가 아니라 횡단도 기하로 갈린다. 지표면~암반 경계선이
토사, 그 아래가 암이다. 기존에는 측점당 절토 단면적이 하나뿐이라 리핑암/발파암 측점의
상단 토사층까지 암 환산계수로 곱해졌다(실데이터 기준 다짐환산 +21% 과대).
- Engine_Design: `_split_cut_areas()` 신설. `d=0`, `d=t0` 교차점을 브레이크포인트로 넣어
정확 적분(무작위 2,000회 검산 `soil+rock==cut` 최대오차 1.4e-14).
`cut_soil_area_m2` / `cut_rock_area_m2` / `cut_rock_kind` 3필드 추가(기존 키 불변).
- UI_Cross_Areas(신규): 면적 readout을 4칩으로 확장하고 절토(토사)/절토(암반)/성토 밴드를
그린다. 선택된 카드에서만 붙어 다른 측점을 고르면 자동 해제된다.
- UI_MassHaul: `AreaSample`을 2분할로 교체해 부분별 환산계수를 물리고, 측점별 구간 물량
내역(토사/암반/다짐환산/성토)을 남긴다. 구 데이터는 전량 측점 지반유형으로 폴백.
- UI_MassHaul_View: 선택 측점의 구간 물량 표기 줄과 곡선 위 강조점 추가. 측점 매칭은
id가 아니라 누가거리로 한다(종단 기준 곡선의 점 id는 파생값이라 형태가 다름).
암반 경계선 오프셋을 바꾸면 분리 면적과 유토곡선 환산량이 함께 움직인다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
패널을 줄여 둔 세션에서 B06 에 다시 들어오면 패널 높이는 복원되는데 차트 높이 배분만
기본값(종단 220 / 유토 190)으로 계산돼, 합계 410px 가 200px 공간에 밀려 들어가면서
종단면도가 20px 로 잘려 사실상 사라졌다. 창 크기를 조금만 바꾸면 정상으로 잡혀
(자가 치유) 구현 당시 검증에서 걸리지 않았다.
원인은 첫 렌더 시점의 조회 방식이다. draw() 는 root.replaceChildren(panel, ...) 보다
먼저 drawPanel() 을 부르므로, 그 시점의 panel 은 아직 root 에 붙기 전(detached)이다.
detached 요소는 getComputedStyle 이 빈 값을 돌려주기 때문에 --b06-profile-height 를
읽지 못하고 BASE_PANEL_HEIGHT(506) 로 폴백했다. 리사이저가 복원해 둔 값 자체는
인라인 스타일에 정상적으로 들어가 있었다.
panelHeight() 가 인라인 스타일을 먼저 읽고, 없을 때만 computed 로 폴백하게 바꿨다.
인라인 조회는 detached 상태에서도 동작하므로 첫 렌더부터 저장값이 반영된다.
구조는 C02 에서 유입됐으나 당시에는 차트가 하나뿐이라 영향이 작았고, C05 로 차트가
둘이 되면서 배분 실패가 종단면도 소멸로 확대됐다.
자체 검증 — 판정 기준은 "첫 렌더 = 재렌더"(결함이 있으면 첫 렌더만 어긋난다):
- 저장값 296px : 296/99/111 = 296/99/111 일치
- 저장값 없음 : 496/220/190 = 496/220/190 일치 (회귀 없음)
- 저장값 700px : 700/220/384 = 700/220/384 일치 (기본 초과 시 종단도 고정, 유토가 흡수)
prettier 변경 없음, tsc --noEmit 오류 0건, 437줄.
근거: docs/raw/verification/2026-08-02_verify_mass_haul_multi_curve.md [F1]
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
임도는 산복 사면을 따라가 편절·편성이 지배적이라, 종단 계획고로 본 절성토 균형과
실제 횡단 단면적으로 본 균형이 크게 어긋난다. 어느 쪽을 정식 기준으로 삼을지
사용자가 그래프를 보고 결정할 수 있도록 두 기준을 한 축에 겹쳐 그린다.
지반유형 처리도 암반 경계선 분리 전까지는 미결이라 세 가지를 함께 낸다.
법령 근거([임도의 설계 및 시설기준] 별표):
- 2.다.(3)(나) "시공계획고는 절토량과 성토량이 균형을 이루게 하되" → 종단 기준 곡선
- 2.다.(4)(마) 측점마다 절토고·성토고·단면적 기입 → 횡단 기준 곡선
- 2.다.(4)(다) "절토부분은 토사·암반으로 구분" → 암반 분리(미결 1번)의 근거
같은 별표에 토공 운반장비 선정거리 기준은 없다. 장비 경계값의 근거는 법령이 아니라
3공구 도면 실측치다.
곡선 6종 = 기준 2(횡단/종단) x 환산 3(지반유형별/토사 단일/환산 없음).
색이 기준, 선모양이 환산 방식을 뜻한다.
- _UI_MassHaul.ts: 공통 적분 함수 integrate(samples, conversion, groundMode)로 통일.
두 기준이 AreaSample[]까지 정규화된 뒤 같은 코드를 탄다 — 평균단면법·환산 로직을
이중으로 두지 않는다. computeMassHaulSeries() 신설.
computeMassHaul()은 시그니처·결과를 그대로 유지해 _UI_Page.ts의 확정 저장 경로는
건드리지 않는다.
종단 기준: difference_m(= 계획고 - 지반고, 음수가 절토) x 노반폭.
노반폭·지반유형은 종단 샘플에 없으므로 최근접 설계 측점에서 상속한다.
- _UI_MassHaul_View.ts: 다중 곡선 렌더 + 그래프 상단 오버레이 범례.
Y 스케일은 표시 여부와 무관하게 항상 전체 곡선 기준으로 잡는다 — 곡선을 껐다 켤 때마다
축이 움직이면 비교 자체가 불가능하다.
면(band)은 맨 앞 곡선 하나에만 칠한다(여러 개면 서로 가려 못 읽는다).
곡선은 범례 역순으로 그려 첫 곡선이 맨 위에 온다.
- _UI_Section_View.ts: 표시 집합을 sessionStorage에 보존. 전부 끈 상태도 사용자의
선택이므로 기본값으로 되돌리지 않는다. 요약 수치는 켜 둔 첫 곡선의 것이며,
어느 곡선인지 요약 끝에 반드시 밝힌다.
- _UI_Style_MassHaul.css(신규): _UI_Style_Cross.css가 742줄로 700줄 제한을 넘어
유토곡선 블록을 분리했다(분리 후 606줄). 범례는 sticky + height:0이라 가로 스크롤에도
왼쪽에 남으면서 곡선 위로 뜬다.
- ui_template_locale_b2.ts: 곡선명·범례 문구 9개 키. 하드코딩 없음.
검증(테스트1 / route 48 / 24측점 중 23측점 설계):
- 계산 엔진 단위 테스트 18건 통과, tsc --noEmit 통과, 전 파일 700줄 이하
- 범례 6개 생성, 토글 2 -> 6 -> 0 -> 2 정상
- Y 눈금이 세 상태 모두 60.5 / -46.3 / -153.0 으로 동일 (축 고정 확인)
- X축 정렬: 종단도 측점선 [62 ... 1454] 24개 = 유토곡선 [62 ... 1454] 24개
- 새로고침 후 켜 둔 곡선 복원 확인
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
유토곡선 운반계획(Phase 2)이 평균운반거리로 장비를 고를 때 쓸 경계값이다.
사용자 확정값이며 현장·발주처 기준에 따라 달라질 수 있어 config 한 곳에만 둔다.
참고 도면 관측치(종무대 14~16m, 도쟈 20m, 덤프 67.8m)와 모순되지 않는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
상세 배수유역 정보는 페이지에 들어오면 바로 보여야 하는데 기본값이 접힘이었고,
접기/펼치기 화살표도 반대를 가리키고 있었다.
- 기본값: 저장값이 없을 때 `!== "false"`(접힘)를 `=== "true"`(펼침)로 바꿨다.
같은 페이지 하단 종단 패널(B05_wf2_Route_UI_Profile_Panel.ts:592)이 이미 쓰던 규칙과
같아졌다.
- 화살표: 공용 `createWorkflowPanelHandle`은 왼쪽에 도킹해 왼쪽으로 접히는 패널
(제목 카드)을 전제로 회전값을 고정하고 있었다. 배수유역 패널은 오른쪽에 도킹해
오른쪽으로 접히므로 같은 회전을 쓰면 열기/닫기 표시가 정확히 거꾸로 나온다.
`collapseToward` 인자를 추가하고 이 패널만 "right"를 넘긴다.
기본값 "left"라 나머지 호출처는 회전값이 이전과 동일하다:
- ui_template_overlay.ts:81 제목 카드 — "side" 기본값, 열림 180° / 닫힘 0° 그대로
- B05_wf2_Route_UI_Profile_Panel.ts:244 하단 패널 — "bottom" 배치라 애초에 무관
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
헤드리스 브라우저로 실화면을 확인하다 드래그가 전혀 먹지 않는 것을 발견했다.
손잡이 중심의 hit-test가 손잡이가 아니라 패널을 돌려주고 있었다.
- 손잡이 위치: 패널이 `overflow: hidden`이라 경계에 걸치게 둔 `bottom: -3px`는
아래 절반이 잘려 나가 클릭 영역이 3px도 남지 않았다. `bottom: 0` + 높이 8px로
안쪽에 붙여 전체가 잡히게 했다.
- 높이 상한: 부모 `.b06-profile__main`은 횡단 카드까지 담은 스크롤 콘텐츠라
clientHeight가 5809px였고, 상한이 4647px로 잡혀 사실상 무제한이었다. 이 패널은
화면 위에 sticky로 붙으므로 상한을 화면 높이 기준으로 바꿨다.
- Y축 눈금: 패널을 줄이면 유토곡선 그래프 몫이 60px대까지 내려가 눈금 5개의
라벨이 서로 겹쳤다. 그래프가 낮을 때는 3개만 그린다.
실화면 검증(프로젝트 테스트1, route 48, 측점 24개 / 설계 23개):
- 기본 496px → SVG [220, 190]
- 아래로 드래그 694px → SVG [220, 378] (종단도 고정, 유토곡선이 늘어난 몫 흡수)
- 위로 드래그 392px → SVG [170, 147] (기본값 대비 비율만큼 둘 다 축소)
- 접기 35px / 펼치기 복원
- 종단도와 유토곡선의 첫 측점 x=62, 마지막 측점 x=1454로 세 높이 모두에서 일치
- 요약: 절토(자연) 216.1㎥ (토사 14.9 / 리핑암 201.2 / 발파암 0.0),
절토(다짐환산) 244.8㎥, 성토 321.4㎥, 토취 76.6㎥
→ 14.9×0.90 + 201.2×1.15 = 244.79, 244.8 − 321.4 = −76.6 으로 수식과 일치
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
참고 도면 `13 유토곡선(울진 울진 대흥 산65 외2(3공구)).pdf` 분석 결과를 반영해
B06 종단면도 바로 아래에 유토곡선을 추가하고, 둘을 접이식 상단 슬라이드 패널
하나로 묶었다.
계산 (프론트 전담, 확정 시에만 영구 저장)
- `_UI_MassHaul.ts` 신설: 평균단면법으로 구간 토량을 만들고 토량환산계수로 기준을
통일해 누가토량을 누적하는 순수 함수. DOM 의존 0이라 B08/B09가 재사용 가능.
- 기준상태는 다짐상태 — 운반거리 산정 시 모든 수량은 다짐상태로 환산하고 내역서
수량은 자연상태로 한다(국도건설공사 설계실무 요령). 내역서용 자연상태 수량은
cut_natural_m3로 함께 보존한다.
- 지반유형이 다른 구간은 각 측점이 자기 절반(단면적 × Δd / 2)을 자기 지반유형으로
가져간다. 두 절반의 합이 평균단면법과 정확히 일치한다.
- 측점 조작마다 백엔드를 왕복하지 않고 메모리에서 계산하며, 확정 시점에만
longitudinal_sections.data.mass_haul에 저장한다.
X축 정렬
- longitudinalMaxChainage()를 공용으로 신설해 종단 렌더러와 유토곡선이 같은 X
매핑을 쓰게 했다. 두 SVG는 chart-wrap 하나를 공유해 가로 스크롤도 함께 움직인다.
패널 높이
- 아래 경계 리사이저로 사용자가 조절한다. 기본값 이상으로 키우면 종단도는 220px을
지키고 늘어난 몫은 유토곡선이 먹으며, 기본값보다 줄이면 둘이 같은 비율로 작아진다.
- 종단도가 줄면 Y스케일도 그 높이로 다시 잡아 표고가 잘리지 않게 했다.
토량환산계수
- config_system.py 5-4-3절 신설(유일한 정의처). 표준품셈 암종별 범위를 B06 지반유형
3종에 대응시킨 제안값이며 현장 조정이 전제라 env 없이 상수로 두었다.
검증: tsc 0건, ruff 통과, prettier 적용, 전 파일 700줄 이하.
계산 엔진 테스트 10종 전건 통과(평균단면법·다짐환산·지반유형 배분·비정규 측점
간격·정렬·중복 측점·계수 부재 폴백·페이로드 반올림). 서버 기동 및 번들 포함 확인.
Phase 2(평형선·운반토량 Q·평균운반거리 L·장비 배분·M.N)는 장비 거리 경계와 M.N
정의가 미확정이라 제외했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1,230줄이던 ui_template_locale.ts를 얇은 배럴(51줄)로 축소하고,
ui_locales 사전 데이터를 4개 파일로 분리했다.
- ui_template_locale_common.ts (96줄, 60키) — 공통 액션/상태/폼/네비/워크플로우/앱 셸, LocaleEntry 타입 정의
- ui_template_locale_a.ts (263줄, 141키) — A01~A09 로그인 전 페이지
- ui_template_locale_b1.ts (430줄, 260키) — B01~B04
- ui_template_locale_b2.ts (408줄, 253키) — B05~B11
배럴이 4종 사전을 스프레드로 합성하고 LANGUAGES / LanguageCode /
currentLanguageIndex / setLanguage / t / ui_locales / LocaleKey export
시그니처를 그대로 유지하므로, 소비처 13개 이상 파일의 import 수정은 없다.
검증: 분할 전후 714개 키가 값 문자열까지 완전 일치, 파일 간 중복 키 0건,
tsc --noEmit 오류 0건, prettier 5개 파일 모두 unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B04/B05 2D 지도·B06 횡단도와 같은 방향으로 맞췄다. openwebcad의 zoomScreen
계산식은 그대로 두고 호출부에서 부호만 뒤집어 넘긴다(외부 코드 변경 최소화).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B04 2D 지도·B05 배수유역도와 같은 방향으로 맞췄다. viewBox 축소가 확대이므로
factor 판정만 deltaY > 0 기준으로 바꿨고, 커서 아래 지점 고정은 그대로다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B04 2D 지도와 B05 배수유역도의 휠 판정을 deltaY > 0 기준으로 바꿨다.
커서 아래 지점을 고정하는 offset 보정은 그대로다. 3D 뷰어는 손대지 않았다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
하이라이트 열이 덮는 자리의 규칙 측점 값 셀을 통째로 숨겨(hideCoveredCells),
비정규 측점을 고를 때마다 좌우 최대 2개 열의 값이 사라졌다. 표는 그대로 두고
선택된 값만 위에 얹도록 그 함수와 .is-covered 규칙을 걷어냈다.
하이라이트 열에서 계획고만 자주색 테두리·글자색으로 따로 강조되던 것도 없앴다.
평상시에는 다른 셀과 같은 모습이고, 고칠 수 있다는 표시는 hover·focus에서만
나타난다. 직접 입력 기능은 그대로다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
구조물 측점이 두 곳에 있었다. 화면 정본인 사이드바 목록과, 경로 확정 때 종단
정본 파일에 병합된 kind="irregular" 측점이다. 그래프와 3D가 둘을 겹쳐 그려서
관을 옮기면 사이드바 목록만 따라가고 확정 당시 자리는 그대로 남았다.
그래프(_UI_Profile_Panel.draw)와 3D(_UI_Page.renderStationLines) 모두 종단
정본의 비정규 측점을 걷어내고 사이드바 목록만 얹는다. 저장분은 진입 시
restoreSections가 목록으로 되살리고, 관 항목은 배수유역도가 정본
(pipe_points.json)에 맞춰 갈아 끼운다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1) 사이드바 폼으로 이름을 "배관"이라 적어 넣은 항목은 origin이 "user"라 [초기화]로
지워지지 않고 배수유역도와도 어긋난 채 남았다. isPipeStation()(origin이 pipe이거나
이름이 "배관")으로 판정을 통일해 목록 교체·이동·삭제·선택 동기화가 같은 규칙을 쓴다.
2) 대시보드에서 곧장 B05로 들어오면 배수유역도가 비어 보이고 새로고침해야 나왔다.
패널이 배치되기 전(0×0)에 fitToRoute()가 돌아 엉뚱한 배율이 굳은 것이다. 크기가
2px 미만이면 맞춤을 미뤘다가 첫 배치 때 다시 맞춘다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
[초기화]가 화면 목록만 자동 배치로 되돌리고 edits/pipe_points.json은 그대로 두어,
페이지를 다시 열면 옛 관이 살아났다. B04와 같은 파일을 보므로 B04에도 그대로 남았다.
- DELETE /{project_id}/drainage/pipe-points 신설: 저장분과 파생물
(04_detailed_basins.geojson)까지 지우고 자동 배치 결과를 돌려준다.
- clear_pipe_points() 헬퍼 추가.
- B05 [초기화] 버튼이 이 경로를 쓴다.
- loadSaved / analyze / resetPipes가 같은 뼈대를 반복해 run() 하나로 묶었다.
검증: 초기화 전 {user:1, stream:1, spacing:2} → 초기화 후 {stream:1, spacing:3},
두 파일 삭제 확인, 재조회도 같은 자동 배치.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
pointerdown에서 유역 고르기 후보(basinClickStart)를 기억하는 코드가 실제로는 들어가
있지 않아, pointerup의 후보가 늘 null이었고 pickBasinAt()이 한 번도 불리지 않았다.
같은 편집에 묶여 있던 좌클릭 전용 제한도 함께 빠져 있어 우클릭·가운데 클릭으로도
마커가 잡히고 있었다.
- 좌클릭일 때만 pipeEditor.handleDown()을 부르고, 잡았으면 pipeClickStart로 기록
- 마커를 못 잡은 좌클릭은 basinClickStart로 남겨 뗄 때 유역을 고른다
- 700줄 유지: basinIndexOfPipe()를 _Drainage_Parts.ts로 이동
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
집중점 마커와 유입 외곽선이 세부유역 채움·관 마커 아래에 깔려, 켜도 무엇을 고른
것인지 보이지 않았다. 강도 색칠은 그대로 두고 마커·외곽선만 떼어 맨 마지막에 그린다.
- FlowStrengthOverlay.draw(): 계획선 강도 색칠만
- FlowStrengthOverlay.drawTop(): 집중점 마커 + 선택한 지점의 유입 셀 외곽선
- MapViewer 그리기 순서: 배수유역 오버레이 → 계획선 → 강도 색칠 → 세부유역·관 마커
→ 집중유역
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
하단 패널이나 우측 배수유역 패널을 늘리면 computeMapRect()가 지도를 뷰포트에 다시
맞춰(contain) 지도까지 함께 확대됐다. 배율이 바뀌니 방금 보던 자리를 다시 찾아야 했다.
화면 변환 계수(ax·bx)가 그대로가 되도록 배율·오프셋을 되계산해, 늘린 만큼은 확대가
아니라 더 넓은 범위로 채운다.
- preserveViewOnResize(): 이전 프레임의 변환 계수를 새 뷰포트에서 재현
- observeViewportSize(): 크기 변화를 지켜보며 위 보정을 걸고 다시 그린다
- 700줄 유지를 위해 fitCanvasToViewport / createProgressReporter / pipeMarkerColor도
_Drainage_Parts.ts로 이동
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
채움과 함께 그리던 번호가 등고선·흐름 화살표·관 마커에 가려 읽히지 않았다.
번호만 떼어내 프레임 맨 마지막에 얹는다.
- MapRender에 drawRingBadge()·ringCenterOnScreen()을 분리 노출.
drawFilledRing은 라벨이 있을 때 drawRingBadge를 부르는 형태로 바뀐다.
- B04: drawBasinNumbers() 호출을 관 마커 뒤로 이동(관이 없어도 번호는 그린다).
- B05: 채움은 라벨 없이 그리고 배지 자리만 모아 두었다가 배관 마커 뒤에 그린다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
구조물 조작이 테이블과 그래프로 나뉘어 있었다. 이동은 그래프 측점선, 추가·삭제는
테이블이라 어디서 무엇을 하는지 알기 어려웠다. 메뉴를 그래프 칸으로 옮겨 셋을 한
자리에 모은다. 테이블은 값만 보여 준다.
- mountStructureMenu의 부착 대상을 테이블 → 그래프 칸(.b05-profile__chart)으로 교체
- ProfileTableOptions.structureLines 제거
- CSS 블록명 b05-profile-table__context-menu → b05-profile-chart__context-menu
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 테이블에 얹던 구조물 세로선을 걷어냈다. 위치는 그래프 측점선이 이미 보여 주므로
같은 것을 두 번 그리는 셈이었다. 테이블에는 우클릭 메뉴만 남는다
(가까운 구조물이 있으면 삭제, 없으면 배관 추가).
- 드래그는 종단 그래프의 구조물 측점선에서 한다. createLongitudinalProfile에
onDragStation을 추가하고 kind === "irregular" 측점선에만 붙였다(좌클릭 전용).
- 좌측 구조물 폼에서 "배관" 항목을 고치거나 지우면 그래프와 배수유역도가 함께
갱신된다. DrainagePanel.setPipeChainages() 신설.
reconcilePipes()가 목록이 같으면 null을 돌려 관↔구조물 순환을 끊는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
데이터 흐름 문제
- B04 해석 산출물 7개(7.2MB)가 B05로 전량 복사되고 있었고, 관 지점 정본
(pipe_points.json)은 B05가 아예 참조하지 않았다. B04에서 확정한 관이 B05에
보이지 않고 진입할 때마다 자동 배치로 되돌아갔다.
- 사본은 "B05 편집이 원본을 덮어쓴다"를 막으려던 것인데, 외곽선 편집을 제거한
뒤로 B05는 아무것도 저장하지 않아 존재 이유가 사라졌다.
일원화
- B05 전용 모듈 3개 삭제: Engine_Drainage_Store / Engine_Drainage_Basin /
Router_Drainage. 두 화면이 B04_wf1_Surface/drainage/ 한 폴더를 직접 읽는다.
- POST /drainage/basins 폐기 → GET/PUT /drainage/pipe-points ·
POST /drainage/detail-basins 한 벌로 통합. 응답에 route_lonlat ·
main_polygon_lonlat · flow_arrows · upstream_lonlat · inflow_hotspots를 추가해
B05가 그리는 데 필요한 값을 같은 응답으로 받는다.
- 경로 확정 시 관 지점을 B04와 같은 저장소에 커밋한다.
B05 화면
- 유역 폴리곤을 눌러 고르기(지도에서도 선택), [집중유역] 토글, 관 개수·유역 수·
종단 Z 출처 요약 줄 추가.
- 관 마커는 좌클릭으로만 잡는다(우클릭은 메뉴, 가운데 버튼은 팬).
- 유역 목록은 3행까지 보이고 나머지는 스크롤.
종단 테이블 구조물 라인
- 관 매설 지점을 "배관" 구조물로 실체화(origin: "pipe"). 정본은 관 지점 파일이며
목록은 그 투영이라, 어디서 옮기든 pipeEditor 한 경로로 전파된다.
- 테이블 위 세로선을 끌어 이동(배관은 세부유역까지 재산정), 우클릭으로 배관
추가/구조물 삭제.
정리
- B05_wf2_Route/drainage/ 사본과 debug/(삭제된 Subdivide 엔진 검증 스크립트) 삭제.
- config DRAINAGE_B05_DIRNAME 제거.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
등고선을 전부 해석해 얻은 경계라 사람이 다시 그릴 이유가 없다(2026-08-01 사용자 지시).
남겨 두면 손으로 옮긴 외곽선과 1m 셀 라벨로 만든 세부유역이 어긋나 면적·관경의 근거가
깨진다. 외곽선은 이제 해석 결과를 그대로 표시만 한다.
제거 대상
- B05_wf2_Route_UI_Drainage_Boundary.ts (핸들 편집기)
- "유역선 편집" 버튼과 경로 확정 시 저장 여부 모달
- PUT /{project_id}/drainage/boundary 엔드포인트
- boundary_overrides 로드·저장·재부착 로직과 resample_boundary
- DRAINAGE_BOUNDARY_OVERRIDE_FILENAME / _HANDLE_SPACING_M / _MATCH_RADIUS_M
B05 저장소 모듈은 B04 산출물 사본 동기화만 남겨 245줄 → 55줄로 줄었다.
이미 저장돼 있던 boundary_overrides.json은 지우지 않았다(사용자 데이터라 그대로 둔다).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B04
- 세부유역을 눌러 고르면 그 유역만 진하게, 나머지는 옅게 물러난다. 관 마커를
눌러도 그 관이 받는 유역이 골라지고, 유역 밖을 누르면 강조가 풀린다.
- 고른 유역의 제원(측점·면적·표고차·유하장)을 상태 줄에 표기한다.
B05
- "배관 편집" 토글을 없애고 마커를 언제나 끌 수 있게 했다. 계획선을 그냥 누르는
것으로는 배관이 생기지 않는다 — 유역을 고르려 할 때마다 배관이 생기기 때문이다.
추가·삭제는 B04와 같은 우클릭 메뉴로 옮겼다.
- 배관을 옮기거나 넣거나 지우면 세부유역을 즉시 다시 나눈다(격자 해석 없음).
- "자동 제안" 버튼 이름을 "초기화"로 바꿨다.
- 노선 유입 강도 색칠을 B04 지도와 같은 색띠로 추가했다(토글 포함).
공용화
- common_util_drainage_detail: 1m 구간별 유입 면적 곡선을 응답에 포함(B04·B05 동일).
- B04_wf1_Surface_UI_FlowRamp.ts: 색띠·정규화·강도선 렌더러를 두 화면이 공유.
- ui_template_context_menu.ts: 지도 우클릭 메뉴를 공용 부품으로 분리.
- B05_wf2_Route_UI_Drainage_Parts.ts 신설로 패널을 700줄 규칙 안으로 되돌림(677줄).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 관 매설 추가·삭제가 안 되던 원인 수정: 메뉴 항목을 누를 때 pointerdown이
뷰포트로 전파돼 메뉴가 먼저 닫히면서 click이 발생하지 않았다. 메뉴 안에서 난
pointerdown/pointerup/contextmenu는 지도 조작에서 제외한다.
- 관 매설·세부유역 토글을 "세부유역" 하나로 합쳤다(따로 끄면 관을 옮겨도 유역이
보이지 않아 판단할 수 없다).
- 유입 집중점 마커를 흐름 강도 색칠에서 떼어 "집중유역" 전용 토글로 옮기고
기본을 꺼짐으로 두었다. 끄면 골라 둔 유입 외곽선도 함께 걷는다.
- 세부유역마다 서클 번호를 폴리곤 면적 중심에 얹었다(시점에서 종점 순).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
관 매설 지점을 기준으로 세부 배수유역을 나누는 기능을 B04 2D 지도에 추가한다.
경계는 B04 전처리 격자(03_road_routing.npz)의 road_slot — 1m 셀마다 물이 도달하는
도로 셀 — 을 담당 관으로 라벨링해 그 경계로 잡는다. 종단 Z는 경계를 긋지 않고
"도로 셀이 어느 관으로 흐르는가"만 정한다.
공용 승격 (B04 관리자 화면과 B05 사용자 화면이 같은 결과를 내야 함)
- common_util_drainage_detail.py: 관 보충(9)·세부유역 분할(10) 알고리즘
- common_util_drainage_context.py: 노선·종단 Z·좌표계 입력 준비
- common_util_drainage_pipes.py: 관 지점 정본 저장소(edits/pipe_points.json)
- common_util_route_profile.py: 종단 Z 해석기(계획고 > 경로 정점 > 지표면 > CSV)
- common_util_surface_sampler.py: B05 종횡단 sampler 이동
- B05 _prepare()의 노선 소스를 원청 계획노선 CSV로 정정(B04 격자와 누가거리 정합)
B04 신규 API
- GET /{project_id}/drainage/pipe-points 저장분 조회(없으면 자동 생성)
- POST /{project_id}/drainage/detail-basins 편집 중 목록으로 재분할(저장 안 함)
- PUT /{project_id}/drainage/pipe-points 모델 확정 시 관 지점·세부유역 커밋
B04 화면
- 관 마커 기본/자동/수동 색 구분, 계획선 스냅 드래그 이동
- 계획선 우클릭 "관 매설 추가" / 마커 우클릭 "관 매설 삭제"
- 표시 토글 2그룹(관 매설 / 세부 유역)을 유입 집중점과 분리
- "상세유역 분석" 버튼을 눌렀을 때만 재계산
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
간격 토큰이 4·8·16·24…만 있고 12가 없었다. CSS는 정의되지 않은 변수를 만나면 그 선언을
통째로 버리므로, `right: var(--spacing-12)` / `bottom: var(--spacing-12)`가 auto가 되어
절대 위치 요소가 offset 없이 원래 흐름 자리(좌상단)에 놓였다. B04 2D 지도의 객체 개수·
유역 결과·분석 진행 라벨 셋이 좌상단에 겹쳐 보이던 것이 이 때문이다.
- ui_template_theme.css에 --spacing-12: 12px를 정의한다(값의 유일한 정의처).
- 이 변수는 A07·B03·B04·B07·B11 등 10개 파일 31곳에서 쓰이고 있었고 그 선언이 전부
조용히 버려지고 있었다(패딩·간격이 0). 일부 파일에 남아 있던
`var(--spacing-12, var(--spacing-8))` 우회는 이 문제를 앞서 겪은 흔적이다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
지금까지 main.py는 Vite를 띄우기만 하고 종료를 시키지 않았다. 서버를 다시 띄울 때마다
이전 Vite가 살아남고, 포트가 차 있으면 Vite가 조용히 옆 포트로 올라갔다. 그래서 오늘
5173~5190에 13개가 쌓였고, 사용자가 오전에 뜬 인스턴스를 보는 바람에 하루치 변경이
화면에 반영되지 않은 것처럼 보였다.
- 종료 시 stop_frontend_dev()로 개발 서버 계통을 통째로 끝낸다. shell=True로 띄우면
실제 계통이 cmd.exe -> npm -> node라 부모만 죽이면 node가 남는다. Windows는
taskkill /T /F, POSIX는 프로세스 그룹으로 처리한다.
- 개발 서버 포트를 FRONTEND_DEV_PORT(기본 5173)로 고정한다(--strictPort). 포트가 막혀
있으면 조용히 옮겨가지 않고 그 자리에서 드러난다.
- 기동 전에 그 포트를 물고 있는 잔여 프로세스를 정리한다. 앞선 실행이 강제 종료됐을 때를
대비한 청소이며, 이게 없으면 --strictPort 때문에 기동이 실패한다.
실기동 검증: 기동 시 5173/8000만 뜸 -> API만 강제 종료해 고아 Vite를 만든 뒤 재기동하니
"포트 5173를 물고 있던 잔여 프로세스 30736 정리" 로그와 함께 5173을 회수했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
한 줄을 결과와 같이 쓰다 보니 분석을 돌릴 때마다 직전 결과가 지워졌다. 진행 문구는
우상단, 결과는 좌상단에 남겨 둘 다 동시에 읽을 수 있게 했다(2026-08-01 사용자 지시).
- WatershedOverlay에 busyElement(진행 전용)를 추가하고 sayBusy()로 갱신한다.
결과·오류는 종전대로 statusElement(좌상단)에 쓴다.
- 분석이 끝나면 진행 문구를 거둔다.
- 지도에 .b04-map__status-topright 자리를 신설했다. 객체 개수는 우하단
(.b04-map__status-corner), 유역 결과·흐름 강도 요약은 좌상단 그대로다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
세류가 도로를 가로지르는 자리가 대개 그 노선에서 가장 큰 유역을 받는데, 그 자리는
구역 경계라 구역별 선정 규칙으로는 영영 뽑히지 않았다. 실측 프로젝트에서 전체 유역의
89%(409,210㎡)를 받는 지점이 마커에서 빠져 있었다.
- 기본 관마다 관 ±최소간격 안에서 강도가 가장 큰 칸을 집중점으로 넣는다. 관 누가거리를
그대로 쓰지 않는 이유는 도로를 폭 4m로 굽는 과정에서 실제 유입 봉우리가 관에서 두어
걸음 옆에 놓이기 때문이다(관 149.73m, 봉우리 152m).
- 이 항목은 구역 번호 -1로 구분한다. 구역별 보충 후보 선정 규칙은 그대로 둔다.
- 관 자리와 같은 칸이 구역 쪽에서 다시 뽑혀 마커가 겹치는 것만 막았다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
흐름 강도 계산은 이미 trace_flow()가 원본 1m 격자에서 하고 있었고 03_road_routing.npz에
저장까지 되어 있었다. 이번 작업은 그 원본값을 밖으로 꺼내 화면에 그리는 것이다.
- 강도 곡선 출력 간격을 5m -> 1m로 바꿔 계산 원본을 그대로 내보낸다(구간 합, 평균 아님).
구간 기준을 round -> floor로 바로잡았다. 도로 셀 누가거리가 전부 0.5 배수라
numpy의 짝수 반올림이 짝수 칸에 3배를 몰아 2m 주기 빗살을 만들고 있었다
(도로가 격자축과 나란한 구간은 홀수 칸이 전부 0이라 색이 점선으로 나왔다).
- find_inflow_hotspots(): 도로를 시점·기본 관(세류 교차)·종점으로 잘라 구역을 만들고
구역마다 floor(길이 / 관 최대간격) + 3개를 뽑는다. 강도 최대점부터 고르되 고른 지점
양 편측으로 관 최소간격만큼을 후보에서 빼 한쪽 쏠림을 막는다. 관 쪽 경계에서도 같은
거리만큼 물러난다 - 그러지 않으면 그 관이 이미 받는 물 전부가 관 옆 칸에서 다시
최대값으로 잡혀, 정작 관이 없어 보충이 필요한 자리가 뽑히지 못한다.
- GET /api/projects/{id}/drainage/road-inflow 신설(B04_wf1_Surface_Router_Inflow.py).
저장된 road_slot으로 그 1m 구간에 귀속된 셀 마스크를 만들어 외곽선만 돌려준다.
새 그래프 탐색 없음. npz는 mtime 키로 프로세스 캐시에 둔다.
- 응답에 schema_version을 넣어 형식이 바뀌면 옛 저장분을 무시하고 다시 계산하게 했다.
- 프론트: B04_wf1_Surface_UI_FlowStrength.ts 신설. 계획선 위에 1m 구간 로그 레인보우와
유입 집중점 마커(크기=강도, 번호)를 얹고, 마커를 고르면 기여 셀 외곽선을 겹쳐 그린다.
마커 안쪽만 선택 대상이며 팬은 가운데 버튼 전용이라는 규칙은 그대로 둔다.
좌표 변환은 MapRender에 모았다(normalizedToScreen / lonLatToScreen / metricToScreen).
- 사이드 패널: 지면 필터·서피스·스무딩을 "지표면 분석" 한 컨테이너로 모으고 스무딩을
드롭다운(적용/미적용)으로 바꿨다. 포인트·모델 표시 옵션은 "모델 표시 옵션" 하나로
합치고 맨 아래에 점 크기·밀도를 [값][게이지] 형태로 놓았다.
- DRAINAGE_ROAD_WIDTH_M 주석에 설계 도로폭이 아니라 D8 대각 통과를 막는 해석용 굽기
폭임을 명시했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- ui_template_theme.css에 2D 지도 벡터 팔레트(--map-*) 33종을 유일한 정의처로 등록하고,
캔버스에서 CSS 변수를 읽는 공통 유틸 ui_template_palette.ts(themeColor)를 신설.
값은 한 번만 읽어 캐시하고 data-theme 변경 시 비운다(다크 전환 대응).
- B04 지도·유역 오버레이·흐름 화살표와 B05 배수유역도·유역선 편집·배관 마커의
하드코딩 색상을 전부 토큰 조회로 교체. 계획선 색·굵기, 후광색은 공용 함수로 일원화.
- B05 배수유역 패널의 사용자 문구를 전부 ui_locales로 이관(제목, 레이어 토글 5종,
도구 버튼 5종, 툴팁, 상태 문구 8종, 유역 제원 표기). B04 유역 분석 오버레이의
버튼·갈래 토글·진행/실패 안내도 함께 전환. 관리자 진단용 결과 판독문은 원문 유지.
- A02 프로그램 소개의 6단계 제목과 A01 히어로 문구의 단계 나열을 진행단계 이름
(전처리/종단설계/횡단설계/상세설계/수량산출/설계도서)과 일치시킴.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 진행단계 오버레이 버튼과 B그룹 페이지 제목을 파일입력/전처리/종단설계/횡단설계/
상세설계/수량산출/설계도서로 통일(ko/en). i18n 키는 유지하고 값만 교체.
B05 페이지 제목의 하드코딩 문구를 locale 참조로 교체.
- ui_template_resizer 공통 스플리터 신설. B05 하단 종단 패널은 위쪽 경계를 끌어
높이 조절(늘어난 만큼 그래프만 신축, 도면 테이블 높이는 고정), 안쪽 우측
배수유역 패널은 왼쪽 경계를 끌어 폭 조절(상한 = 하단 패널 폭의 70%).
크기는 sessionStorage에만 저장하고 CSS 변수로 적용해 접기 규칙과 충돌하지 않게 함.
- B04 2D 지도에 계획선 레이어 추가. 계획노선 좌표를 주는
GET /api/projects/{id}/planned-route 신설(B03 업로드 CSV → 사업지 좌표계 m).
선 색·굵기는 MapRender에 상수로 두고 B05 배수유역도와 공유.
- B04 지도 오버레이 재배치: 객체 표시 라벨은 우측 최하단, 배수유역 정보는 좌측 최상단.
- B04 지도·B05 배수유역도에서 좌버튼 드래그 팬 제거(가운데 버튼 전용).
유역선 핸들·배관 마커 편집은 좌버튼 그대로 유지, 팬 중에만 grabbing 커서.
- B05 배수유역도에 위성사진 표시 토글 추가(등고선 앞, 기본 on).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B04 하단 지도와 B05 배수유역도가 같은 규칙으로 열린다 — 계획도로 중심을 화면 중앙에
두고 도로 전체 + 사방 200m가 보이는 배율(2026-08-01 사용자 지시).
- computeRouteView()를 공용 렌더 엔진(B04_wf1_Surface_UI_MapRender)에 두어 두 화면이
같은 정의를 쓴다. 여유 거리는 ROUTE_VIEW_MARGIN_M 한 곳에서 정의.
- B04는 도로 범위를 알 방법이 없어 GET /surface/confirmed 응답에 route_bounds를 추가
(B03 계획노선 CSV 범위를 프로젝트 좌표계로 변환). 노선이 없으면 배경 전체 보기로 폴백.
- B05는 기존 상대 배율(0.85배) 대신 같은 함수를 쓴다.
- 표본 실측: 노선 239x166m -> 여유 포함 639x566m가 화면에 들어온다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 사용자 지정 기본값을 한곳(BACKGROUND_DEFAULT_ON / GIS_DEFAULT_ON /
CONTOUR_LABEL_DEFAULT_ON)에 모아 정의한다.
- 켜짐: 백지도, 위성, 시군구, 읍면동, 세류(전체)
- 꺼짐: 하이브리드, 연속지적도, 등고선, 도엽등고선, 표고점, 성절토, 옹벽석축, 등고라벨
- 유수방향 레이어는 화면에서 제외(목록에서 삭제)
- 명칭: 세류(하천중심선) -> 세류(전체), 배수유역 재산정 -> 유역 분석
- 유역 갈래 기본값(1차 꺼짐 / 2차 켜짐 / 유역방향 꺼짐 / 평균흐름 켜짐)은 기존과 동일
- B05 배수유역도 초기 보기는 도로 기준 줌인으로 되돌림(B04 하단 지도는 배경 전체 보기 유지)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지시(2026-08-01): 위성사진은 수치지형도 도엽과 같은 눈금으로 확보한다.
계획노선이 걸치는 기준 도엽만 받고(1매 또는 2~3매), 주변 도엽은 받지 않는다.
- sheets_for_points(): 기준 좌표가 속한 도엽번호만 반환(주변 확장 없음)
- satellite_extent(): 기준 도엽들의 도곽 합집합을 프로젝트 좌표계로 반환.
도엽을 못 구하면 라이다∪계획노선 범위로 폴백
- 다운로더: 주변 확장 로직 제거. 요청 범위를 덮는 타일만 받되, 한 변 타일 수가
한도를 넘으면 zoom을 낮춘다(도엽 1매를 zoom 18로 받으면 한 변 19타일 = 4,864px)
- 국가 GIS 벡터는 종전대로 라이다∪계획노선 범위 사용
- 표본 실측: 기준 도엽 1매(37816093) -> 10x13 타일, 2438x3169m, 0.95m/px, 15.1MB,
실패 타일 0개 (이전 731x853m)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3D(라이다)와 2D(브이월드)는 다루는 범위가 다르다. 그런데 2D 지도가 열릴 때 라이다
범위에 맞춰 확대하고 있어서, 배경을 넓게 받아도 화면에 보이는 범위가 늘 같았다
(2026-08-01 사용자 지적).
- 확보 범위: 계획노선·기준 좌표를 덮는 기준 박스 + 주변 박스(SURFACE_MAP_NEIGHBOR_RINGS=1)
= 3x3 배치. 미터/타일 여유폭 방식(SURFACE_MAP_MARGIN_TILES) 폐기.
해상도(zoom 18)는 브이월드 기본 스케일 그대로 — 화소를 키우는 것이 아니다.
- 타일 상한 15는 양쪽에서 균등하게 줄여 기준 박스가 가장자리로 밀리지 않게 한다.
- B04 하단 지도·B05 배수유역도는 확보한 배경 전체가 보이도록 열린다.
- 표본 실측: 기준 박스 372x401m -> 12x15 타일 = 1463x1828m (이전 731x853m).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
기존에는 vworld_*_meta.json이 있으면 무조건 건너뛰었다. B03 업로드가 부르는 전처리
경로는 rebuild=False라, 계획노선이 바뀌거나 여유 셀 설정을 바꿔도 옛 사진을 계속 썼다
(2026-08-01 사용자 지적: 트리거 시점 문제).
map_meta_covers()로 저장된 사진이 필요한 범위(라이다 U 계획노선)를 실제로 덮는지
확인하고, 못 덮으면 다시 받는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 요청 방향(2026-08-01): 해상도(zoom 18)는 그대로 두고, 계획노선과 기준 좌표를
덮는 타일 바깥으로 주변 셀을 더 확보한다.
- SURFACE_MAP_MARGIN_M(300m) 제거, SURFACE_MAP_MARGIN_TILES(3겹) 신설.
기존 하드코딩 1겹 -> 설정값. zoom 18에서 1겹 약 122m(위도 37deg).
- download_extent는 덮어야 할 범위(라이다 U 계획노선)만 돌려주고 여유는 타일 쪽에서 준다.
- 표본 실측: 덮을 범위 372x401m -> 10x11 타일 = 1220x1341m,
계획노선 사방 여유 474~588m (이전 731x853m).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
도엽 표시용 사본을 철회했지만, 이미 그 사본을 받아 둔 브라우저는 계속 그것을 쓴다
(보관함 키가 주소 기준이라 서버 파일을 지워도 남는다). DB_VERSION 1 -> 2로 올리고
업그레이드 시 기존 저장소를 버리도록 해 다음 접속에서 원본을 새로 받게 한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
배수유역이 어디까지 뻗을지 알 수 없어 도엽 자료를 잘라 두 벌로 나누지 않는다
(2026-08-01 사용자 지시). 분석 경로는 원래부터 원본을 읽었고 사본은 전송용이었으나,
사본 자체를 없앤다.
- B04_wf1_Surface_Engine_SheetView.py 삭제, SHEET_VIEW_* 설정 제거
- /geojson의 도엽 레이어는 원본 파일 그대로 + ETag로 전송
(재직렬화 제거만으로 요청당 2.0초 -> 0.006초, 두 번째 요청부터 304)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
저장분을 자동 표시하도록 바꾼 뒤로 진입 시 shown=true가 되어, 재산정 버튼을 누르면
분석 요청 없이 오버레이만 숨겨졌다(사용자 눈에는 무응답). 버튼은 언제나 재산정을
실행하도록 하고, 보이기/숨기기는 갈래별 버튼(1차/2차/유역방향/평균흐름)이 맡는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 도엽 병합본의 화면 표시용 사본 생성(B04_wf1_Surface_Engine_SheetView):
프로젝트 + 500m로 잘라내고 좌표를 소수 7자리로 줄여 등고선 37.3MB -> 0.97MB.
분석용 원본은 그대로 둔다(배수유역은 상류까지 넓은 범위가 필요).
- /geojson의 도엽 레이어를 파일 그대로 + ETag로 전송 — 매 요청 2.0초 재직렬화 제거(0.008초).
- /vworld-map도 ETag 전송으로 바꾸고, 프론트가 붙이던 `&_t=` 시간꼬리표 제거.
- 도엽 레이어를 브라우저 보관함 경유로 조회하고 준비화면에서 미리 담는다.
- 배경 지도 범위 = 라이다 범위 + 계획노선 범위 + 여유 300m(SURFACE_MAP_MARGIN_M).
- 도엽 기준 좌표 = 계획노선 시점·종점(없으면 라이다 중심). 같은 도엽이면 9매,
이웃 도엽에 걸치면 12매. 표본 프로젝트는 기존 9매와 동일(회귀 없음).
- 선정에서 빠진 도엽 zip 정리(prune_sheets) — 표본에서 30매 중 21매가 다른 지역 잔재.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- GET /surface/confirmed 추가: 확정 구성(모델·필터·표현·평활·등고선간격)과
지형 가장자리만 반환(수 KB, 0.02s). 진입 판정·준비화면·B05의 단일 출처.
- B05 진입이 받던 포인트클라우드 JSON 23.8MB 제거 — 실제로 쓰던 값은 bounds뿐.
- 준비 표식을 프로젝트 ID에서 확정 signature로 변경: B04에서 다시 확정하면
대시보드 복귀·새 브라우저·B그룹 단계 이동 어느 경로로 들어와도 최신본을 담는다.
- preloadSurfaceAssets가 평활 여부를 추측하던 부분 제거(확정 저장값 사용) —
추측이 어긋나면 같은 지형을 두 번 내려받았다.
- B04 진입 시 필터·표현·평활·등고선간격을 확정본 값으로 초기화(확정 없으면 기존 기본값).
- 모델 확정 직후 준비 표식과 B05 세션 캐시를 비워 옛 지형이 남지 않게 함.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- B11_Status_UI_Loading + 라우트 b11-loading: 공통 프로그레스 서클로 단계·진행률 표시,
끝나면 원래 가려던 화면으로 자동 이동
- goToWorkflowStage: 아직 준비하지 않은 프로젝트면 준비 화면 경유, 같은 프로젝트로
다시 들어오면 건너뜀(탭 단위 기억). 다른 프로젝트면 보관분 교체
- 선적재 범위: 확정 지표면 3D + 그 등고선만 (종단·횡단은 0.86MB·0.06초로 이미 즉시라 제외,
배수유역·포인트클라우드도 제외)
- 실패 시 자동 이동하지 않고 담당자 연락 안내 + [그래도 이동]/[대시보드로]
- B04 등고선 간격 시작값을 B05 저장값과 공유(B04 변경은 DB에 쓰지 않음)
- 새 문구는 ui_locales에 한국어·영어 등록
- 휠 위 = 축소로 반전, 커서 지점을 축으로 한 dolly를 공용 유틸에서 직접 처리
- 회전 중심을 작은 구로 표시(돌리는 동안만, 화면상 크기 일정, 항상 위에 그림)
- 등고선 렌더 비용 감소: 폴리라인을 주곡선·보조곡선 2덩어리로 병합(드로우콜 424 → 2),
라벨은 카메라가 움직였을 때만 재배치
- common_util_http_cache: 파일 mtime+크기 ETag, If-None-Match 일치 시 304
(preview·contour 적용, 파일이 바뀌면 자동 무효화)
- A00_Common/b_asset_cache: IndexedDB 보관함(키 = projectId|url, 값 = 바이트+ETag).
보관본 즉시 사용 후 백그라운드 재검증, 3D는 보관 바이트를 직접 파싱
- 프로젝트 전환 시 타 프로젝트 보관분 삭제, 대시보드→B그룹 이동 시 확정 모델의
3D 프리뷰·등고선(1.0m) 미리 받기(포인트클라우드 제외)