Commit Graph
462 Commits
Author SHA1 Message Date
eomsangdonandClaude Opus 5 93d2838f4c feat(B06): 기슭막이 하단을 수평 기초로 — 높이는 상~하단 전체로 표기
- 하단선 = 수평(기초공사 기준 — 2026-08-22 사용자 확정). 깊이는 벽
  발자국 안 원지반(또는 관 invert) 최저점 − 0.5m. 종전 지반 추종
  경사 하단 폐지.
- 전면 1:0.3 경사선을 하단까지 연장 — 바닥이 깊어진 만큼 발끝이
  바깥으로. 발끝 지반이 더 낮으면 한 번 더 내림(2-pass).
- WallLayout.height = 상단~하단 전체 높이(근입 포함)로 변경 — 툴팁
  H 표기 기준. 설계 파라미터(폭·기움)는 invert 기준 높이 유지.
- 검증: 4+4.3(H 2.0/2.1)·13+15.7(H 1.9) 하단 수평·관 감싸기 SVG
  실좌표 확인.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 09:46:20 +09:00
eomsangdonandClaude Opus 5 a24cfe1378 feat(B06): 기슭막이 이동 한계 도달 시 토스트 안내
- 조정창 ◀/▶ 요청이 한계에 잘려 벽이 안 움직일 때 이유를 토스트로
  알린다(2026-08-22 사용자 요청, 13+15.7 참조).
  · 안쪽 한계: 성토 물매 1:1.2가 깨지는 자리(배관 최소 길이)
  · 바깥 한계: 조정 범위 초과
- 그 벽이 선택된 조작 중에만 띄운다 — 리로드로 복원된 세션 값에는 침묵.
- 검증: 공용 브라우저 실조작 — 13+15.7 안쪽 시도 토스트 표시,
  바깥 정상 이동 시 무음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 09:35:52 +09:00
eomsangdonandClaude Opus 5 d51a07258e fix(B06): 관 축을 최종 벽 자리로 재유도 — 벽 바닥 아래 삐짐 해소
- 관 하단선은 관 시작점과 유출 벽 하단선 중점(invert)을 잇는 직선으로
  고정 — 정수 맞춤이 벽을 옮길 때마다 축·법선 재유도(deriveAxis).
  종전엔 옛 축을 그대로 늘려 가파른 지반(13+15.7)에서 관이 벽 바닥
  아래로 삐져나갔다.
- 관 시작 기준도 유입 노견점이 아니라 실제 관 시작점(집수정 내공 벽)
  으로 통일.
- 끝단면 교점을 마감면 선분 안으로 클램프(clampToFace) — 연장선
  교차로 벽 밖에 꼭짓점이 생기는 것 차단.
- 검증: 13+15.7 SVG 실좌표(관 꼭짓점 385→371, 벽 하단 379 위),
  4+4.3 회귀, dz 스윕 24건 이탈 0건.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 09:14:22 +09:00
eomsangdonandClaude Opus 5 030b81b744 feat(B06): 기슭막이 자동 자리 노견 최소화·수동 이동 독립화
- 자동 자리 = 물매 1:1.2가 딱 성립하는 가장 안쪽(노견 최소) 지점.
  관 m단위 올림 잔여만 유출 벽 바깥 이동으로 흡수(minShoulderWallOffset).
  사면 끝 밖 자리는 급물매 교정일 때만 인정 — 얕은 성토 폭주 방지.
- 손으로 민 벽은 관 정수 맞춤이 절대 옮기지 않음 — 한쪽 이동 시
  반대쪽 벽 동시 이동(관 +2m) 소멸. 표기 길이만 올림(m).
- 안쪽 당김 한계 = 1:1.2 성립 자리(우선순위: 배관 연장 > 높이 증가 >
  바닥 띄움). 1:1.2 자리가 없는 지형 폴백에서만 높이 증가·바닥 띄움
  (solveWallVertical, 한계 찰3.0/메2.0).
- 기슭막이는 관을 감싼다: 하단은 항상 관 invert 아래 0.5m 확보,
  뜬 바닥도 동일(뜬 공간은 별도 지지 구조물 — 추가 예정).
- 검증: 4+4.3 관 13m→9m·노폭연장 1.52→0.08, 13+15.7 UI 조작
  (◀▶↺·클램프·단독이동) 및 dz 스윕 24건 물매 이탈 0건.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 09:07:35 +09:00
eomsangdon a5800e5a34 auto: 2026-08-21 19:34 (EOMSANGDON-HOME) 2026-08-21 19:34:27 +09:00
eomsangdonandClaude Opus 5 67ec86b05f feat(B06): 성토 물매 1:1.2 고정 — 벽이 나간 만큼 노폭 연장
물매를 1:1.2~2.0 범위에서 역산하던 방식을 걷어내고 **수평 1.2 : 수직 1 고정**으로
바꿨다(2026-08-21 사용자 확정). 벽이 1:1.2 사면이 닿는 자리보다 밖에 있으면 물매를
완만하게 바꾸는 대신 **노폭을 그만큼 늘린다** — 기슭막이를 바깥으로 1m 밀면 노폭이
약 1m 늘어난다.

- fillSlopeOf가 [원 노견 → 연장된 노견 → 벽 이음선 상단점] 폴리라인을 돌려주고,
  설계선 오버레이가 그 폴리라인을 그린다(노면 연장 구간이 수평으로 붙는다).
- 반대로 벽이 안쪽이라 물매가 1:1.2보다 급해지는 자리는 노폭으로 못 맞춘다(도로를
  좁힐 수는 없다) — 자동 자리를 1:1.2가 될 때까지 바깥으로 미는 처리를 유지한다.
- fillSlope.roadWideningM 신설, 툴팁에 "노폭 연장 x.xxm" 표시.

검증(계획고 스윕 24케이스): 물매 23건이 정확히 1:1.200(나머지 1건은 성토고 0.2m로
사면이랄 게 없는 측점). 벽 이동 시험 — 밖으로 1m씩 밀 때 노폭 연장 1.52→3.27→
4.22→5.21m, 물매는 계속 1:1.200. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 18:35:53 +09:00
eomsangdonandClaude Opus 5 6391bb4c7e fix(B06): 성토 물매 1:1.2 하한을 자동 자리에도 강제
기슭막이 기본 자리를 사면 끝으로 바꾼 뒤 물매가 규정보다 급해지는 측점이 생겼다
(13+15.7 실측 1:0.865 — 성토_비탈면.md §1의 1:1.2~2.0 위반). 1:1.2는 지켜야 하는
하한이므로, 사면 끝 자리의 물매가 그보다 급하면 **1:1.2에 닿을 때까지 바깥으로**
민다. 지반이 1:1.2보다 급해 끝내 못 맞추면 사면 끝을 그대로 쓰고 경고로 알린다.

물매 계산의 이음선 위치도 바로잡았다 — 자리 기준이 하단선 중점으로 바뀐 뒤에도
`REVET_TRAP_TOP_M`을 그대로 더해 실제보다 0.3m 바깥으로 보고 있었다.
`fillWallBaseWidth()`로 중점↔이음선 환산을 한곳에 모았다.

검증(계획고 스윕 24케이스, 새 계획노선): 물매 최소 1:1.202 — **1:1.2 미만 0건**
(종전 0.4~0.9까지 나왔다). 페이지 실데이터로도 13+15.7 1:1.206 확인.
tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 18:24:58 +09:00
eomsangdonandClaude Opus 5 6a5cd725c2 feat(B06): 집수정 깊이를 관 여유로 결정
집수정 벽 높이를 성토 경사선과의 교점으로 잡던 방식을 걷어내고, **관 아래 여유
0.5m + 관경 + 관 위 여유 0.5m**로 정한다(2026-08-21 사용자 확정). 위 여유는
기슭막이와 같은 REVET_FREEBOARD_M을 써서 좌·우 표현이 어긋나지 않는다.

BASIN_BOTTOM_CLEARANCE_M(0.5) 신설. 종전 바닥판 두께 0.45가 아래 여유 자리를
겸하고 있었다.

검증(13+15.7, D800): 집수정 깊이 1.8m = 0.5 + 0.8 + 0.5, 바닥 여유 0.5 확인.
계획고 스윕 24케이스 문제 0. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 18:14:10 +09:00
eomsangdonandClaude Opus 5 38acdd02ed feat(B06): 기슭막이 자리·하단선 규칙 재정립
2026-08-21 사용자 확정:
- 기본 자리 = **성토 사면이 원지반과 만나는 지점**(사면 끝). 사면이 5m를 넘으면
  기슭막이가 사면을 5m에서 끊는다 — 5m는 자리 한계가 아니라 "5m 이상이면 기슭막이
  의무"라는 규정(성토_비탈면.md §2)의 표현이다. 물매 1:1.2~2.0으로 자리를 풀던
  방식은 걷어냈다(자유도 축소였다).
- 벽 하단선 = **원지반을 수직 0.5m 내린 선**. 수평 바닥이라 사면에서 앞 모서리가
  뜨던 문제가 사라진다(배면·전면 모두 근입 0.500 확인).
- 자리 기준(이동 중심) = **하단선 중점**. 배면 기준이면 벽이 기울 때 체감 위치가
  어긋난다.
- 관 유출단 invert = 그 자리 원지반 → 관 하단 경사가 지반과 만난다.
- structureRequired = 사면길이 5m 이상(의무 발생), 종전의 "받을 수 없는 자리" 판정 대체.

그리기도 기운 하단선에 맞췄다 — 이음선 바닥·돌 해칭이 하단선 위에서 잡힌다.

검증: 두 측점 이동 10케이스 근입 배면·전면 모두 0.500, 하단선 중점이 원지반과 일치
(관 수평 클램프 2건 제외), 계획고 스윕 24케이스 문제 0. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 17:56:35 +09:00
eomsangdonandClaude Opus 5 564b289ee6 fix(B06): 이동량이 한계에 걸려도 숫자만 커지던 문제·안쪽 이동 최소 물매
- 조정창 숫자가 실제와 갈렸다. 안쪽으로 계속 누르니 "안쪽 10.0m"까지 올라가는데
  벽은 노견 한계에서 멈춰 있었다. 기하가 **실제 적용한 이동량**(revetShift)을 돌려
  주고, 카드가 그 값을 제어기에 되담는다 — 이제 한계에 닿으면 숫자도 멈춘다.
- 안쪽으로 당기면 사면이 짧아져 물매가 급해진다. **1:1.2(가장 급한 한계)**를 넘지
  않는 자리까지만 들어가게 막았다(2026-08-21 사용자 지시). 바깥으로 밀 때는 완만해
  지므로 막지 않고 범위 밖이면 경고로만 알린다.

검증: 4+4.3은 자동 자리가 이미 1:1.21이라 안쪽 이동 0(차단), 13+15.7은 −1m까지
허용(1:1.61)하고 그 이상 차단. 조정창 숫자도 같은 자리에서 멈춘다. 두께 16케이스
0.450 고정, 계획고 스윕 24케이스 문제 0. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 17:24:35 +09:00
eomsangdonandClaude Opus 5 ce03edc180 fix(B06): 벽 폭 흡수 폴백 제거 — 좌우 단면이 서로 달라지던 문제
유입 벽을 조정창으로 밀면 유출 벽이 자동으로 관 길이를 맞추다가 **폭 흡수 폴백**에
걸려 0.45→0.85m로 부풀었다(4+4.3 화면 확인: 좌 0.45 / 우 0.85). 조정한 벽만 폭을
지키게 했던 앞 조치로는 반대편 벽이 보호되지 않았다.

폭 흡수를 아예 없앤다 — 벽 두께는 항상 0.45 고정이고, 자리를 더 못 옮기면 거기서
멈춘다. 남는 몫은 관이 벽을 조금 벗어나는 것으로 두는 게 기존 확정 규칙이다.

검증: 두 측점 이동 16케이스 전부 두께 0.450 고정(두께 이상 0건), 계획고 스윕
24케이스 문제 0. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 17:15:26 +09:00
eomsangdonandClaude Opus 5 bcdfde2a05 fix(B06): 유출 기슭막이가 지반에서 뜨던 문제
벽 밑을 관 축(유입 → 자연 사면 끝 직선) 위에 얹고 있었다. 성토측 지반이 관 물매보다
가파른 구간에서는 축이 지반 위로 떠올라 벽이 공중에 떴다 — 13+15.7 유출 벽은 자동
자리에서도 전면 0.14m, 바깥으로 2m 밀면 배면까지 0.16m 떴다.

관 끝은 원지반 위에 놓는다는 원칙대로 벽 밑을 **그 자리 원지반**(역경사는 유입 invert로
클램프)으로 바꿨다. 관 물매는 그 자리에 맞춰 다시 잡힌다. 유입 벽은 원래 지반을 따르고
있어 멀쩡했다 — 좌우가 달라 보인 이유가 이것이다.

표기 길이도 목표값이 아니라 **실제 그려진 관**의 올림값으로 바꿨다(자리 제약에 걸려
못 늘린 경우 도면보다 길게 적혔다).

검증: 이동 ±3m 전 구간 배면 근입 +0.500 고정(종전 −0.16~+0.59), 계획고 스윕
24케이스 문제 0. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 17:09:20 +09:00
eomsangdonandClaude Opus 5 8564e118d6 fix(B06): 조정 단위를 관 길이 1m로·벽 형상 불변·사면 역전 차단
지적 3건:
- 우측(유출) 기슭막이만 좌우로 밀 때 단면이 변했다. 0.1m씩 미니 관 길이 정수의
  끝수를 벽 폭이 흡수해 0.45→0.90까지 뚱뚱해졌다. 조정 단위를 **관 길이 1m**로
  바꾸고, 조정창으로 옮긴 벽은 폭을 절대 건드리지 않게 했다. 자리만 옮기면 정수
  길이가 성립하므로 형상이 그대로다(검증: 두께 0.450 고정, L 1m씩 증감).
- 성토 사면이 역전되는 자리가 있었다. 벽 상단이 노견보다 높아지면 사면선이 위로
  올라간다 — 최소 성토고 0.3m(FILL_MIN_RISE_M)를 두고 그 앞에서 멈춘다.
- 이동이 노견을 넘어 도로 반대편까지 갔다. 벽은 제 노견 바깥에만 서게 막았다.

조정창은 "관 길이 8m · 바깥 2.0m"처럼 관 길이를 같이 적는다.
700줄 유지를 위해 clampWallOffset·cutLength·outletSlopeFactory를 _Solve로 옮겼다.

검증: 이동 ±5m 20케이스 역전 0건·두께 고정, 275.71 유출 이동 11↔7m 정상,
계획고 스윕 24케이스 회귀 문제 0. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 16:50:45 +09:00
eomsangdonandClaude Opus 5 4eed191d2a feat(B06): 구조물 위치 조정을 횡단도 안 오버레이 창으로
카드 하단 버튼 그룹을 걷어내고 **해당 횡단도 안**에 뜨는 조정창으로 바꿨다
(2026-08-21 사용자 확정). 앞으로 구조물 위치 조정은 모두 이 창을 통한다.

- _UI_Cross_Structure_Panel.ts 신설. 그래프 영역 좌측 하단에 절대 위치로 얹는다
  (줌 버튼 우측 상단·면적표 중상단과 겹치지 않는 자리).
- 창 내용: 구조물 이름 · 자동 자리 대비 이동량 · ◀/▶/↺ · ✕(닫기 = 선택 해제).
- 이동량은 부호(+/−) 대신 "바깥 0.2m"처럼 적는다 — 좌·우 벽에서 부호만으로는
  어느 쪽인지 읽히지 않는다.

검증(공용 브라우저 4+4.3): 유입 벽 클릭 → 창 열림(제목·자동 자리), ◀ 2회 →
"바깥 0.2m"·도형 이동, ↺ → 자동 자리 복귀, ✕ → 창 닫힘·강조 해제.
tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 16:34:09 +09:00
eomsangdonandClaude Opus 5 83a1309a37 feat(B06): 구조물 선택 = 카드 선택·면적 강조와 같은 레벨, 붉은 강조
- 강조 색을 --color-danger(붉은색)로 변경.
- 구조물을 고르면 그 측점 카드도 같이 선택된다. 이미 선택된 카드 안에서 다른
  구조물을 고를 때는 강조만 옮겨 가고 카드 선택은 건드리지 않는다.
- 구조물 선택과 절·성토 면적 강조는 같은 레벨 — 하나를 고르면 다른 하나가 풀린다.
  카드가 선택에서 빠져도 구조물 선택은 풀린다.
- 조정 버튼이 안 보이던 원인: .b06-cross-card__revetctl 스타일과 .is-hidden 규칙이
  아예 없었다. 스타일을 넣고 "기슭막이" 라벨을 붙여 표시 반폭 그룹과 구분했다.

미선택 카드에서 구조물이 먹히지 않던 버그도 잡았다 — 면적 비우기(onAreaSelect)가
먼저 카드를 선택해 버려, 뒤이은 onSelect가 "같은 측점 재클릭 = 해제"로 상쇄됐다.

검증(공용 브라우저 4+4.3): 미선택 카드에서 구조물 클릭 → 벽 강조 + 화살표 + 카드
선택. 같은 카드 다른 구조물 → 강조만 이동. 면적칩 → 구조물 해제. 다시 구조물 →
면적 해제. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 16:28:27 +09:00
eomsangdonandClaude Opus 5 5eed5e801c fix(B06): 기슭막이 클릭이 관에 먹히던 문제·강조 색 토큰화
화면 확인에서 나온 두 가지:
- 그리기 순서가 벽 → 관 → 보호공이라 관 폴리곤이 벽 가운데를 덮어, 벽을 눌러도
  관이 먼저 클릭을 먹었다. 그리기 순서는 그대로 두고 **투명 판정면**을 맨 마지막에
  얹어 벽 전체가 눌리게 했다.
- 선택 강조가 존재하지 않는 --color-accent를 참조하고 있었다. 면적 밴드와 같은
  규칙으로 --color-royal-amethyst를 쓰고, 규칙 위치도 기슭막이 기본 스타일 옆
  (_Style_Cross_Areas.css)으로 옮겼다.

검증(공용 브라우저, 13+15.7 카드): 벽 클릭 → 강조·화살표 노출, ◀ 2회 이동 반영,
↺ 자동 자리 정확 복귀. tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 16:21:09 +09:00
eomsangdonandClaude Opus 5 6a3c991b5a feat(B06): 기슭막이 선택·X 자리 조절 화살표
- 기슭막이 폴리곤을 눌러 고르면 강조되고 카드 하단에 ◀/▶/↺가 뜬다. 0.1m씩
  화면 좌우로 민다(좌우 벽에서 뜻이 뒤집히지 않게 outward 부호는 내부 환산).
- 구조물 선택이 절·성토 면적 강조보다 우선한다. 벽 클릭은 벽에서 멈춰 밴드·카드
  선택으로 번지지 않고, 한쪽을 고르면 다른 쪽 강조는 꺼진다.
- computeCulvertLayout에 revetShift 인자 추가. 손으로 민 자리는 고정되어 관 길이
  정수 맞춤이 벽을 다시 옮기지 않고 폭으로만 흡수한다(폭 상한 0.45×2).
- 값은 세션 보관(b06:revetx), 이동 범위 ±3m.
- 700줄 정리: Page 751→690(_UI_Page_Station_Controls 분리),
  Cross_View 765→629(_UI_Cross_View_Zoom 분리).

검증: 이동 5케이스 접점 오차 0.00e+00, 계획고 스윕 24케이스 회귀 문제 0,
tsc 통과, pytest 148 pass. 화면 조작 확인은 다음 단계.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 16:14:17 +09:00
eomsangdonandClaude Opus 5 a04da05fe1 feat(B06): 배수관 기슭막이 여유고·성토 물매 재설계
- 기슭막이 높이 = 관경 + 여유고 0.5m (0.1m 눈금 올림). 좌우 여유고 동일.
- 관 길이는 절단 긴 변 기준 정수 m. 벽 자리 이동으로 맞추고, 물매·5m 제약에
  걸리면 벽 폭으로 흡수(폭은 5m 한계를 넘지 않는 범위까지만).
- 성토 물매를 1:1.2 고정에서 1:1.2~2.0 범위(성토_비탈면.md §1)로 전환.
  벽 자리가 굳은 뒤 물매를 역산해 사면선이 벽 이음선 상단점을 지나게 한다.
  종전에는 관 길이 맞춤이 벽을 옮겨 접점이 깨졌고 스냅으로 가리고 있었다.
- 성토 사면선은 단일 각도 직선 하나를 배수관 레이아웃이 직접 공급(설계선 대체).
- 벽 자리 탐색 상한 = 성토 사면 끝, 사면길이 5m 초과 전까지. 성토고 3m 이상이면
  5m 쪽으로 끌어올린다.
- 기슭막이로 성토를 못 받는 자리는 structureRequired로 표시(옹벽·석축 검토).
- 700줄 제한으로 Const/Types/Solve 3개 파일 분리.

검증: 계획고 -2.0~+3.0 스윕 24케이스 문제 0 (접점 오차 <1e-6, 여유고 0.5,
5m 초과는 전부 경고). tsc 통과, pytest 148 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 15:51:54 +09:00
eomsangdonandClaude Fable 5 0d5fba4400 feat(B06): 배수관 횡단도 세트(배관·기슭막이/집수정·보호공) 추가
B05에서 배치한 배수관 측점의 B06 횡단도에 배관·기슭막이(또는 집수정)·보호공을
분리 도형으로 그린다. 기존 도형(지반선·면적 밴드·포장·암 경계)은 손대지 않고,
계획선 표시 규칙만 세트와 정합을 맞춰 함께 정비했다.

- 백엔드: pipe_points.json 정본(facility=="pipe")에 레지스트리 기본값을 채워
  chainage ±0.02m로 맞는 횡단에 culvert 키를 얹는다(Engine_Culvert 신규, Router의
  상세조회·재생성 두 경로에서 호출). 횡단 dict는 자유형이라 Pydantic 변경 없음.
- 배관: 유입 invert = min(노견 아래 원지반, 노면고 − 관경 − 토피 0.5), 유출 앵커는
  성토사면이 지반과 만나는 사면 끝(성토사면 길이 5m 한계 — 별표2 Ⅰ.2.차.(3)).
  역경사는 수평 클램프, 길이는 m 단위 올림. 단면은 축 법선 방향 직사각형이고
  외경선(실선)+내경선(점선) 2겹으로 관벽 두께를 보인다(파형강관 2.7T — KS D 3590).
  끝단면은 구조물의 계류측 변을 복사해 자른다.
- 기슭막이: 배면 수직 사다리꼴 + 전면 평행사변형 띠(1:0.3, t=0.45 — 실무 L3=45)의
  합성 단면. 높이는 이음선 상단점이 성토 사면선과 만나는 접점까지, 하한 관경+0.45,
  상한은 형태별 한계(찰 3.0/메 2.0 — 교본 7-3). 근입 0.5m(실무 기초콘크리트 H=0.5).
  돌 해칭은 벽 폴리곤 clipPath 안에만 그려 어떤 높이에서도 벽 밖으로 새지 않는다.
- 집수정: 절토측 유입이거나 원지반이 관 단면의 30% 이상을 막으면 자동 전환.
  I형(벽)·ㄴ형(+바닥)·ㄷ형(+반대측 막음), 기본 ㄴ형·내공 1.0m. 구조물이 원지반
  안쪽에 박히면 절토선을 공사 계획선(보라 실선)으로 긋는다. 라벨은 I형 벽 하단.
- 보호공: 시작 윗점 = 관 하단 꼭짓점, 시작 변은 기슭막이 전면과 같은 경사.
  성토경사를 따라 원지반까지 내려간 뒤, 최소 길이(낙차고×2)를 채울 때까지 원지반을
  따라 더 간다.
- 계획선 표시: 원지반과 차이 없는 구간은 그리지 않되(보라 점선 폐지), 노면·노견·
  측구부터 사면 1차 접점까지는 항상 그린다. 측구는 노견 바깥에 붙으므로 보호 범위를
  측구 폭만큼 넓히고 접점 탐색도 그 바깥에서 시작한다. 배수관 측점은 벽 접점에서 트림.
- B05: 배수관 측점 계획고를 지반고 + 관경 + 토피 0.5m 아래로 내리지 못하게 막고
  경고 토스트를 띄운다.
- 700줄 제한: 오버레이 파일이 919줄이 되어 기하(_Geom 678줄)와 그리기(247줄)로
  분리했다. import 경로는 재수출로 유지해 B05·Cross_View는 건드리지 않았다.

근거 미확정(코드 주석·툴팁에 명시): 토피 0.5m(별표2 교량·암거 복토 50㎝ 교차 참조),
기슭막이 근입 0.5m(실무값), 흄관·VR관 관벽 두께(관경÷12 — KS F 4403 미확보).

검증: tsc, ruff, pytest 148 passed(신규 test_b06_culvert_set.py 6건), 헤드 브라우저 —
4+4.3·13+15.7 세트 표시, 보호공 시작점과 관 하단 꼭짓점 간격 0.6px 이내·시작 변
기울기 실측 0.223(= 0.3·H/(H+0.5) 이론값과 일치)·최소 길이 5.0m 확보, 계획선
세그먼트 연결 틈 0개(8·9·10·12·4+4.3). ⚠ 13+15.7 성토사면 5.03m로 법정 5m를
0.03m 초과 — 툴팁에 표기하고 접점 보간 여부는 사용자 판단 대기.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 19:43:51 +09:00
eomsangdonandClaude Fable 5 a6197cdc46 fix(B06): 횡단 반폭 표시 기본값 12가 20으로 되돌아오던 문제
원인: 진입 로직이 data.options.cross_half_width_m을 '사용자가 확정한 표시 반폭'으로
보고 입력칸을 덮었다. 그 값은 종·횡단을 만들 때 쓴 **샘플링(계산) 반폭**이고
백엔드 기본이 20m라, 표시 기본값 12를 넣어도 진입할 때마다 20으로 돌아왔다.

수정: 계산 범위(백엔드 20m)는 그대로 두고, 입력칸은 사용자가 실제로 고른 표시
폭만 되살린다 — 측점 개별 표시 반폭 저장값(design.display_half_width_m)의 최대값,
그다음 세션에 남은 마지막 조절값 순. 둘 다 없으면 표시 기본 12m.

검증: tsc, pytest 125 통과, 헤드 브라우저 B06 탭에서 반폭 12·횡단면도 X축 12~-12 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 19:52:20 +09:00
eomsangdonandClaude Fable 5 8812657022 feat(B05/B02): 표시 정보 정비 + 설계속도 축 도입
- 종단 상단 표시줄을 법정 판정 3항목으로 축소: 최대 기울기/상한(별표2 Ⅰ.2.라),
  절·성토 불균형(Ⅰ.1.나.(4)(다)), 종단곡선 필요 n곳(Ⅰ.2.마 — 대수차 5% 초과인데
  곡선이 빠진 변화점). 변화점·종단곡선 개수·기본 곡선길이 L·중복 경고칩은 제거.
- [초기선 복원] → [편집 되돌리기] — 실제 동작은 화면 편집 델타 삭제이지 저장 지점
  복귀가 아니다. 툴팁에 동작과 [초기화]와의 차이를 적었다.
- 3D 뷰포트 안내 라벨 삭제(로딩 완료 후 남던 조작법 문구).
- 배수유역 버튼 정비: 유역 다시 나누기 / 선택한 관 삭제 / 배관 배치 초기화 +
  각 툴팁에 실제 동작 명시(선택 삭제는 툴팁 자체가 없었다).
- 유토곡선 요약 12칩 → 5칩(절토·성토·잉여|부족·운반·검산). 토질 3종 내역·다짐
  환산·블록 수·장거리 운반·사토는 해당 칩 툴팁으로. B05·B06 공용 함수라 동시 반영.
- 설계속도 축 도입(임도는 속도를 낼 수 없는 노선 — 기본 20km/h):
  · 임도 종류는 프로젝트 등록값(projects.road_type)을 읽어 B05가 읽기 전용 표시
    (main→간선임도, fire→산불진화임도, 그 외→작업임도). 화면에서 고치지 않는다.
  · 설계속도 선택(간선·산불진화 20/30/40, 작업 20 고정) 신설 — 종단기울기 상한과
    종단곡선 반경이 등급이 아니라 이 값으로 정해진다(지식DB 설계제원_총괄 §6·§7).
  · B02 임도 종류 선택지를 현행 3종으로 정리(지선 폐지·계류보전은 사방 구분).
  · 백엔드: ROUTE_GRADE_CLASSES 3종+branch 호환, selectable_design_speeds 신설,
    resolve_design_speed 신설, legal_grade_limit_pct·resolve_grade_options에
    설계속도 인자, sections/context가 road_type 제공(B06도 저장값 승계).
  · 계획선 정책은 그릴 때마다 현재 기준으로 동기화 — 저장분의 옛 상한이 남지 않는다.
- 검증: pytest 125 통과(설계속도 12건 신규), tsc, 헤드 브라우저 — 진입 시 상한 9%,
  40km/h 전환 시 7% 즉시 반영, 원복 9%, 안내문 '간선임도 · 설계속도 20km/h ·
  일반지형', 유토곡선 5칩, 유역 버튼 새 이름·툴팁, 3D 라벨 빈 문자열 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 19:46:03 +09:00
eomsangdonandClaude Fable 5 0cb772a351 feat(B05): 기슭막이 보호공 삭제·바닥막이 부활·지형 기준 즉시 반영
- 기슭막이는 기슭(사면)을 막는 공정이라 그 아래 돌붙임이 붙을 자리가 아니다
  (2026-08-19 사용자 지시). 배관 유입·유출부와 독립 기슭막이에서 보호공
  (돌붙임 찰/메·도수로)·보호공 면적·도수로 폭 옵션을 전면 삭제.
- 바닥막이(bed_sill) 부활 — D군 점형, 형태(돌붙임 찰/메)·면적·높이
  (기본 메·10㎡·0.3m). 바닥 보호는 이 구조물이 담당한다.
- 독립 기슭막이(D4)를 시설 서브폼에서 떼어 C군과 같은 레지스트리 옵션 방식으로
  전환: 측점 범위 + 기준측점 전/후, 기본 돌쌓기(메)·높이 2.5·길이 10·전 5·후 5.
- 페이지 설정의 지형 구분·등급·최대 종단기울기를 바꾸면 안내문·placeholder와
  종단 그래프 위반 판정이 즉시 갱신된다(profilePanel.setGradeLimit 신설).
  계획선 자체 재산출은 서버 재계산 몫이라 건드리지 않는다.
- 지식DB 재점검(설계제원_총괄 §4·§6·§7): 종단기울기·종단곡선 반경 표는 일치.
  미해결 3건(폐지된 "지선" 선택지·등급↔설계속도 고정 매핑·최소 곡선반경 안내가
  종단곡선 반경)은 값을 임의로 바꾸지 않고 주석으로 남겼다 — 사용자 협의 대기.
- 검증: pytest 113 통과, tsc, 헤드 브라우저(D군 목록 바닥막이, 기슭막이 범위+
  전/후·보호공 없음, 배관 서브폼 보호공 라벨 소멸, 지형 변경 7%→10%·위반 재판정).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 19:12:37 +09:00
eomsangdonandClaude Fable 5 0b1a66b8d1 feat(B05/B06): 입력 흐름·알약 번호·초기화 모달·전후 분할·표시 반폭 정비
- 위치 마지막 칸 Tab → 상세 옵션 첫 칸(잠금 해제보다 탭 계산이 빨라 메모로
  건너뛰던 문제). 화면 순서(위→아래) 그대로 이동.
- [초기선 복원] → "저장선 복원"으로 문구 교정 — 복원 목표는 마지막 저장선이다
  (임시저장 시 편집이 정본에 반영). 최초 자동 계산 복귀는 [초기화] 안내.
- 종단 알약에 좌측 목록과 같은 중복 번호("옹벽 1/2") — 라벨·툴팁·벌룬 동일 표기.
- [초기화] 무동작 수정: 원인은 playwright 연결 브라우저의 네이티브 confirm 자동
  취소. 공용 showConfirmDialog 모달(ui_template_elements) 신설로 교체.
- C군 옵션: 전길이 → "기준측점 전" + "기준측점 후" 신설(기본 10/5/5). 나중에
  입력한 쪽이 살아남고 반대쪽 = 길이 − 그 값. 저장은 before_m 기준(후는 파생).
- B06 횡단 반폭 표시 기본 20 → 12 (계산·보유 샘플 폭은 백엔드 20m 유지 — 표시
  범위만 좁힘, 저장·세션값 있으면 그 값 우선).
- 측점 범위 표기 폰트 = 기준 측점 입력 칸과 동일(13.33px), 볼드 유지.
- 검증: pytest 112 통과, tsc, 헤드 브라우저 — Tab 포커스 '높이', 전7→후3·후2→전8
  연동, 범위 2+12.0~3+2.0, 알약 '옹벽 1/2', 초기화 모달 표시, 저장 왕복·원복.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 18:56:06 +09:00
eomsangdon 074bf9c0c0 auto: 2026-08-19 18:33 (EOMSANGDON-HOME) 2026-08-19 18:33:03 +09:00
eomsangdonandClaude Fable 5 2745168888 feat(B05): C군 기본값·마커 민감도·3D 우클릭 배치·메뉴 단일화·3D 스냅·측점선 연장
- C군 기본값 확정(2026-08-19 사용자): 높이 2.5·길이 10·전길이 5 — 기본값이 생겨
  required 해제. 기준 측점만 넣으면 범위가 바로 계산된다.
- 드래그 민감도 완화: 종단 알약(누적→변위 14px, 임계 전 시각 이동 금지)·배수유역도
  관 마커(이동 시작 8px 임계) — 고르려다 옮겨지는 문제.
- 3D 노선 우클릭 → 구조물 배치 메뉴(신규 B05_Profile_UI_Viewer_Menu) — 지형 픽을
  노선 폴리라인에 투영(15m 이내), 그래프·배수유역도와 같은 2단 메뉴·addAt 경로.
- 우클릭 메뉴 전역 단일화(ui_template_context_menu): 새 메뉴가 열리면 다른 영역
  메뉴는 닫히고, 좌클릭·중간버튼은 어디서든 닫는다(캡처 단계).
- 3D 비정규 측점(배관 등) 좌표를 노선 폴리라인 chainage 투영으로 정확화 — 규칙
  측점 직선보간의 곡선 모서리 잘림(노선 이탈) 해소.
- 3D 측점선(노란 띠) 도로 반폭 1.5배 연장 — 측구 방향 램프는 끝단에 따라붙음.
- 검증: pytest 112 통과(정책 테스트 기본값 반영), tsc, 헤드 브라우저 저장 왕복
  (기준 3+0 → 55~65·anchor 60·before 5, 목록 '배수관 1/2' 번호 표기).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 18:32:55 +09:00
eomsangdonandClaude Fable 5 19c0b085ab feat(B05): C군 전길이 분할·옹벽 명칭 단순화·목록 중복 이름 번호
- C군 5종에 전길이(before_m, 기본 0) 옵션 신설 — 시작 = 기준 − 전길이,
  후길이 = 길이 − 전길이 자동. 종단 마크 = 기준점, 띠 = 시작~종료(기존 렌더 유지).
  전길이 > 기준(시작 음수)은 칸 붉힘으로 거절. 구 저장분은 폼 로드 시 역산 채움.
- 옹벽(철근콘크리트) → "옹벽" (전역 표기는 레지스트리 name 단일 원천).
- 좌측 구조물 목록: 같은 이름 여럿이면 노선 시점 가까운 순 "이름 1/2…" 번호
  (numberDuplicateNames 공용 헬퍼 — B06 목록 신설 시 재사용, 2026-08-19 사용자 지시).
- 검증: pytest 112 통과, tsc, 헤드 브라우저(CDP 캐시 비움 방식) — 옵션 순서
  높이→길이→전길이, 전5 범위 2+15.0~3+5.0, 목록 "옹벽 1/2", 원복 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 18:17:22 +09:00
eomsangdonandClaude Fable 5 84a73a3c09 feat(B05): C군 사면안정 5종 범위 입력 개편 — 기준 측점+길이 계산 표시
- 레지스트리: C군 5종(옹벽·돌쌓기 찰/메·흙막이·큰돌쌓기)에 길이 옵션 신설,
  높이와 함께 B05 필수 입력(phase b05)으로 전환. 순서 = 높이 → 길이.
- 패널: 구간 직접 입력(시작·종료) 삭제, 기준 측점 위 '측점 범위' 표시 행 신설
  — 기준+길이로 "시작 ~ 종료" 실시간 계산, 저장 시 시작=기준·종료=기준+길이.
- 구간 직입 시절 저장분 호환: 폼에 열면 길이를 시작~종료에서 자동 역산.
- 검증: pytest 111 통과(tmp/tests 정책·저장소 테스트 갱신), tsc, 헤드 브라우저
  저장 왕복(60~90·len=30·h=2.5) 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 18:04:03 +09:00
eomsangdonandClaude Opus 5 7df9ae622a feat(B05): 측점 입력 전역 정규화 — 잔여거리 넘침을 측점번호로 올림
측점 표기 규칙(2026-08-18 사용자 확정): 잔여거리는 [0, 간격 20m) 범위만 유효,
넘치면 측점번호로 올려 표시한다(1+30 → 2+10). 저장 수치는 원래 누가거리라
계산은 이미 동일했고, 입력 칸 표시를 확정(change) 시점에 정규화한다.
시작·기준·종료 측점 세 칸 공통(stationFields 확장).

검증(헤드 브라우저): 1+30→2+10.0, 0+45→2+5.0, 3+19.9 유지, 3+20→4+0.0 PASS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 19:51:08 +09:00
eomsangdonandClaude Opus 5 99c94777af feat(B05): 페이지 개선 2차 — 우클릭 메뉴 일원화·벌룬·문구·초기 표시 (PLAN 3-1~3-7)
- 3-1 우클릭 메뉴 일원화: 종단그래프·배수유역도 빈 자리 메뉴 = 사이드 「구조물
  배치」와 같은 구조물군(A~G·기타) → 종류 2단 아코디언(공용 컨텍스트 메뉴에
  하위 메뉴 지원 추가). 선택 = 즉시 추가가 아니라 폼 자동 지정(addAt, A군은
  임시 배치까지). 구 [배관 추가]·평면 나열·기성막이/대피로 항목 흡수.
- 3-2 유역 리스트 문구: 세월교 검토→세월교 제안, BOX암거 후보→BOX암거 제안,
  추천 Ø{d} 배관→Ø{d} 배관 제안.
- 3-3 구조물 알약 벌룬: 아래(테이블에 가림) 대신 위로 — 1행 좌상, 2행 우상,
  솔로 위 중앙.
- 3-4 사이드: 스크롤 영역 상단 여유 + 페이지 설정 샘플 간격 2열(종단 먼저).
- 3-5 배수유역도 위성사진 기본 꺼짐.
- 3-6 B04 초기화 버튼 톤 다운 — 붉은 테두리·글자만, 채움 없음.
- 3-7 그래프 빈 공간 클릭 = 완전 해제 — 알약 해제 신호가 아예 없던 것 수정 +
  외부 해제 시 구조물군·종류까지 리셋(선택 없을 땐 유지).

검증: tsc·vite + Playwright 헤드 실화면 V1~V8 전부 PASS (PLAN.md 3-8).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 19:38:52 +09:00
eomsangdonandClaude Opus 5 4b504f2e2c fix(B05): 임시 배치 자기 삭제·설계유량 미도착 — 헤드 브라우저 테스트로 확정
Playwright 헤드 테스트(사용자 동석)로 잡은 두 버그:

1. 임시 배치 자기 삭제: 관 추가 직후 전역 선택 동기화에서 투영 측점이 아직 없어
   사이드에 null(해제)이 전달 → 해제=임시 취소 규칙에 걸려 방금 넣은 관을 즉시
   지웠다. 투영 측점이 없어도 누가거리를 그대로 넘기도록 수정(Selection.ts).
2. 월류 높이 미계산: 세부유역 재계산 완료 후 선택 통지가 조용히 끝나 폼이
   설계유량을 못 받았다. setPipeFacilities의 임시 관 추적 지점에서
   setDesignFlow로 직접 반영.

검증(테스트 프로젝트, 화면 확인): 섹션 순서·경로계산 비활성·옵션 잠금/해제 시점·
임시 배치(3+5.0)·삭제/리셋 취소·[추가] 확정·물넘이 월류폭 5m 기본·월류 높이
0.07m 자동(설계유량 1.118㎥/s)·미만 입력 보정·초과 입력 허용·목록 재클릭 해제
전부 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 19:14:05 +09:00
eomsangdonandClaude Opus 5 47fa05abd3 fix(B05): 측점번호+잔여거리 확정 즉시 유역 임시 계산 실행
잔여거리까지 입력해도 입력군을 떠나기 전에는 임시 배치가 나가지 않았다
(2026-08-18 사용자 보고). 잔여거리 값 확정(change) 즉시 commitPosition을
실행하고, 측점번호 수정은 잔여거리가 이미 있을 때만 즉시 반영한다.
focusout 경로는 잔여거리 없이 정측점만 쓰는 경우의 확정용으로 유지.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 18:49:36 +09:00
eomsangdonandClaude Opus 5 33fe2fa660 feat(B05): 옵션 활성화 시점을 위치 입력 확정 시점으로 통일
측점번호만 넣어도 옵션이 풀리던 것을, 임시 배치와 같은 시점 — 측점번호+잔여거리를
다 받고 입력군을 빠져나온 순간(commitPosition) — 으로 맞춘다(2026-08-18 사용자
지시). 값을 지우면 확정이 풀려 즉시 다시 잠긴다. 기존 항목·우클릭 추가는 위치가
실려 열리므로 처음부터 활성.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 18:47:42 +09:00
eomsangdonandClaude Opus 5 2e6f657f39 fix(B05): 임시 배치 좌표 = 측점번호+잔여거리 확정값 — Enter도 focusout 경로로 통일
측점번호 칸에서 Enter 시 잔여거리 0으로 즉시 배치되던 빈틈 제거. Enter는
포커스만 빼고, 임시 배치는 입력군 이탈(focusout) 한 경로에서 두 칸 합산값으로만
나간다. 배치 좌표는 스냅 없이 입력값 그대로다(노선 범위 클램프만).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 18:44:16 +09:00
eomsangdonandClaude Opus 5 cdf4814719 fix(B05): 임시 배치를 측점+잔여거리 입력이 끝난 뒤로 지연
측점번호만 넣고 잔여거리 칸으로 넘어가는 순간(blur) 임시 배치가 나가 재계산
동기화가 입력을 끊었다(2026-08-18 사용자 보고 2차).

- 임시 배치 시점 변경: 측점 입력군(positionRow)에서 포커스가 완전히 빠져나간
  뒤(focusout + rAF 판정) 또는 Enter. 칸 사이 이동 중에는 나가지 않는다.
- 관이 계획선에 스냅되며 입력 누가거리와 어긋나면 임시 추적이 풀리던 것 —
  허용오차를 0.05m에서 0.51m(관 매칭 공통 기준)로 넓히고, 재계산 후 실제
  좌표로 임시·선택 누가거리를 갱신해 계속 따라간다.
- 우클릭 추가는 측점이 확정돼 들어오므로 즉시 임시 배치(기존과 동일).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 18:39:39 +09:00
eomsangdonandClaude Opus 5 52b3dfe616 fix(B05): 임시 배치 재계산이 입력 중인 폼을 덮어쓰던 것
기준 측점을 넣으면 임시 배치 → 세부유역 재계산 → 전역 선택 동기화가 그 관의
폼을 통째로 다시 로드해, 잔여거리를 입력하려는 순간 칸이 비워졌다(2026-08-18
사용자 보고).

임시 배치 중 그 관이 동기화로 되돌아오면 폼은 그대로 두고 설계유량만 갱신한다
(facilityOptions.setDesignFlow 신설 — 필드 값 불변, 월류 높이 재계산만).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 18:35:21 +09:00
eomsangdonandClaude Opus 5 3c05052418 feat(B05): 사이드 패널 입력 로직·레이아웃 개편 (PLAN 2-1~2-5)
- 2-1 선택 해제 복구: 목록 재클릭 = 해제(계곡 통과 시설 포함 — 기존엔 시설이
  항상 재선택됨). 해제는 리셋 버튼과 같은 전체 초기화(resetForm — 구조물군·종류·
  측점·옵션)이며, 시설 해제는 onPipeSelect(null)로 그래프·3D·배수유역도까지 푼다.
- 2-2 입력 순서 가이드: 측점(점형 기준, 구간형 시작·종료) 미입력이면 옵션 칸·부속
  서브폼 잠금(disabled+inert+is-locked 흐림). 입력 즉시 해제.
- 2-3 월류폭·월류 높이: 기본값 세월교 10m·물넘이 5m. 월류 높이 칸 신설 —
  fordSection(Manning 역산) 필요 수심을 자동 기입, 계산값 미만 입력은 되돌림.
  저장 키 ford_height_m(0.01m 정밀도).
- 2-3b A군 임시 배치: 기준 측점 입력 순간 관 지점에 임시로 넣어 세부유역·설계유량
  미리보기. [추가]로 확정, 삭제·리셋·다른 항목 선택·종류 변경·외부 해제 시 관을
  물려 직전 상태 복원.
- 2-3c 우클릭 추가 개편: 종단도·테이블·배수유역도 [배관/구조물 추가]가 즉시 추가
  대신 사이드 폼에 종류·측점을 자동 입력(A군은 임시 배치까지). BOX암거 기본
  제원은 폼에 실려 유지.
- 2-4 컨테이너 병합: 등고선 간격+시작 측점·샘플링+종단 설계 기준 → 「페이지 설정」.
  측점 간격 입력 삭제(STATION_INTERVAL_M=20 고정, 서버 스키마 불변). 순서 =
  구조물 배치 > 페이지 설정 > 경로 계산 설정.
- 2-5 경로 계산 설정 비활성화: 사용여부 미결정 — 본문 inert(조작 불가) +
  is-disabled 흐림. 제목·접기는 유지.

검증: tsc --noEmit 무오류, vite build 성공. 상세는 PLAN.md 2-6.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 18:30:18 +09:00
eomsangdonandClaude Opus 5 d192343012 feat(B05): 구조물 목록 항목 양식 — 측점 좌측·이름 우측, 그 외 정보 삭제
한 항목 = [측점(좌측 맞춤)][구조물 이름(우측 맞춤)]. 메모·"배수유역 연동" 등
부가 표기는 지운다(2026-08-18 사용자 지시).

- labelOfStructure/labelOfPipe("측점 · 이름" 결합 문자열) 폐지 —
  측점 표기만 stationOfStructure로 남기고 이름은 렌더에서 따로 그린다.
- 이름 span: margin-left:auto + text-align:right, 주 정보가 되었으므로
  본문색으로 승격(기존 muted 캡션은 메모용이었다).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 17:29:11 +09:00
eomsangdonandClaude Opus 5 a3382212ea fix(ui): 사이드 액션 줄 분리가 동작하지 않던 선택자 수정
splitSidebarActions가 body 직계자식(:scope >)에서만 .ui-sidebar-actions를
찾았지만, 실제 액션 줄은 페이지 패널 루트(b05-route__panel 등) 안에 있어 분리가
아예 일어나지 않았다 — 직전 커밋에서 sticky까지 걷어낸 상태라 액션 줄이 내용을
따라 끌려 올라갔다(2026-08-18 사용자 보고).

- 깊이 무관하게 찾고, 액션 줄의 실제 부모를 기준으로 [스크롤 래퍼][액션 줄]로 쪼갠다.
- body와 그 부모 사이 중간 요소에 ui-sidebar-fill을 붙여 높이 체인(플렉스 세로
  확장 + min-height:0)을 이어준다. B08 목록의 자체 overflow도 이 규칙이 덮어
  스크롤이 래퍼로 옮겨간다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 17:24:34 +09:00
eomsangdonandClaude Opus 5 a794252e2e refactor(ui): 사이드 패널을 [스크롤 영역][고정 액션 영역]으로 분리
sticky + margin-top:auto 조합은 본문 높이가 패널 높이를 넘나들 때마다 액션 줄이
붙었다 떨어졌다 했다(2026-08-18 사용자 보고). 액션 줄을 스크롤 대상에서 아예 빼는
구조로 바꾼다.

- overlay.ts: 사이드 패널 생성 시 본문의 `.ui-sidebar-actions` 앞 형제들을
  마진·패딩 없는 `.ui-sidebar-scroll` 래퍼로 옮기고 body에 `ui-sidebar-split`을
  붙인다. 페이지 코드는 지금처럼 본문 끝에 액션 줄을 붙이기만 하면 된다.
- overlay.css: split body = 세로 플렉스 + overflow hidden + padding-bottom 0,
  스크롤 래퍼 = flex:1/min-height:0/overflow-y:scroll + gap:inherit(그룹 간격 유지),
  액션 줄 = flex:none(sticky·margin-top 제거).
- B08: 전용 sticky 규칙을 버리고 공용 ui-sidebar-actions로 통합 — B04~B08이 한 규칙.

스크롤바 자리 상시 예약(2026-08-17)은 래퍼가 이어받아 내용 폭은 그대로다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 17:21:40 +09:00
eomsangdonandClaude Opus 5 74b1cd2143 fix(ui): 사이드 패널 액션 줄을 내용이 짧아도 최하단에 고정
지금까지는 sticky만 걸려 있어 내용이 패널보다 짧으면 버튼 줄이 내용 바로 아래에
떠 있었다. 공용 .ui-sidebar-actions에 margin-top:auto를 주고, 액션 줄을 담은
사이드 body를 세로 플렉스로 만들어(:has) 남는 세로 공간을 액션 줄 위 여백이
전부 먹게 했다. B04·B05·B06·B07 공통 적용(B08은 .b08-drawing-actions가 이미
같은 방식).

- B05: 액션 dock 위 구분선·구조물 목록도 함께 최하단에 붙는다.
- B05 .b05-route__panel의 padding-bottom(24px) 제거 — dock이 바닥에 붙은 뒤로는
  버튼 아래 빈 띠로만 남는다. 공용 body 패딩 16px는 dock의 sticky bottom:-16px가 덮는다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 17:12:24 +09:00
eomsangdonandClaude Opus 5 7753c53522 feat(B05): 구조물 목록을 사이드 하단 고정 영역으로 이동
선택한 구조물의 폼 길이에 밀려 「구조물 배치」 섹션 아래 목록이 화면 밖으로
나가던 문제. 목록(<ul>)을 섹션 본문에서 빼 StructuresSection.listRoot로 노출하고,
패널이 하단 고정 영역(b05-route__dock)에 배치한다.

배치 순서: 상단 구분선(dock border-top) → 구조물 목록 → 중간 구분선 →
[초기화][임시저장][횡단 이동].

- 공용 ui-sidebar-actions(sticky·배경·상단선)는 그대로 쓰고, 안쪽만 세로 배치로
  되돌리는 .b05-route__dock 규칙 추가(공용 규칙보다 좁은 선택자로 로드 순서 무관).
- 선택·폼 로드·스크롤 동작은 그대로 — DOM 부모만 바뀌었다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 17:06:06 +09:00
eomsangdon fdd9c77cb3 feat(B05): 배수유역도 필터 버튼을 지도 오버레이로 · 유역 번호 배지를 라운드 사각으로
- 표시 필터 버튼 묶음을 헤더에서 지도 좌측 상단(8px 여백)으로 옮겼다. 버튼 줄과
  상태 문구를 한 오버레이가 세로로 쌓아, 문구가 버튼 아래에서 시작한다
- 버튼 줄은 한 줄 유지. 오른쪽 진행단계 오버레이에 끝이 가려도 창을 넓히거나 그
  오버레이를 접으면 드러난다(사용자 확정) — 두 줄로 접는 쪽이 지도를 더 가린다
- 오버레이 빈 자리는 pointer-events를 흘려 지도 팬·유역 고르기를 막지 않고,
  버튼 위 pointerdown만 지도로 내려가지 않게 끊는다
- 유역 번호 배지를 원에서 라운드 사각으로. 지도 위 다른 숫자가 전부 동그라미라
  크기로만 갈렸다. 크기(지름 22px)는 그대로. B04 지도 배지도 같은 함수라 함께 바뀐다
2026-08-17 20:17:05 +09:00
eomsangdon b92ba4592e refactor(B05): 구조물 설치측·이격 입력 폐지 — 데이터 필드까지 제거
사용자 지시로 두 값을 걷어낸다. 구조물별 옵션·정의는 앞으로 타입마다
따로 정한다. 어차피 소비처가 없어(B06~B08은 structures를 읽지 않는다)
화면에만 남아 있던 값이었다.

- 폼: 설치측 select·이격 칸 행 삭제, 목록 부제·종단 벌룬에서 측 표기 제거
- 계약: StructureSide 타입, StructureInstance.side/offset_m 삭제(프론트·스키마)
- 설계지문에서 두 값 제외 — 후속 단계 무효화 판정에서 빠진다
- 구 저장분은 읽을 때 두 키만 떨어낸다. extra="forbid"라 그냥 두면 정본이
  통째로 버려진다. 다른 낯선 키는 계속 거절한다
2026-08-17 20:04:32 +09:00
eomsangdonandClaude Opus 5 6c6a0c2773 fix(B05): 유역 목록 표기 통일 — 세월교만 유효직경·추천 자리가 뒤바뀌던 것
세월교 줄만 `세월교 검토 (Ø4719mm)`로 추천이 앞, 유효직경이 괄호 안이었다(구 문구
잔재). 같은 열을 위아래로 훑을 때 읽는 방향이 달라진다는 사용자 지적에 따라 네 줄을
`유효직경 Ø…mm → 추천 …` 한 형식으로 맞췄다.

- B05_Drainage_Basin_Bridge 문구에서 {d}를 빼고 "세월교 검토"만 남긴다 — 유효직경은
  앞머리가 적는다
- recommendationOf()가 ford_bridge도 맡아 bridge_required 특례 분기를 없앤다

실화면 확인(서버 기동 + Playwright): 네 줄이 각각 Ø929→추천 Ø1000 배관 /
Ø4719→세월교 검토 / Ø1529→BOX암거 후보 / Ø549→추천 Ø800 배관으로 표시된다.

검증: npm run typecheck 무오류, pytest tmp/tests 124 passed·7 skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 19:33:18 +09:00
eomsangdonandClaude Opus 5 a9c46b9711 feat(B05): 배수 추천 구조물·관경 자동 설정 + 물넘이·세월교 개략 단면
지시 2 — 배수유역도가 유효직경 다음에 추천을 보여 주고, 초기 전처리 계산이
그 값으로 관 지점을 설정한다:
- recommend_structure(): 유효직경 임계로 구조물·관경을 고른다. D≤1500 배관(규격
  스냅 800·1000·1200·1500), 1500<D≤2000 BOX암거 후보, D>2000 세월교 검토.
  판정 근거는 유량뿐 — 계곡 횡단경사·하천 차수는 지형 계산이 필요해 뺐고 화면이
  "현장 확인"으로 안내한다(2026-08-17 사용자 확정)
- WatershedBasin에 recommended_facility·recommended_diameter_mm·required_area_m2
  추가, 응답 payload와 DetailBasin 타입까지 배선
- _apply_recommendations(): 자동 배치 관의 **빈칸에만** 추천을 채운다. 사용자가
  놓은 관(source=user)·이미 바꾼 시설·이미 있는 옵션 키는 건드리지 않는다.
  carry_facility_attributes 뒤에 얹어 승계값이 덮이지 않게 했다
- 유역 목록 표기: `Ø1234mm → 추천 Ø1500 배관` / `→ BOX암거 후보`
- 추천 관경 목록은 레지스트리 pipe_diameter_mm 선택지와 같아야 한다 — 폼에서 못
  고르는 값을 추천하지 않도록 테스트로 묶었다

지시 1 — 물넘이포장·세월교는 지정할 옵션이 거의 없으니 계산값이라도 보여 준다:
- 레지스트리에 ford_width_m(월류 폭) 신설. 기본값 없음 — 지식DB에 폭 근거가 없어
  프로그램이 지어내지 않는다
- fordSection(): 설계유량과 폭으로 필요 수심을 되짚는다. 광폭 근사로 출발해 실제
  동수반경(R=A/P)으로 수렴시킨다 — 근사값을 그대로 쓰면 통수능이 늘 설계유량에
  못 미쳐 판정이 무의미해진다. n=0.017·S=10%는 실무 수리계산서 역산값
  (울진1 물넘이·관 시트가 둘 다 S=0.10에서 검산 일치)
- 폼에 월류 폭 한 칸 + 읽기전용 요약(설계유량·필요 수심·필요 단면·유속). 설계유량은
  유역 payload에서 폼까지 배선(onPipesChanged → Page → setFacility)

⚠ 실무 시트의 수심 0.27m는 Qd 역산값이 아니라 가정 수심이다(B=20·h=0.27의 통수능
41.2㎥/s ≫ 그 시트 Qd 2.54㎥/s). 실무는 단면을 가정해 통수능을 검증하고, 프로그램은
필요 최소 수심을 낸다 — 화면 문구도 "필요 수심"으로 적었다.

검증: pytest tmp/tests 124 passed·7 skipped(신규 17건), npm run typecheck 무오류,
npm run build 성공. 물넘이 산식은 프론트 전용이라 수치 손검증으로 대신했다 —
Qd=2.54·B=20에서 필요 수심 0.0503m·유속 2.526m/s, 통수능이 2.5400㎥/s로 Qd와 일치.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 19:18:28 +09:00
eomsangdonandClaude Opus 5 d8aa525bb8 refactor(B05): 700줄 초과 잔여 2파일 분리 — Page·Profile_Panel
앞 커밋에서 남긴 두 파일을 마저 갈랐다. 상태를 모듈로 옮기면 나머지 참조가 전부
바뀌므로 상태는 제자리에 두고 **접근자만 넘기는** 방식으로 동작·공개 인터페이스를
보존했다.

- Profile_Panel 1152 → 649
  - _Profile_Layout: X축 배치(측점 칸 폭·캔버스 폭·chainage↔x 매핑). 순수 함수
  - _Profile_Heights: 그래프·유토곡선·테이블 높이 배분. 드래그 플래그·상세 유무는
    본체가 계속 들고 접근자로 읽는다(저장 높이 기준 판정 규칙 그대로)
  - _Profile_Render: 본문 재구성(캔버스·그래프·구조물 레인·테이블·유토곡선).
    그리기 시작 시 상태를 스냅숏하되 이벤트 핸들러 안에서만 현재값을 다시 읽는다
  - _Profile_Balance: 상단 균형 표시줄(절·성토·불균형·위반 경고·초기선 복원)
- Page 1031 → 685
  - _Page_Helpers: 설계폭 조회·모델 경계 변환·마커 복원·비정규 측점 보간 +
    시설 표시 이름
  - _Page_Structures: 구조물 정본과 관 지점 정본을 사이드 목록·그래프·3D에 맞추는
    다리. 두 정본을 섞는 지점이라 여기만 상태(비정규 측점 목록·판번호·저장 큐·
    타입 사전)를 팩토리 안으로 옮겼고, 본체는 bridge.irregularStations()로 읽는다

B05_Profile 전 파일이 700줄 이하가 됐다(최대 695).

검증: npm run typecheck 무오류, npm run build 성공(374 modules),
pytest tmp/tests 107 passed·7 skipped, prettier 정합.
프론트 테스트 러너가 없어 실제 화면 동작 확인은 남는다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 18:51:21 +09:00
eomsangdonandClaude Opus 5 77f833bb25 feat(B05): 보호공 개편·종단 기준 기본 접힘·700줄 파일 분리 3건
지시 1 — 사이드 「종단 설계 기준」 컨테이너를 기본 접힘으로. section()에
collapsed 인자를 더해 초기 is-collapsed만 붙이고 토글은 전역 collapsible이
그대로 맡는다(B06 buildGroup과 같은 패턴).

지시 4 — 배수관 유입·유출 바닥 보호를 "보호공" 한 축으로 개편:
- 구 돌붙임 있음/없음 + 표면처리(찰/메) 두 축 → 돌붙임(찰)/돌붙임(메)/도수로.
  도수로·산비탈수로(B4)는 유출부에서 돌붙임 대신 쓰는 공종이라 별도 구조물이
  아니라 이 선택지로 받는다(별표2 유출구~원지반 도달 의무)
- "없음" 삭제 — 물이 흐르는 자리라 보호공은 필수(사용자 확정). 기본값은
  유입 돌붙임(찰)·유출 돌붙임(메)
- 치수는 배타 — 돌붙임이면 면적(㎡, 기본 10), 도수로면 폭(m, 기본 1.0)
- 저장 키 개명 *_pitching → *_protection, *_pitching_finish 삭제,
  *_protection_width_m 신설. 독립 기슭막이(D4)도 같은 축
- 구 저장분은 parse_pipe_points가 읽는 순간 새 키로 옮긴다("없음"은 부위
  기본값으로 승격). 폼 write()도 구 키를 폴백으로 읽어 structures.json 몫을 덮는다
- revetment.pitching_area_m2가 기본값과 required를 동시에 갖던 모순도 정리

지시 5 — 700줄 초과 파일 분리(순수 이동 + import 정리, 공개 인터페이스 불변):
- Drainage_Facility 724 → 401 (+_Facility_Fields 354)
- Structures_Panel 753 → 695 (+_Structures_List 113)
- Drainage_Panel 822 → 693 (+_Drainage_Chrome 150, +_Drainage_Interact 159)
- Page 1031 → 911 (+_Page_Helpers 144) — 아직 초과
- Profile_Panel 1152 — 미착수. 두 파일은 가변 클로저 상태를 곳곳에서 직접
  읽고 써 상태 승격이 선행돼야 하며, 프론트 테스트가 없어 순수 이동으로는
  떼어낼 수 없다. 분리안은 PLAN.md 3-3에 기록

검증: pytest tmp/tests 107 passed·7 skipped(신규 보호공 마이그레이션 6건 포함),
npm run typecheck 무오류, npm run build 성공(374 modules).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 18:19:46 +09:00
eomsangdonandClaude Opus 5 70bfddce1b feat(B05): BOX암거 본체 규격 프리셋·날개벽 기본 제원
- 본체 규격을 실무 관측 규격 프리셋(기본 2.0×2.0·3.0×3.0)으로 받고, 그 밖의
  규격만 "사용자 지정"으로 폭·높이를 직접 입력한다. 저장 키는 어느 쪽이든
  body_width_m·body_height_m 숫자 그대로 — 프리셋 전용 키를 만들지 않아야
  하류(B06 횡단도·수량)가 폭·높이만 읽고 끝난다
- 날개벽 유입·유출을 createWingFields 한 조각으로 묶고(기존 기슭막이
  createRevetmentFields와 같은 패턴) 설치 있음·짧은쪽 높이 1m·길이 2m·
  각도 45°를 프리필. 설치 "없음"이면 제원 칸을 접는다
- setFacility 빈값 폴백을 기본값으로 — 빈 문자열 대입으로 select가
  selectedIndex=-1(공백 표시)되던 문제도 함께 해소
- 레지스트리 정본에 위 기본값 10건 등재하고 required·phase:detail 해제.
  이 값들은 B05 서브폼이 실제로 받으므로 detail 표기가 정본과 어긋나 있었다
- addAt의 managed_by 분기에 BOX암거 한정 defaultOptions 동봉(방어선 —
  현재 우클릭 메뉴는 managed_by 타입을 제외하므로 도달하지 않는다)

기본값 전부 2026-08-17 사용자 확정. 검증: tmp/tests 101 passed·7 skipped,
npm run typecheck 무오류, prettier·ruff format 변경 없음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:36:16 +09:00
eomsangdon 3e9be53e7c auto: 2026-08-17 17:09 (ESD_LAPTOP) 2026-08-17 17:09:05 +09:00
eomsangdon 38ea71e15b refactor(B05): 배관 편집을 구조물 배치 폼으로 단일화 — 별도 시설 폼 폐지
- 자동 배관·수동 배관은 같은 구조물(2026-08-17 사용자 지시) — 별도 편집 UI
  (createFacilityEditor) 폐지. 배관/BOX암거/물넘이/세월교도 일반 구조물과
  같은 흐름(구조물군 → 종류 → 시작·기준·종료 측점 → 옵션 → 추가/수정/삭제)
- createFacilityOptionsForm: 부속 옵션 서브폼이 구조물 폼 옵션 자리에 삽입.
  시설 종류는 종류 드롭다운, 위치는 측점 칸이 담당
- loadPipeForm: 목록·그래프·3D·배수유역도 어디서 골라도 같은 폼에 로드,
  버튼 [수정]. onPipeUpdate 신설(기준점 이동=관 이동, 옵션만=재계산)
- 기슭막이 총/앞/뒤 → 시작·종료 측점 칸 자동 채움. onPipesChanged에
  source·options 추가. 배수유역 패널은 지도·정본 보관·재계산만 담당
- 700줄 대응: 입력 조각을 B05_Profile_UI_Structures_Fields.ts로 분리
  (패널 685줄). tmp/tests 98건·typecheck·build 통과
2026-08-17 15:02:45 +09:00