[1] 수평선이 곡선에서 떨어져 보이던 문제. 엔진은 포물선으로 교점을 잡는데 곡선만
직선(polyline)으로 그리고 있었다. 평형선·장비 경계현·평균운반거리선의 양 끝이
곡선 위가 아니게 되어 어긋나 보였다.
곡선을 2차 베지에 경로로 바꿨다. 제어점 (x0 + Δ/2, V0 + a0Δ/2)에 두면 2차 베지에가
구간 포물선과 정확히 같아진다. 0선 아래 음영도 같은 경로로 닫고, 띠 테두리도
측점만 잇던 것을 구간마다 4등분해 곡선에 붙였다.
[2] balloon 위치 저장 경로를 둘로 나눴다.
- 프론트 캐시(localStorage, 프로젝트+경로별 키): 끌어 옮기는 즉시
- 영구저장소: 횡단 확정 시 mass_haul.balloon_offsets로 저장
진입 시에는 영구저장소 값이 이긴다 - 다른 브라우저에서도 같은 자리에 뜬다.
상세 응답에 balloon_offsets를 실어 내려보낸다.
[3] 범례 줄에 "도형 위치 초기화" 버튼(분배 레이어를 켰을 때만). 프론트 캐시를 비우고
다시 그리며, 비워진 값이 다음 확정 때 영구저장소를 덮는다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
참고 도면(기번3, 측점별 누가토량 81점 + balloon 43개)과 대조해 오류 2건 확인·수정.
[1] 측점 사이는 직선이 아니라 포물선이다. 단면적이 선형으로 변하면 그 적분인
누가토량은 2차식이 된다. 도면에서 측점간격 20m 구간의 반종거가 20/√2 = 14.14m로
12번 반복해 찍히는 것이 근거(직선이면 10m). 직선으로 재던 평균운반거리가 약 40%
짧게 나와 20m 경계 판정이 어긋나고 있었다.
MassHaulPoint에 다짐환산 순단면적을 실어 구간마다 V(t) = V0 + a0t + (a1-a0)t²/(2Δ)를
세운다. V(Δ) = V0 + (a0+a1)Δ/2라 곡선 자체는 그대로고 현 길이만 바뀐다.
두 단면적의 평균이 구간 평균과 어긋나면 포물선이 끝점을 벗어나 수평선 교점을 못 찾고
블록이 통째로 늘어난다(도면 곡선 검증에서 성토 1455㎥가 한 블록에 묻혔다). 두 값을
같은 양만큼 옮겨 끝값을 강제로 맞춘다. 곡률은 보존되므로 포물선 모양은 그대로다.
[2] 남은 사토와 토취를 거리 가까운 짝부터 맞물려 장거리 운반으로 바꾼다. 도면 곡선은
0선 아래로 한 번도 내려가지 않는데 기존 로직은 토취 1435㎥를 만들어 냈다. 도면의
덤프 L=935/1008m가 이 장거리 운반이고, 배분 3원칙 ①(거리 최소) ③(모아서 운반)이다.
- 사토 표기에 측점(M.N) 추가 - 도면은 사토에 운반거리를 안 매긴다
- 검산 칩: 운반(띠) + 장거리 운반 + 토취 = 총 성토량
- 장거리 운반선은 1점쇄선 + 화살촉 (네 번째 선타입)
- 700줄 초과로 곡선 기하를 _UI_MassHaul_Curve.ts로 분리
도면 곡선 재현: 토취 1435 -> 0, 사토 2606 -> 1171(= 최종 누가토량),
운반계 오차 -10.1% -> -0.80%, 종무대 L 0.2~13.2 -> 10.51~18.01m(도면 8.39~15.98).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
누가토량 곡선은 "얼마가 남는가"만 말한다. 어디 흙을 어디로 얼마나 옮기는지를
뽑아내는 계층을 얹었다 — 평형선, 운반 블록, 운반토량 Q, 평균운반거리 L,
EA/RR/BR 안분, 장비 선정.
작도 규칙 근거는 clouds-daily.tistory.com/249 와 교과서 표준 작도법이다
(참고 도면 3공구의 수치·작도는 근거로 삼지 않았다).
평형선을 0선 하나로 고정하면 임도처럼 절토가 우세한 노선에서 사토가 전부
종점 한 덩어리로 몰린다. 그래서 곡선을 왼쪽부터 훑으며 커서를 옮기고, 성토가
절토를 다 못 받는 자리에서 평형선을 계단으로 옮긴다. 구간이 겹치지도 비지도
않고 단차의 합이 최종 누가토량과 정확히 맞는다.
- 신규 _UI_MassHaul_Balance.ts: computeHaulPlan() 순수 계산기
- 신규 _UI_MassHaul_Balance_View.ts: 계단형 평형선 + 반종거 수평선 + 육각 balloon
- MassHaulPoint에 cut_rr_m3/cut_br_m3 추가 (블록별 암종 안분 입력)
- EARTHWORK_HAUL_EQUIPMENT_LIMITS_M을 context 응답으로 노출 (프론트 사본 없음)
- massHaulPayload에 haul_plan 직렬화 (B08 인계)
검증: 수동 6종 + 무작위 100건에서 보존·안분합·L 범위·구간 무결성 성립.
렌더 스모크 4개 크기 NaN 0건. 영구저장소 프로젝트(26측점) 실측 시 블록 6개,
토취 75.4㎥가 최종 누가토량 -75.4㎥와 일치.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 면적표 값·머리글을 가운데 맞춤으로 바꾼다.
- 값 칸을 모든 카드에서 버튼으로 만든다. 선택되지 않은 카드에서 눌리면 부모에 측점과 키를
함께 올려, 카드 선택과 면적 강조가 한 번에 반영된다. 강조 상태는 부모가 들고 있다가 카드를
다시 그릴 때 되살리고, 측점이 바뀌면 따라가지 않는다.
- 카드 그리드 빈 자리를 누르면 선택을 해제한다.
- 접어도 빈 배경이 남던 문제: 인라인 min-height가 .is-collapsed { height: auto }를 이겨
360px 상자가 그대로 남았다. CSS 변수로 넘기고 :not(.is-collapsed)에만 건다.
- 접기 손잡이를 헤더 캐럿에서 패널 하단 가운데 삼각형 손잡이로 옮긴다. 좌측 사이드 패널과
같은 공용 컴포넌트를 90° 돌린 모양이며, 위로 접히는 패널이라 collapseToward 옵션에
"up"/"down"을 추가했다(기존 좌우 호출부는 그대로). 리사이저는 손잡이 위로 14px 올렸다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 종단면도 이름표를 플롯 안쪽 상단으로 겹치고 LONG_PAD.top 30 → 12로 줄여 위 여백을 그래프
몫으로 돌린다. 구조물 라벨은 그만큼 내려 겹치지 않게 했다.
- 유토곡선에 같은 양식의 이름표를 하단에 넣는다. 곡선이 지나가는 자리라 불투명 배경판을 깔고
아래 여백을 16 → 8로 줄였다.
- 상단 패널과 횡단 카드 사이의 횡단면도 제목·개수 행을 없앤다. 카드마다 측점이 적혀 있어
무엇을 보는지 이미 분명하고, 공간만 먹었다. 관련 CSS와 로케일 키도 정리.
- 종단 기준 곡선을 기본 비활성화한다(계획고 기반 개략값이라 참고용). 세션 저장 키를 v3로 올려
옛 값이 이 곡선을 되켜지 못하게 했다.
- 면적표 단위를 값 칸에서 좌상단 교차 셀로 옮기고, 열 제목을 가운데 맞춤으로 바꿨다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 면적 하이라이트가 먹지 않던 원인: 값 칸·밴드 클릭이 카드까지 버블링돼 측점 선택이 다시
걸리고, draw()가 카드를 새로 만들면서 방금 켠 강조가 즉시 지워졌다. stopPropagation 추가.
- 면적 표기를 칩 나열에서 절토/성토 2행 × EA·RR·BR·계 4열 표로 바꾼다. 이름은 도면 표기를
그대로 쓰고, 0값이어도 항목을 유지해 카드끼리 비교가 되게 한다. 성토는 완성 단면이라
지반유형으로 갈리지 않으므로 계 한 칸만 쓴다.
- 암반 밴드는 하나뿐이라 그 측점의 암종에 해당하는 칸만 강조 버튼이 된다.
- 유토곡선 0선에 Y축 눈금값 0을 적어 무슨 선인지 읽히게 한다(선 자체는 원래 상시 표시).
- 오버레이가 1줄에서 3행 표가 되어 상단 여유를 28 → 58px로 키웠다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 횡단 카드 측점 종류 표기에서 "일반 측점" 제거(BP/EP만 남김).
- 구간 물량을 패널 아래 칩 줄에서 유토곡선 위 둥근 사각 말풍선으로 옮긴다. 말풍선이 놓일
가로 구간의 곡선 세로 범위를 실측해 위/아래 빈 곳 중 들어가는 쪽에 놓고, 좌우 후보를
모두 재서 여유가 큰 조합을 고른다. HTML 오버레이 대신 SVG 안에 그려 X축 정렬을 지킨다.
- 패널 제목 문구 삭제. 헤더는 캐럿만 남긴 손잡이 행이며, 캐럿은 좌측 사이드 패널과 같은
공용 규칙을 쓰되 방향만 상하(펼침 ▴ / 접힘 ▾)로 바꿨다.
- 측점 라벨을 종단 그래프 바닥에 붙이고 유토곡선 상하 여백을 좁혀 두 그래프가 측점 표기를
공유하는 것처럼 보이게 한다. 좌우 여백(LONG_PAD)은 X축 정렬 때문에 그대로 둔다.
- 패널을 줄이면 그래프 폭까지 줄던 문제: SVG가 flex 기본값으로 세로로 눌리면서
preserveAspectRatio(meet)가 가로도 같은 비율로 축소한 것. flex: none으로 막고 패널에
최소 높이를 건다.
- 토사 단일 환산·환산 없음 곡선 삭제. 절토가 암반 경계선으로 갈려 나온 뒤로는 부피비를
단일값이나 1로 넣은 곡선에 정보가 없다. 곡선 키 형식이 바뀌어 세션 저장 키를 v2로 올렸다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
절토부의 토사·암반 구분은 환산계수가 아니라 횡단도 기하로 갈린다. 지표면~암반 경계선이
토사, 그 아래가 암이다. 기존에는 측점당 절토 단면적이 하나뿐이라 리핑암/발파암 측점의
상단 토사층까지 암 환산계수로 곱해졌다(실데이터 기준 다짐환산 +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>
임도는 산복 사면을 따라가 편절·편성이 지배적이라, 종단 계획고로 본 절성토 균형과
실제 횡단 단면적으로 본 균형이 크게 어긋난다. 어느 쪽을 정식 기준으로 삼을지
사용자가 그래프를 보고 결정할 수 있도록 두 기준을 한 축에 겹쳐 그린다.
지반유형 처리도 암반 경계선 분리 전까지는 미결이라 세 가지를 함께 낸다.
법령 근거([임도의 설계 및 시설기준] 별표):
- 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>
상세 배수유역 정보는 페이지에 들어오면 바로 보여야 하는데 기본값이 접힘이었고,
접기/펼치기 화살표도 반대를 가리키고 있었다.
- 기본값: 저장값이 없을 때 `!== "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>
참고 도면 `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 해석 산출물 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>
흐름 강도 계산은 이미 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>
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>
- B11_Status_UI_Loading + 라우트 b11-loading: 공통 프로그레스 서클로 단계·진행률 표시,
끝나면 원래 가려던 화면으로 자동 이동
- goToWorkflowStage: 아직 준비하지 않은 프로젝트면 준비 화면 경유, 같은 프로젝트로
다시 들어오면 건너뜀(탭 단위 기억). 다른 프로젝트면 보관분 교체
- 선적재 범위: 확정 지표면 3D + 그 등고선만 (종단·횡단은 0.86MB·0.06초로 이미 즉시라 제외,
배수유역·포인트클라우드도 제외)
- 실패 시 자동 이동하지 않고 담당자 연락 안내 + [그래도 이동]/[대시보드로]
- B04 등고선 간격 시작값을 B05 저장값과 공유(B04 변경은 DB에 쓰지 않음)
- 새 문구는 ui_locales에 한국어·영어 등록
분석이 30초 걸리는데 B05는 일반 사용자 화면이다. 관리자 확인용 B04에서
한 번 돌려 저장하고, B05는 그 결과를 읽어 관 보충과 세부유역만 처리한다
(2026-07-31 사용자 지시).
노선 원천 변경
- B05 확정 경로 -> B03 업로드 계획 노선 파일(CSV). 분석이 노선 설계보다
먼저 끝나 있어야 하기 때문. 샘플 planned_route_sample_epsg5187.csv 로 검증.
- common_util_route_geometry.py 신설 — RouteVertex/StructureCandidate/누가거리
보간/세류 교차점/계획 노선 CSV 리더. B04와 B05가 같은 표현을 쓰도록 공용화.
열 이름은 대소문자·한글 표기를 함께 받는다(B03이 여러 형식 수용 예정).
B04 (관리자 확인용, 신규)
- Engine_Watershed_{Grid,Stream,Descent,Flow,Expand,Export} — B05에서 git mv
- Engine_Watershed_Analyze.py — 1~8단계 오케스트레이션
- Router_Watershed.py — GET /drainage/primary-region
- UI_Watershed.ts — 2D 지도 GIS 레이어 그룹에 "배수유역" 토글 추가.
격자/화살표/세류망/1차영역/2차유역/기본관을 겹쳐 그린다.
- 저장 위치 B05_wf2_Route/drainage -> B04_wf1_Surface/drainage
- 03_road_routing 단계 추가: B05가 세부유역을 나눌 최소 배열(셀->도로셀 귀속,
유하장, 강도, 도로셀 제원, 셀 표고) + 계획도로선/기본배관/2차유역 기하
B05 (일반 사용자용, 축소)
- Engine_Drainage_Basin.py — B04 산출물 로더 + 관 보충(9) + 측구 라우팅/세부유역(10,11)
- Engine_Drainage.py 는 관경 산정만 남기고 322 -> 27줄
- Router_Drainage.py 509 -> 142줄. POST /drainage/basins 만 남김
- 화살표·격자·강도 띠 렌더 제거. 계획도로선/기본배관/2차유역만 받는다
삭제
- _legacy_watershed/ 4파일 (능선 행진 방식 원본 보관본)
- Engine_Watershed_Basin.py (B04 Analyze + B05 Drainage_Basin 으로 분할)
- GET /drainage/candidates 와 propose_structure_stations (구방식 후보 제안)
E2E 검증 (실데이터)
B04 분석 28.2s -> 저장(geojson 11KB + npz 2.6MB)
B05 로드 + 세부 설계 0.11s <-- 30초가 0.1초로
면적 457,404m2 로 B04 2차 유역과 정확히 일치
관 편집 재산정 0.12s, 관 3개 -> 세부유역 3개, 면적 보존
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>