- `docs/` 를 .gitignore 에서 빼 git 추적 대상으로 전환 (위키·완료 이력·검증 기록) - `docs/raw/PLAN.md` · `docs/raw/OWNERS.md` 를 저장소 최상위로 이동 후 .gitignore 에 등록 — 창끼리 공유하되 저장소에는 안 올리는 장부 - 살아 있는 경로 참조 7개 파일 정정 (아카이브 107건은 그때 사실이라 그대로 둠) - graphify 날짜별 산출물(`docs/wiki/graphify-out/20*/`) 제외 — `graphify update` 가 다시 만듦 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
35 KiB
2026-09-03 완료 항목 이관
사용자가 완료 항목의 위치 정리를 요청했으며, 요청에 따라 위키 관리자의 2차 교차검증과 별도 검증보고서는 생략했다.
docs/raw/PLAN.md에서 완료 체크 항목과 그 하위 원인·조치·자체검증 설명을 이관했다.
2026-09-03 화면 개선 (메인 창 · B05·B06 담당)
-
I형 집수정 배관이 횡단도에 삼각형으로 그려짐 (사용자 항목 4).
- 원인 —
B06_Section_UI_Cross_Culvert_Solve.tspipeAxisSolver.corners()가 관 끝단 두 꼭짓점을 마감면(I형 벽 안쪽 변) 선분 안으로clampToFace하는데, 원지반이 벽 상단 위라 관 시작점이 벽 상단에 붙으면 위·아래 교점이 같은 끝점으로 접혀 사각형이 삼각형이 됨. 13+4.1 실측 — 관 폴리곤[[594.6,418.7],[338.9,537.3],[348.5,505.4],[594.6,418.7]](1번=4번 꼭짓점 동일), 집수정 벽 상단y=419= 관 시작점y=418.7. - 조치 — 자른 끝단 길이가 관경보다 짧으면(비스듬히 자르면 항상 관경 이상) 접힌 것으로
보고 축 직각 마감(fallback) 으로 되돌림. 편집 단일 창구인
corners()한 곳만 수정. - 자체검증 — 공용 브라우저 B06(8+17.3·13+4.1 등 8개 단면) 실측:
수정 전 유입측 끝단 길이
0.0 px(세월교 1건 제외 전부), 수정 후18.7~58.4 px로 전부 살아남.npm run typecheck통과, prettier 무변경. - 2차 수정 (2026-09-03 사용자 지적 「측벽과 배관의 형상이 교차하고 있어야 함」) — 1차 수정은 삼각형만 없앴을 뿐 관이 벽 위에 얹혀 벽과 만나지 않았음. ㄴ형과 대조해 (관이 바닥판 윗면에서 시작해 벽 안에 물림) 원인 확정: I형 관 하단이 벽면×원지반 교점인데 원지반이 벽 상단보다 높으면 교점이 상단으로 밀림. 교점을 벽 상단에서 관경+여유(0.5m) 아래로 제한해 관이 벽을 관통하게 함. 벽을 키우는 안은 벽 기울기(1:0.3)로 base 가 계류측으로 밀려 벽이 7.5m 까지 자라 폐기.
- 2차 자체검증 — I형 8개 단면 관·벽 세로 겹침
18.1~56.4 px(수정 전 0). ㄴ형 대조는 13+4.1 을 조정창에서 ㄴ형으로 바꿔 확인 후 세션값 원복. pytest 370 passed·17 skipped. - 육안검증 기록(아티팩트): https://claude.ai/code/artifact/c4ef706c-c3d8-461c-ae54-6c376980c043
- 원인 —
-
유토곡선 세부 항목이 리로딩 중 보였다가 사라짐 (사용자 항목 3) — 원인 규명 완료.
- 재현(공용 브라우저 30ms 폴링) — 2.0초 그림: 절토 6,908 / 성토 42,050 / 운반 5,571㎥, 평형선 6·장비 띠 9·balloon 12. 3.5초 그림: 절토 3,704 / 성토 14,881 / 운반 0㎥, 평형선 1·띠 0·balloon 1.
- 원인 —
B06_Section_UI_Page.ts:285 reconcileStaleDesigns()가 저장분 횡단 설계 중 현재 종단 계획선과 어긋난 측점을 일괄 재계산해 제자리 교체함. 첫 그림은 재계산 전 저장분(20m 구간당 성토 860㎥ — 임도에 불가능한 값), 둘째가 정본. 캐시 덮어쓰기· 숨김·토글 문제 아님(범례는 두 시점 모두 「토량 분배」 켜짐). - 벌룬이 정본 상태에서 안 생기는 이유 — 성토 14,881 vs 절토 3,704(4배)라 누가토량 곡선이 0선을 한 번도 넘지 않아 평형선 계단이 서지 않음. 극값 가지치기 기준(범위×2%) 탓이 아님 — 실무 6건은 같은 기준으로도 극값이 14~53개 남음.
- 실무 원본 대조(
유토곡선.MASS6건 파싱) — 최종 누가토량 +49 ~ +324㎥, 0선 교차 3~17회. 용화는 −11,094㎥ · 교차 0회. 실무EARTH.DAT헤더 6건 전부 무대 20.0 / 도자 60.0 m (현행 구현은 20/70). - 조치 — 사용자 확정(2026-09-03 「절·성토 불균형 판정은 사용자 몫, 자동 조정 금지」)에 따라 진단만 노출: 유토곡선 요약줄에 「최종 누가토량」 칩 신설(툴팁에 균형 의미와 평형선 미생성 사유). B05·B06 공용 함수라 양쪽에 함께 뜸.
- 지식DB — 유토곡선_토량배분 신설(실무 6건 관측표·장비 한계거리 후보·근거 공백 명시), 미결 20·21 등재.
- 자체검증 — 공용 브라우저 실측: 요약 칩이
절토(자연) 3,704.6㎥ · 성토 14,881.8㎥ · 토취 11,094.6㎥ · 최종 누가토량 −11,094.6㎥ · 운반토량 계 0㎥ · 운반·성토 검산 −3,787㎥로 표시됨.npm run typecheck통과, prettier 통과.
-
옛 계획고 유토곡선 노출 차단 + 사면 미교차 경고 (2026-09-03 사용자 확정).
- 「새 값만 보여주기」 — 저장 횡단이 지금 계획선과 어긋나면(재계산 예약) 유토곡선을
그리지 않고 안내만 띄움. B05·B06 양쪽 적용(
staleDesignChainages공용 판정). - 「사면 미교차는 경고로 대체」 — 사면이 계산 반폭(±20m) 끝까지 원지반과 안 만나 면적이
잘린 측점에 카드 경고. 판정은 면적을 내는 엔진 한 곳(
B06_Section_Engine_Design)이slope_unclosed로 내림 — 화면·수량·도면이 같은 기준을 봄. 계산은 무수정. - 실측 근거 — 용화 65측점 중 56개가 낡음, 계획고 차 −9.36~+5.83m(예: 0+20 저장 875.36 → 현재 870.26, 저장분 성토 단면 85.9㎡ / 43+0 지점 256.4㎡).
- 자체검증 — 공용 브라우저: 2.6초 「재계산 중」 안내만(옛 값 미노출), 4.4초 정본 표시,
사면 미교차 경고 13/65측점.
pytest 366 passed·17 skipped, typecheck·prettier 통과.
- 「새 값만 보여주기」 — 저장 횡단이 지금 계획선과 어긋나면(재계산 예약) 유토곡선을
그리지 않고 안내만 띄움. B05·B06 양쪽 적용(
-
B05·B06 유토곡선 일원화 (2026-09-03 사용자 지시 「하나의 데이터를 두 페이지에 보여 주는 기능이니 로직·템플릿이 다르면 일원화」). 갈림 3곳을 모두 한 벌로.
- 보는 노선 — B05는 최신 경로(
get_latest_route), B06은 최신 확정 경로만 열어 노선을 다시 탐색한 프로젝트에서 서로 다른 노선을 봤음. 실측: B05 route 126(DRAFT) / B06 route 125(CONFIRMED), 같은 20m 측점 계획고 870.26 ↔ 875.36 · 성토 4.82㎡ ↔ 85.9㎡. →get_workflow_route_context()(최신 경로) 신설, B06 화면 context가 사용. 납품 도면(B07)이 쓰는 확정 전용 창구는 그대로 둠. - 횡단 재계산 창구 — 호출이 두 벌이라 인자가 갈림(B06만 표준 단면값·암 경계 오프셋
전달, 보존 사용자값 2개 ↔ 7개). →
B06_Section_Cross_Refresh.refreshCrossDesigns()하나로 통합, 세션 편집값은 저장소에서 직접 읽어 패널 없는 B05도 같은 값을 보냄. - 낡음 판정 — 「옛 암 2단계 필드 누락」 조건이 B06 페이지에만 있어 B05는 재계산을
건너뜀(실측 절토 합 228.52㎡ ↔ 270.12㎡). → 공용
staleDesignChainages()안으로 이관. - 자체검증 — 공용 브라우저 실측: 두 화면 모두 route 126, 요약줄 문자열 완전 일치
(
절토(자연) 4,526.8㎥ · 성토 14,881.8㎥ · 토취 10,213.3㎥ · 최종 누가토량 −10,213.3㎥ · 운반토량 계 0㎥ · 운반·성토 검산 −4,669㎥).pytest 370 passed·17 skipped(일원화 소스검사 4건 신설tmp/tests/test_masshaul_single_source.py, 기존 stale 규칙 테스트 1건은 조건 이관에 맞춰 갱신), typecheck·prettier·ruff 통과.
- 보는 노선 — B05는 최신 경로(
초기 계산 실패 처리 후속
initial_design.failed마커 — 백필·재확정 적용 둘 다 안 함(2026-09-03 사용자 결정). 새 실패만 마커를 남기는 현행 유지.
LAS 없는 설계 — 곡선 경고 판정 후속
- 지표면 종류별 계곡 시설 차이 — 원인 조사 완료(2026-09-03).
- 시설 종류는 유효직경 하나로 갈린다: 1,500mm 초과 = BOX암거, 2,000mm 초과 = 세월교,
그 이하는 규격 스냅(800·1000·1200·1500). 임계 유량 실측 — BOX
3.711 ㎥/s, D8001.056 ㎥/s. - 저장 산출물 대조(같은 노선, 두 번의 LAS 해석): 200.9m 유역이 임계 위에 아슬아슬하다 —
면적 28,907㎡ → D
1,529.3mm, 29,209㎡ → D1,537.3mm. 임계 1,500mm 를 2% 차이로 넘는다. 면적이 1~2%만 작아지면 그대로 관(D1500)으로 내려간다. 같은 LAS 해석끼리도 면적이 1.0% 흔들린다(격자·트림 차이). - 반면 관측된 BOX → 관D800 은 그 흔들림으로 설명되지 않는다. D800 이 되려면 설계유량이 3.5배(면적 기준 약 1/3.5) 줄어야 한다 — 표고 해상도 차이가 아니라 유역 분할 자체가 달라진 것이다. 같은 관측에서 4번째 시설 자리가 275.71m → 297.71m 로 옮겨진 것이 그 신호(관 위치가 바뀌면 유역 귀속이 통째로 재배분된다).
- 149.7m 유역은 414,106㎡ · D
4,719mm로 세월교 판정 — 관측과 일치.
- 시설 종류는 유효직경 하나로 갈린다: 1,500mm 초과 = BOX암거, 2,000mm 초과 = 세월교,
그 이하는 규격 스냅(800·1000·1200·1500). 임계 유량 실측 — BOX
B08 CAD 후속
- 도각 편집 안내 띠 — 이미 해결돼 있음(2026-09-02 사이드바 액션 1행으로 이동).
2026-09-03 화면 실측: 띠는
.b07-drawing-actions안(사이드바 하단 y=1243)에 평소 숨김 상태로 있어 CAD 리본과 겹칠 수 없음. 코드 변경 없음. - SVG 서명 — CAD 벡터로 변환(2026-09-03 사용자 결정).
_Engine_Cad_Svg신설(path M·L·H·V·C·Q·S·T·Z, 곡선 16분할, viewBox 비율 유지·y 뒤집기). 래스터는 종전대로 ImageEntity.- 화면 검증 불가(2026-09-03) — 회사 자산 폴더(
storage/1/assets/)의 서명·로고가 전부 PNG라 SVG 경로를 탈 자산이 하나도 없다. 단위 검증 (tmp/tests/test_b07_signature_vector.py5건)만 선 상태. 화면으로 보려면 SVG 서명을 한 장 올려야 하므로 사용자 판단 대기(시험용 SVG 업로드 여부).
- 화면 검증 불가(2026-09-03) — 회사 자산 폴더(
B08 횡단도·장 배치 후속
- 장 단위 확정 흐름 실측(2026-09-03) — 용화 검증본
d6997dd93장(cross_s00220m)을 실제로 확정해 결함 3건을 찾아 고침(커밋4fdbcaf0).- ① 수량표 역추출이 측점을 구분하지 않음 —
_table_values_from_cells()가 도면의 표를 전부 훑어 마지막 값을 모든 측점에 기록(실측: 4측점 전부 지반고837.21, 도면에는 840.87/840.33/836.45/837.21). 표 엔티티 iduuid5(_ENTITY_NS, f"{drawing_id}:qtable")로 그 측점 표만 읽고, 못 찾으면 옛 도면 폴백. - ② 계획고가 통째로 빔 — 장 배치 입력 원본에 계획고가 없어 21항목 중 지반고 1개만 채워짐.
_quantity_table(source, design)이 횡단 설계의design_elevation_m도 보게 함. - ③ 확정 해제(invalidate) 404 — 도면 목록을
designs없이 만들어 장 나눔이 달라짐. 목록·확정과 같은 인자를 쓰게 함. - 자체검증(백엔드 재시작 후 실동작) — invalidate
404 → 200, 표 값이 측점마다 다름 (ground=840.87 planned=840.87 fill=0.00·ground=831.72 planned=836.64 fill=4.92),manifest.json.quantity_tables5측점(220·240·260·264·280) 각각 4/21 항목 채움 (나머지 17칸은 CAD 에서 사용자가 채우는 자리). 시험 확정은 전부 해제해 원상복구 (확정 남은 도면[]). pytest 383 passed·17 skipped. - 관찰(결함 아님) — 확정하면 설계 재계산으로 장 나눔이 바뀜(3장 220
264m → 220280m). 확정 시점의 장 구성을 고정할지는 판단 대기.
- ① 수량표 역추출이 측점을 구분하지 않음 —
- 돌쌓기 해칭 — 경계로 잘라 싣기(2026-09-03 사용자 결정). 수확기가
g[clip-path]를 통째로 건너뛰어 형태 해칭이 CAD 에 하나도 안 실렸다. 선분–폴리곤 교차로 안쪽 조각만 남기고 클립 안 원은 36각으로 펴서 자른다.- 화면 검증에서 2차 결함 발견·수정(2026-09-03, 커밋
0f5b4e4d— 자동 폴백 커밋에 묶여 메시지가auto:로 남음). 클립 건너뛰기만 고쳤을 뿐 수확기 selector 가polygon, polyline, line, circle, text라rect를 아예 안 봤다. 돌쌓기 돌·돌망태 칸은cell()이rect+rotate(벽기울기)로 그리므로 주 표현이 통째로 빠졌다. 실측(용화 route 126 B06 화면) — 형태 해칭 80개 =line31 +rect49(61%), 264.06 카드는rect4(돌쌓기(메) 4켜) +line1. - 조치 — selector 에
rect추가,rectPoints()로 네 모서리 점열 변환(rotate(각도 cx cy)적용,rx무시). 회전을 빼면 기운 돌이 벽 폴리곤을 벗어나 클립에 전부 잘린다. - 자체검증 — 3장(220~280m) CAD 구조물 엔티티 14 → 22개(돌 8 = 벽 2매 × 4켜).
돌 상자가 켜마다 가로 1mm 씩 밀려 벽 경사를 따름(
-30,-168,-25,-163→-34,-154,-29,-149).tmp/tests/test_cad_rect_harvest.mjs4건, pytest 383 passed·17 skipped, typecheck 통과.
- 화면 검증에서 2차 결함 발견·수정(2026-09-03, 커밋
- 장 선택 시 정보 패널 표기 정리(2026-09-03). 장에는 측점 단위 값이 없는데 제목이
「측점 3장 (220~264m)」이었다 — 제목을 「장」으로 바꾸고 안내 문구를 넣었다. 판정은 도면
id(
cross_s…)로 한다(chainage_m은 장에도 첫 측점 값이 실려 옴).
B08 토적도·유역도 후속
- 토적도 축척 = 길이별 자동(2026-09-03 사용자 결정).
auto_scale_h()— 후보 1:500~1:6,000 중 A1 가용 폭 700mm 에 드는 가장 큰 그림. 실측 40m→1:500 · 용화 1,106m→ 1:2,000 · 3,465m→1:5,000. 세로는 종이 1mm=50㎥ 고정. - 유역 정보표 측점 표기 통일(2026-09-03, 커밋
e29e3cab) — 토적도와 같은n+ 0.0형식으로 맞춤.station_plus_label()을_Engine_Cad로 공용 이관해 두 도면이 한 함수를 씀. 자체검증 —tmp/tests/test_b07_masshaul_basin.py갱신·통과. 화면 실측 완료(2026-09-03, 「S자유역검증」8879c53b유역도) — 정보표 48개 전부(1) 4+ 18.3·(2) 9+ 16.1…(48) 221+ 9.9형식. - 납품 도면 표기 8행 전부 반영(2026-09-03 사용자 결정) — 종무대 ·
Q=한 칸 · 계단형 지시선 · 평형선·경계현 빨강 ·120+ 0.0· 표 눈금(정규 빨강·추가 회색) · 행 이름 3.2mm 자간 ·0+16.90.- 자체검증(2026-09-03, 「구조물검증-LAS」
2f940d8a토적도 엔티티 실측) — 8행 중 6행 확인:Q= 4491.46M3(한 칸) · 계단형 지시선(301.9,-99.8)→(291.8,-99.8)→(291.8,0)(수평 뒤 수직) · 측점0+ 0.0~17+ 10.1· 표 눈금 빨강 18 / 회색 5(회색 5 = 추가 측점 5개와 일치) · 행 라벨누 가 토 량·측 점3.2mm 자간 ·M.N= 0+0.00(소수 2자리). 축척은SCALE H=1:600 V=1:50,000로 자동 선택. - 남은 2행은 사례 없음 — 종무대(장비 이름)와 평형선·경계현 빨강은 이 프로젝트에 운반
블록이 없어 도면에 그려지지 않음. 코드 상수는
BALANCE_COLOR = BAND_CHORD_COLOR = "#ff4d4d"로 확인. 아래 「운반 블록이 있는 실노선에서…」 항목에서 함께 볼 것.
- 자체검증(2026-09-03, 「구조물검증-LAS」
| 항목 | 납품 도면 | 현재 |
|---|---|---|
| 장비 이름 | 종무대 | 무대 |
| 값 표기 | Q= 162.41M3 |
Q=162.41M3 |
| 지시선 | 계단형·모서리 접점 | 직선·아래 중앙 |
| 평형선·경계현 | 빨강 | 흰색·노랑 |
| 측점 | 120+ 0.0 |
No.120 |
| 표 눈금 | 정규 빨강·추가 회색 | 없음 |
| 행 라벨 | 큰 글씨·자간 벌림 | 2.2mm 본문 크기 |
| M.N 소수 | 0+16.90 |
0+16.9 |
B05 종단 계획선 개편 — 검증 후속 (2026-09-02 laptop-main 화면 검증에서 발견)
화면 검증 자체는 완료(실측 수치는 docs/raw/plans/2026-09-02_plan_user_verified_completed_items_2.md
「B05 종단 계획선 편집」). 아래 4건은 그 과정에서 나온 미해결이다.
완료된 최소고 가드와 구조물 위치 되돌리기는
docs/raw/plans/2026-09-02_plan_B05_profile_edit_followup_completed.md로 이동했다.
-
취소 —
규칙 측점은 선택이 안 돼 방향키 상하도 안 먹는다오검(2026-09-02 재확인)._Profile_Panel.selectStation은 같은 측점을 다시 누르면 선택을 푸는 토글이고, 앞선 검증이 240.000 을 두 번 눌러 해제된 상태에서 ArrowUp 을 보낸 것이었다. 한 번만 누르면b06-chart__station--selected가 붙고 ArrowUp 이 오프셋 0.1 을 만든다. 규칙 측점도 정상 — 코드 변경 없음. -
shiftSegment·shiftMovingPoints— 유지(2026-09-03 사용자 결정). 정리하지 않음. 새 [쉬프트]는shiftStraightRuns를 쓴다._Profile_Alignment.ts두 함수의 파일 밖 참조 0건. 「기하 함수는 남김」 방침이라 유지 중 — 되쓸 계획이 없으면 정리 대상(사용자 확인 후). -
참고 —
/route/confirm([저장])은 계획선을 재산출하지 않는다. 저장 경로는_Router_Lifecycle.py가 기존longitudinal.json에 상단측 변경분만 합쳐 다시 쓴다. 새 초기 계획선을 보려면 [경로 계산](/route/solve)이 필요하다 — 옛 프로젝트를 열어 기본이 안 바뀐 것처럼 보이는 것은 이 때문이고 결함이 아니다.
B05/B06 구조물 3D 판단 대기
완료된 패치·마스크 수정은 docs/raw/plans/2026-09-02_plan_user_verified_completed_items.md로 이관했다. 2D 면적·유토곡선 산식은 분리 보류이므로 건드리지 않는다.
- BOX 날개 사이 — 현행(원지반) 유지(2026-09-03 사용자 결정). 코드 변경 없음.
- 세월교 좌측 접근선 — 패치로 덮음(2026-09-03 사용자 결정). 접근선(노견 → 벽 상단)은
벽보다 위라 덮어도 관 구멍·L자 통로를 막지 않는다. 벽 전면·유로는 종전대로 리본에 담지
않는다. 접근선 줄을
patchPoints앞에 담고fillRuns에 한 장으로 실어 「구간 1줄 = 리본 1장」 규칙을 지킨다.- 자체검증(2026-09-03, 용화 route 126) —
fordSilhouettes()를 실제 세월교 2측점 (177.33m·358.92m)에 돌려 첫 리본이 노견에서 시작함을 확인: 우측(-2, 851.18)=road_edges.right, 좌측(2, 851.30)=road_edges.left, 면마다fillRuns2장 (접근선 1 + 성토 1). 3D 픽셀 육안은 카메라를 그 측점으로 몰아야 해 미실시 — 리본 데이터로 판정함.
- 자체검증(2026-09-03, 용화 route 126) —
B05/B06 700줄 제한 위반 정리
B06_Section_UI_Section_View.ts751 → 689줄 — 유토곡선 조립을_MassHaul로 분리.B06_Section_UI_Cross_View.ts784 → 698줄 — 카드 제목·하단행을_Cross_Card_Chrome, 실효 반폭 계산을_Cross_View_Metrics, 줌 상태 맵을_Cross_View_Zoom으로.B05_Profile_UI_Profile_Panel.ts— 현재 699줄로 제한 안(별도 작업 불필요).B05_Profile_UI_Structures_Panel.ts1,078 → 1,024줄 — 폼 뼈대를_Structures_Form으로 분리(1차).- 자체검증 — 분리 3건의 화면 실동작 확인(2026-09-03, 용화 route 126):
B06 횡단 카드 65장 전부 header·footer 생성(
_Cross_Card_Chrome), 유토곡선 패널 표시 (.b06-masshaul,_Section_View_MassHaul), B05 구조물 배치 폼 본문이grid → position-row → divider → grid(옵션) → 시설 서브폼 → 메모 → [추가][삭제][리셋]순서로 조립되고 목록 11건 표시(_Structures_Form).
B04 세부유역 중첩·빈공간 — 현행 반영 여부 확인 (2026-09-03, 보조폴더)
사용자 지시: 로직은 그대로 두고, S자 노선에서 아래 세부유역이 위 세부유역을 포함하는 경우를 현행이 반영하는지 확인만 할 것.
-
확인 결과 — 셀 단계는 반영, 내보내기 단계에서 소실.
assemble_basins(common_util/common_util_drainage_detail.py:508)의 라벨 격자는 셀마다 관 하나만 배정하므로 포함 관계(도넛)가 정확히 살아 있고,polygonize_labels(B04_PreProcess/B04_PreProcess_Engine_Watershed_Flow.py:526)도 구멍을 가진 폴리곤을 낸다. 그러나largest_ring:563이 외곽 링 하나만 뽑고WatershedBasin.boundary_xy(:107)·APIpolygon_lonlat(B04_PreProcess_Router_Basins.py:164,195)가 단일 링 자료형이라 구멍·조각이 실릴 자리 자체가 없음. 즉 화면에서는 아래 유역이 위 유역을 통째로 덮음. 검증(tmp/tests/test_basin_boundary_holes.py, 1m 격자 합성 사례 3건, 3 passed): ① 도넛 — 갇힌 위 유역 256㎡ 전체가 아래 유역 링에 중첩 ② 조각 — 한 관 유역이 두 조각(225㎡+144㎡)이면 작은 144㎡ 소실 = 빈공간 ③ 유역별 독립 simplify(2.0m) — 들쭉날쭉한 공유 경계에서 중첩 18.2㎡ · 틈 35.2㎡ (전체 6400㎡ 대비 0.8%). 규칙적 계단 경계에서는 재현 안 됨(양쪽이 같게 단순화). -
후속 완료(2026-09-03): 자료형을 링 목록으로 넓힘.
polygon_parts()신설(조각마다 [외곽, 구멍...], 넓은 조각 먼저) ·WatershedBasin.boundary_parts로 교체하고boundary_xy(가장 넓은 조각의 외곽) ·boundary_rings(편 링 목록)는 파생 속성으로 남겨 옛 소비처 무손상 · API 에polygon_rings_lonlat추가 · 저장 GeoJSON 은 구멍을 가진 Polygon, 조각이 여럿이면 MultiPolygon · 캔버스 3곳(B04 유역화면 채움·선택, B05 배수유역도 채움·선택)은 even-odd 로 한 번에 채우고pointInRings()로 판정(구멍 안을 눌러도 바깥 유역이 잡히지 않음). 중복이던 지역pointInRing은 삭제하고 공용 것으로 통일. 검증: 단위 5건 신규(tmp/tests/test_basin_boundary_rings.py— 도넛 구멍 보존, 조각 2개 보존, 파생 속성, 빈 경계, 조립 경로 전체에서 유역 하나가 링 2개), 전체 168 passed. 브라우저 — API 가 22개 유역에 링 목록을 실어 보냄(경계 없는 1개 제외), 캔버스 even-odd 실측(가운데 알파 0 / 고리 255, nonzero 는 255)로 구멍이 실제로 뚫림. 1차 전체 배수유역(분수령)은largest_ring그대로 — 외곽선 한 줄이 맞는 자리. -
S자 노선 실사례 검증(2026-09-03, 사용자 지시): 용화 지형 위에 스위치백 3구간 합성 노선(CSV, 정점 439·연장 4,528m)을 만들어 신규 프로젝트로 자동 체인까지 완주. 결과 관 48개·세부유역 48개. 도넛은 1건 나왔으나 1㎡짜리 simplify 부스러기였고, 진짜 빈공간의 원인은 최소면적 필터로 드러남 — 100㎡ 미만 유역은 폴리곤이 아예 안 만들어져 화면에서 통째로 사라졌음(용화 22개 중 1개, S자 48개 중 1개).
-
최소면적 필터 제거(세부유역 한정):
assemble_basins가polygonize_labels(..., min_area_m2=0.0)로 부름. 실측 면적 오차 용화 5.76%→1.86%, S자 3.56%→1.42%, 경계 없는 유역 1개→0개, 좌표점은 583→622·806→829 로 거의 그대로. 1차 전체 배수유역·다른 호출부의 기본값(100㎡)은 손대지 않음. 전체 168 passed. -
단순화 허용오차 2.0m → 1.0m (2026-09-03 사용자 결정, 메인 창 경유). 격자가 1m(
DRAINAGE_GRID_SIZE_M)라 경계가 1m 계단이므로 허용오차를 격자 한 칸에 맞춤 — 형상 손실이 격자 오차 안으로 들어감. 「공유 경계를 함께 단순화」(라벨 경계를 선분 그래프로 한 번만 단순화)는 작업량 대비 우선순위가 밀려 이번엔 채택 안 함. 실측(min_area=0 상태에서 비교):허용오차 좌표점(용화/S자) 면적오차(용화/S자) 유역끼리 중첩(용화/S자) 틈(용화/S자) 2.0m(옛) 622 / 829 1.86% / 1.42% 1,043㎡ / 1,373㎡ 1,184㎡ / 2,579㎡ 1.0m(채택) 1,749 / 1,987 1.01% / 0.67% 243㎡ / 373㎡ 369㎡ / 668㎡ 0.5m 10,215 / 12,294 0.00% / 0.00% 148㎡ / 129㎡ 296㎡ / 259㎡ 0.0m 12,403 / 14,558 0.00% 0㎡ 0㎡ 0.5m 이하는 1m 계단 점을 못 지워 좌표점만 6배로 튐. 브라우저 실측도 같은 값 (API 좌표점 용화 1,750 · S자 1,987, 경계 없는 유역 0개), 확대해도 계단이 도드라지지 않음. 테스트 159 passed(B07 항목 아래 별도 기록한 1건 제외).
-
병합 뒤 깨진 로컬 테스트 복구(2026-09-03):
tmp/tests/test_b07_masshaul_basin.py가 사라진MM_H를 import 해 수집 단계에서 전체 실행이 막혔음. 메인 창이 알려 준 대로 고침 —auto_scale_h()로 축척을 얻고(시험 노선 40m → 1:500,MM_H = 1000/500), 표기 6곳을 현행으로(종무대·Q= 600.00M3·L= 18.50M·EA= 400.00M3·M.N= 1+10.00·SCALE H=1:500 V=1:50,000). 축척 규칙을 굳히는 시험도 추가 (40m→500 · 1,106m→2,000 · 3,465m→5,000 · 길이 0이면 설정 기본값 2,000).tmp/tests는 git 밖이라 커밋 없음. 전체 169 passed.
B03 계획노선 shapefile — 변환 CSV 정본화 (2026-09-03, 보조폴더)
사용자 확답: 프론트엔드는 올린 파일 그대로 표시, 백엔드는 CSV 로 변환해 사용하고
그 CSV 를 초기값(initial_snapshot/) 정본으로 남김. 좌표는 사업지 좌표계 +
트림·조밀화 후(2026-09-03 사용자 확정).
현행 조사 결과 — 이미 되어 있는 것(작업 불필요):
슬롯 라벨 계획노선 도형(CSV 표기 아님) · .csv/.shp 동시 수용 · shx/dbf/cpg/route_prj
슬롯 · shp 판독기(B03_FileInput_Engine_Shapefile.py) · shp 우선 선택
(find_planned_route_file) · 좌표계 변환·트림·조밀화 단일 창구
(common_util_route_geometry.py:215 load_design_route).
- 초기값 CSV 기록 —
common_util_initial_snapshot.py에planned_route.csv(sequence,x,y) 를save_initial_snapshot()이 함께 씀. 값은 체인 2단계가 이미 만든points(사업지 좌표계·트림·조밀화 후)를 그대로 받음 — 재계산·서피스 샘플러 재구축 없음. - 체인 연결 —
B03_FileInput_Service_Chain.py스냅샷 블록이points를 넘김. - 정본 사용 —
load_design_route()는 surface_params 가 주어진 호출에 한해 초기값 CSV 가 있으면 그것을 읽고 반환(재판독·재투영·트림 생략).surface_params=None호출(도엽 범위 산출B04_PreProcess_Engine_SheetSurface.py:492)은 트림 전 원본이 필요하므로 종전 경로 유지. - 무효화 규약 확인 — 지표면·노선이 바뀌면
discard_initial_snapshot()이 폴더째 지우므로 CSV 도 함께 사라져 자동으로 shp 재판독 경로로 되돌아감. - 자체검증 완료 (2026-09-03, 보조폴더 8001·5174)
① 단위 4건
tmp/tests/test_design_route_csv_master.py— CSV 왕복 좌표 일치, 정본 우선, 트림 전 호출은 정본 미사용, 스냅샷 폐기 시 경로 닫힘. 전체 158 passed. ② 실사용 경로 — 공용 브라우저에서 프로젝트 신규 등록 → 용화 예정노선 shapefile 5개 + 지형 PRJ·TFW 업로드 → [LAS 없이 설계] 체크 → 업로드 → 자동 체인 완료.initial_snapshot/planned_route.csv생성됨(643행). 정본 경로와 원본 shp 경로를 맞대 보니 정점 643개 동일, 최대 좌표차 0.00007m, 연장 2136.2m 동일. B05 화면에 종단 계획선·배수유역도(관 22개·세부유역 22개)가 정상 표시. ③ 프론트 표시 — 슬롯 카드가 올린 파일명을 그대로 보임(대상지_일월.용화.2.2.shp외 4개), 라벨은계획노선 도형.
LAS 없는 설계 — 도엽 서피스가 노선 원본 좌표계로 만들어지던 문제 (2026-09-03, 보조폴더)
증상: shapefile 노선(EPSG:5179) + 지형 PRJ(EPSG:5176)로 [LAS 없이 설계]를 돌리면
자동 체인이 노선 트림: 노선 전체가 지표면 밖입니다 로 중단됨 — 실측 재현.
원인: B04_PreProcess_Engine_SheetSurface.py:503 run_sheet_surface_analysis 만
read_planned_route() 로 노선을 원본 좌표 그대로 읽어 도엽 서피스를 5179 자리에 만들고
(실측: 서피스 x 1,141,9511,143,784), 설계 계통 209,637)으로 옮기므로 두 자리가 어긋나 트림이 노선을 통째로 지움.
같은 파일의 load_design_route() 는 노선을 사업지
좌표계 5176(x 208,402build_sheet_surface_from_route() 는 이미 load_design_route() 를 쓰고 있어
LAS 경로에서는 나지 않던 문제.
run_sheet_surface_analysis()도load_design_route()로 읽도록 창구 통일, 좌표계는planned.crs_input or project_epsg_from_prj()를 그대로 사용 (EPSG 라벨 대신 PRJ 원문 WKT 가 실려 TOWGS84 보정이 보존됨).- 도엽 확보(
download_geodata)의 PRJ 탐색 폴더를 노선 세트(input/shp/)에서 지형 PRJ 폴더(input/prj/)로 교정 — 노선 PRJ 가 잡히던 자리. - 검증: 수정 후 같은 자료로 재실행 → 체인 완주(노선 643점·2136.2m, 관 22개, 세부유역 22개). 전체 테스트 158 passed.
B03 [파일 업로드] 가 잠긴 채 남던 문제 (2026-09-03, 보조폴더)
증상: 필수 파일을 다 골랐는데도 [파일 업로드] 가 비활성. 새로고침하거나 파일을 하나 더 고르면 풀림.
원인(첫 추정 정정): 프로젝트 ID 캐시가 아니었음 — 파일 선택 경로가
detectPausedUploads() 에서 ID를 다시 읽어 스스로 풀림. 진짜 자리는 [LAS 없이 설계]
토글. 이 토글이 LAS 카드의 필수 여부를 바꾸는데(isSlotRequired), change 핸들러가
updateUploadButton() 을 부르지 않아 버튼 판정이 옛 상태로 남음. 파일을 먼저 고르고
토글을 나중에 켜는 순서에서만 재현돼 처음엔 ID 문제로 보였음.
lasFreeCheckchange 핸들러에updateUploadButton()추가 (4줄).- 검증(공용 브라우저, 저장된 토글 표시를 지워 첫 진입 상태로 재현): ① 파일 7개만 고른 상태 → 비활성 + "필수 카드를 모두 채우세요 … LAS/LAZ …" ② [LAS 없이 설계] 켠 직후 → 즉시 활성, 오류 문구 사라짐 ③ 다시 끄면 → 즉시 비활성 + 같은 안내. typecheck 통과.
B04 세부 배수유역 — 종단 높낮이 흐름 반영 (2026-09-03, 보조폴더)
사용자 재정의(2026-09-03): "세밀유역" 표현은 접고, 배수유역 = 횡단배수 지점으로 들어오는 유역. 빠진 것은 종단 계획노선의 높낮이에 따른 흐름 — 용화에서 낮은 도로측 유역이 높은 쪽으로 흐르는 것처럼 표현됨.
진단(용화 실측, 프로젝트 shp정본검증2): assign_road_cells_to_pipes 의 내리막 추적이
한 칸 이웃만 보는 국소 하강이라 1m 간격 계획고의 미세 요철에 걸려 멈춤 — 측점 2,138개 중
1,898개(88.8%)가 저점에 갇힘. 갇힌 측점은 흐름이 아니라 누가거리 최근접으로 관에
붙어, 도로 셀 11,312개 중 4,886개(43.2%)가 자기보다 높은 관에 배정(최대 6.82m).
추적이 성사된 측점의 오르막은 0.8%(최대 0.09m)라 추적식 자체는 정상.
- 배정 규칙 교체 — 관 사이 마루(구간 최고점)가 분수령. 1차원에서 물은 마루를 넘지 못하므로 마루 왼쪽은 앞 관, 오른쪽은 뒤 관, 첫 관 앞·마지막 관 뒤는 그 관이 받음. 미세 요철에 면역 (사용자 확정).
- 관 없는 저점 126개는 그대로 둠 (사용자 확정) — 대부분 계획고 미세 요철이지 진짜 사그가 아니고, 마루 분할이 자동으로 무시함.
- 자체검증 ① 단위 5건
tmp/tests/test_ditch_ridge_assignment.py— 마루가 경계, ±3cm 톱니에도 배정 불변, 사그는 낮은 쪽으로, 첫·끝 구간, 관 순서 보존. 전체 163 passed. ② 실측 재계산: 오르막 배정 43.2% → 17.6%, 최대 상승 6.82m → 4.15m. ③ 잔여 1,993셀은 전부 사그에 고였다가 더 낮은 장벽(=배정된 관) 쪽으로 넘치는 경우임을 확인(어긋남 0개) — 물리적으로 옳은 배정이라 남겨 둠. ④ 화면: B05 배수유역도 [유역 다시 나누기] 후 유역 면적이 실제로 바뀜 (관1 1.35ha → 1.07ha, 관3 2,545㎡ → 3,661㎡, 관4 23.34ha 세월교 제안).
B04 지표면 3D 뷰어 방위 콤파스 (2026-09-03, 보조폴더)
사용자 확인: 대상은 B04 지표면 3D 뷰어 (B03 에는 3D 화면이 없음).
B04_PreProcess_UI_Compass.ts신설 — 카메라 오프셋으로 도북 각도를 내는 작은 모듈. 뷰어 좌표 규약이x, 높이, -y라 세계 북쪽은-z, 화면 회전각은atan2(offset.x, offset.z). 뷰어 파일이 이미 946줄이라 별도 파일로 뺌(700줄 제한).B04_PreProcess_UI_TerrainViewer.ts배선 3줄 — 뷰어 우하단(축척 막대 반대편)에 얹고 애니메이션 루프에서 각도 갱신(0.5° 미만 변화는 건너뜀). 지표면이 보일 때만 표시.- CSS —
.b04-surface__compass*(테마 토큰 사용, 라이트·다크 공용). - 자체검증:
npm run typecheck통과. 공용 브라우저에서 ① [상단] 시점 회전각matrix(1,0,0,1,0,0)= 0° (바늘이 화면 위 = 북쪽, 북쪽 위인 2D 지도와 같은 방향) ② 캔버스를 220px 드래그하니matrix(-0.78152,-0.62388,…)= 218.6° 로 카메라와 함께 회전 ③ 상단·하단 두 3D 뷰어 각각에 하나씩(총 2개) 표시. 검증 후 시점은 기본(사시도) 으로 되돌려 둠.
프로젝트 작업 좌표계 일원화 (2026-08-31 신규)
- 작업 좌표계 = 지형 PRJ 로 확정(2026-09-03 사용자 결정 — 서피스 격자가 모델좌표의 주인이라 현행 유지). 「노선 .prj 우선」은 노선 UTM-K / 지형 동부원점 Bessel 로 실제 좌표계가 달라 서피스·격자를 통째로 재투영해야 해 폐기.
- 폴백 사다리를 창구 하나로 통합 —
common_util_crs.resolve_project_crs()신설. ① 노선 crs_input ② 파일 라벨(원본 좌표를 읽는 자리만) ③ 지형 PRJ ④ DB epsg ⑤ EPSG:5186._route_center_lonlat이 CSV 라벨을 그대로 변환에 쓰던 자리를 이 사다리로 교체.tmp/tests/test_project_crs_resolution.py5건 신설. - 트림 실패 진단 — 지표면 트림이 노선을 통째로 지우면 노선·지표면 bbox 를 함께 로그에 남긴다(겹침 0이면 좌표계, 일부 겹치면 측량 범위 문제).
(완료 — 위 항목):planned.epsg or 5186폴백이 여섯 군데 흩어져 있다B04_PreProcess_Engine_SheetSurface.py:467·496,B04_PreProcess_Router_Watershed.py:186·253,B04_PreProcess_Router_Inflow.py:84,common_util_drainage_context.py:98.B04_PreProcess_Engine_Extent.py:147-152,B04_PreProcess_Engine_GisVector.py:148도 5186 기본값.