Commit Graph
870 Commits
Author SHA1 Message Date
eomsangdon ee5fa16f6a Merge remote-tracking branch 'origin/sub_laptop_1' into main_laptop_1 2026-09-03 21:10:10 +09:00
eomsangdonandClaude Opus 5 db91109b5a fix(B03): 입력 버튼 3칸 1:1:1·높이 통일, 토글 아래 빈 자리 제거
사용자 지시(2026-09-03).

- 고르는 자리를 flex 에서 **격자 3칸**으로 바꿈. flex 로는 내용 폭이 배분에 섞여
  288·254·288 로 어긋났고 버튼 높이도 달랐다. 격자는 칸을 먼저 나누므로 1:1:1 이고,
  칸을 꽉 채우게 해 세 칸 높이가 같아진다(실측 277×47 셋 다 동일).
- 빈 오류 줄이 자리를 잡아 토글 아래가 비어 보이던 것 제거 — 글자가 있을 때만 자리를
  차지한다(`:empty { display: none }`, min-height·마진 제거).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 21:06:48 +09:00
eomsangdonandClaude Opus 5 7c3a65e814 feat(B03): 선택 영역 설명 이관 · 임시 보관함 이름·테두리 정리 · 계획노선은 shapefile만
사용자 지시 4건(2026-09-03).

- 선택 영역의 설명 문구를 좌측 안내 패널로 옮기고 본문에는 「입력 파일 선택」만 남김.
- [임시 보관함에서 불러오기] → [임시 보관함]. 버튼을 감싸던 점선 테두리 삭제 —
  버튼 자신의 테두리와 이중이었음.
- 계획노선 도형 카드는 `.shp` 만 받음. CSV 는 내부 계산이 만드는 파일이라 사용자가 넣는
  자료가 아님(사용자 확인). 컨테이너의 CSV 안내 문구도 삭제.
- 이미 `.csv` 로 올라간 옛 프로젝트가 「미등록」으로 보이지 않도록 **서버 파일 매핑에만**
  `.csv → 계획노선 도형` 예외를 둠. 새로 받는 확장자와 이미 받은 것을 갈라 둔다.

좌측 안내 문구도 함께 갱신 — CSV 언급 제거, 버튼 새 이름 반영.

검증: 실측 — 선택 영역 텍스트 「입력 파일 선택」, 보관함 테두리 none·라벨 「임시 보관함」,
계획노선 안내 문구 없음, 카드 확장자 `.shp`, 옛 CSV 는 「완료 · 용화_계획노선.csv」 유지.
typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 21:02:19 +09:00
eomsangdonandClaude Opus 5 061265f605 fix(B06): 암 경계 세션 오프셋을 자릿수 때문에 통째로 놓치던 것
세션에 저장하는 쪽(`createRockBoundaryStore`)은 키를 `toFixed(2)` 로 쓰는데 브라우저
재계산은 `toFixed(3)` 문자열로 찾아 **한 건도 못 읽었음**. 서버 경로는 키를 숫자로
바꿔 비교해 문제가 없었으므로 로컬 계산으로 옮기며 생긴 어긋남임.

키를 숫자로 되돌려 0.01m 단위로 맞춤. B06 에서 암 경계선을 올리내린 값이 이제 B05
유토곡선·횡단 면적에도 그대로 반영됨.

화면 검증(5173→5174, 같은 시점): B05 첫 진입 절토 4,774.1㎥ / 성토 16,690.7㎥,
B06 도 같은 값(재계산 입력·결과 로그로 대조 — 측점 65, 샘플 65, 자연방토 25건까지 동일).
B06 을 거치기 전과 후의 값 차이(성토 16,715.5 → 16,690.7)도 사라져 **첫 진입부터 일치**함.
진단용 임시 로그는 제거함.

전체 테스트 183건 통과, `tsc --noEmit` 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 21:01:56 +09:00
eomsangdon b0fa00f335 Merge remote-tracking branch 'origin/sub_laptop_1' into main_laptop_1 2026-09-03 20:57:52 +09:00
eomsangdonandClaude Opus 5 b9e6a2b6a8 feat(B03): LAS 없이 설계 토글을 입력 컨테이너로 · 켜면 지형 자료 전체 차단
사용자 지시(2026-09-03).

- 토글을 지형 컨테이너에서 **파일 입력 컨테이너**로 옮김 — 무엇을 받을지 정하는
  스위치라 고르는 자리 옆에 선다. 서식도 입혔음(공용 체크 줄 + 켜짐 강조).
- 켜면 지형 자료를 **통째로** 받지 않음: 포인트클라우드·좌표계·래스터 카드를 모두 잠그고
  컨테이너를 흐림. 필수 판정에서도 지형 슬롯 전체가 빠진다.
- 파일 거르기를 확장자가 아니라 **배정된 카드** 기준으로 바꿈 — `.prj` 는 노선·지형이 같은
  확장자라 확장자로 거르면 노선 좌표계까지 함께 떨어졌다.
- 이미 올라간 자료(재입력)는 지우지 않고 **조작만 잠금** — 로컬로 고른 파일만 내린다.

좌측 안내 패널의 글자 크기도 공용 양식에 맞춤 — 본문 `--text-body-sm`·`--color-text-body`
(B04 `b04-surface__check` 와 같음), 제목 `--text-caption`.

검증: 실측 — 토글이 입력 컨테이너 안에 있고, 켜면 지형 카드 4장이 모두 disabled +
[파일 선택] 잠김, 기존 업로드분은 「완료」·파일명 유지. 끄면 원복. 패널 글자 14px/12px.
typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:55:29 +09:00
eomsangdonandClaude Opus 5 bc7b9e3a48 fix(B06): 유토곡선 영역 누락 — 재계산 결과와 계획선 정본이 어긋나던 것
두 곳이 같은 뿌리였음. 브라우저 재계산은 **편집이 반영된 계획고**로 횡단 설계를 만드는데
`design_profiles` 는 저장분 그대로라 두 값의 기준이 갈렸음.

1. 재계산 창구가 방금 푼 계획선을 **공유 캐시에도 얹도록** 함
   (`detail.longitudinal.design_profiles`). 이게 없으면 낡음 판정이 영원히 참이 되어
   B06 유토곡선이 통째로 빈 채로 남았음(사용자 보고). `profile_alignment`(base_pvi)는
   건드리지 않음 — 편집 델타의 기준선이라 편집분을 구워 넣으면 이중 적용됨.

2. B06 진입 정합이 **미저장 세션 편집을 못 보고 건너뛰던** 것. 서버에서 갓 받은 저장분
   끼리는 늘 일치해 「낡지 않음」이 되는데, B05가 세션에 남긴 편집은 그 안에 없음.
   세션 초안이 있으면 판정을 건너뛰고 무조건 맞추도록 함 — 재계산은 브라우저 안에서
   끝나 값이 쌈.

화면 검증(5174, 같은 시점 비교):
  수정 전 — B05 절토 4,774.1㎥ / 성토 16,715.5㎥, B06 절토 4,515.0㎥ / 성토 14,857.5㎥
  수정 후 — 양쪽 모두 절토 4,774.1㎥ / 성토 16,690.7㎥ (일치)
B06 유토곡선 영역도 곡선이 다시 그려짐(문구 없음).

전체 테스트 183건 통과, `tsc --noEmit` 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:49:25 +09:00
eomsangdonandClaude Opus 5 a00c7497c1 feat(B03): 보관함 선택 요약·「업로드할 파일을 선택하세요」 경고 제거
사용자 지시 2건(2026-09-03).

- 임시 보관함 선택 요약(「선택된 보관 자료 없음」·묶음 이름·파일 수)을 없앰. 불러온 자료는
  카드가 곧바로 보여 주고, 고르기 전 상태는 [파일 업로드]가 잠긴 것으로 이미 드러남.
  쓰이지 않게 된 `.b03-file__temp-summary` 규칙과 로케일 2건도 함께 제거.
- 입력 컨테이너의 「업로드할 파일을 선택하세요」 경고를 띄우지 않음 — 아직 아무것도 고르지
  않은 상태를 붉은 글씨로 알릴 이유가 없음. 확장자·개수·필수 슬롯 같은 나머지 사유와
  [파일 업로드]를 눌렀을 때의 검사 결과는 그대로 표시.

검증: 실측 — 보관함 자리에 버튼 하나만 남음(요약 span 없음), 오류 줄 빈 문자열,
한 줄 배치 선택 518px · 보관함 210px · 업로드 102px. typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:47:02 +09:00
eomsangdonandClaude Opus 5 d9fcfa3b96 refactor(B03): 좌측 안내 패널을 B04~B07 공용양식으로 맞춤
처음엔 B03 전용 스타일로 문단을 만들었으나, 좌측 패널 양식은 다른 단계와 같아야 한다는
사용자 지시(2026-09-03). 공용 조립으로 교체함.

- 패널 루트 `b03-file__form`, 문단은 `ui-collapsible ui-sidebar-section`,
  제목은 `ui-collapsible__title` — 외곽선·캐럿·접힘 동작이 전부 공용 CSS·동작이다.
- 값도 `b04-surface__form`·`__group`·`__group-legend` 와 같게 맞춤
  (gap·padding 16, 배경 `--color-surface-raised`, legend `--text-caption`).

검증: 실측 — 문단 클래스 `b03-file__guide-group ui-collapsible ui-sidebar-section`,
패딩 16px, 배경 `rgb(37,31,56)`, 제목 클릭 시 `is-collapsed` 토글·복귀 확인.
typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:42:50 +09:00
eomsangdonandClaude Opus 5 66717162c5 feat(B05): 도구줄 [초기화] 추가 + 쉬프트 선택 구간 빨간 강조
1. [초기화] — [↶] 왼쪽에 둠. 전체 초기화가 아니라 **마지막 [저장] 시점**이 기준점임
   (사용자 지시). 편집 스토어가 저장 시점 편집분(`savedBaseline`)을 들고 있다가 그리로
   되돌림 — 저장한 작업은 남고 그 뒤 편집만 버림. 이력에 기록해 [↶]로 되살릴 수 있음.
   되돌릴 것이 없으면 버튼은 비활성.
   자동 선형까지 지우는 `resetAll`(좌측 [초기화])과는 다른 조작임.

2. [쉬프트]로 고른 직선이 화면에 표시되지 않아 무엇이 잡혔는지 알 수 없었음. 고른 구간을
   빨갛게 덧그림 — 범위는 **직선 + 양 끝 라운드(R)** 임. 쉬프트는 직선을 통째로 올리고
   내리므로 양 끝 호의 모양까지 함께 바뀜. 구간 시작 라운드의 BVC부터 끝 라운드의 EVC
   까지 계획선 샘플을 그대로 덧그려 곡률이 따라옴. 경계에는 점선 세로 표식.

   공용 종단 렌더러(`B06_Section_UI_Longitudinal`)는 건드리지 않고 별도 오버레이로 얹음
   (`B05_Profile_UI_Profile_RunHighlight.ts`). Y 매핑은 그 렌더러가 넘겨 주는 축 눈금에서
   되짚어 같은 스케일을 씀. 편집 버튼층(z-index 4) 아래(3)라 버튼을 가리지 않음.

`tsc --noEmit` 통과, 전체 테스트 183건 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:42:23 +09:00
eomsangdonandClaude Opus 5 68e0a1c67f feat(B03): 고르는 자리 한 줄 · 완료 안내는 좌측 패널 · 결과 목록 제거
사용자 지시 3건(2026-09-03).

- 재접속 현황 배너(「…모두 완료된 프로젝트입니다」)를 좌측 안내 패널 「고르는 방법」
  안으로 옮김 — 고르기 전에 읽을 것과 같은 자리.
- [입력 파일 선택]·[임시 보관함에서 불러오기]·[파일 업로드]를 한 줄(`b03-file__pick-row`)로
  묶음. 좁아지면 접히되 선택 영역이 남는 폭을 먹음.
- 업로드 완료 항목 목록 삭제 — 같은 내용을 카드가 완료 상태로 이미 보여 줌.
  쓰이지 않게 된 `renderUploadResults`와 `.b03-file__results` 규칙도 제거.

곁들여 고친 것 — 카드 격자를 2열 고정에서 `auto-fill minmax(260px, 1fr)` 로 바꿈.
안내 패널을 연 상태에서 카드 폭이 210px 로 눌려 제목이 글자 단위로 접혔음(실측).
제목은 한 줄 말줄임으로 둠.

검증: 한 줄 배치 실측 — 선택 397px · 보관함 331px · 업로드 102px, 높이 76px 로 정렬.
카드 66px(빈 칸)/117px(파일 있음), 제목 줄 높이 21px(한 줄). typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:39:52 +09:00
eomsangdonandClaude Opus 5 c2b3c56664 fix(B03): 컨테이너 패딩 복구 — 테마에 없는 --spacing-20 사용
`padding: var(--spacing-20)` 은 정의되지 않은 토큰이라 선언째 무효가 되어 카드
컨테이너의 패딩이 통째로 사라졌음(2026-09-03 사용자 보고). 16px 토큰으로 교체.

검증: 실측 계산값 — 컨테이너 16px, 카드 12/16px, 선택 바 12/16px, 안내 문단 12px.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:35:29 +09:00
eomsangdonandClaude Opus 5 b8aa5ce014 fix(B05): 종단 기준 절·성토 불균형 표시 삭제 + 유토곡선 깜빡임 제거 + 쉬프트 안내
사용자 지적 3건.

1. 상단 표시줄의 「절·성토 불균형」은 **종단 기준** 값이었음 — 계획선과 지반선 사이 세로
   면적(㎡)의 비라 실제 토량이 아니고 판단 근거가 안 됨. 삭제함. 의미 있는 균형은 횡단
   단면적을 쌓아 부피(㎥)로 내는 하단 유토곡선 요약이고 그쪽은 그대로 둠.

2. 계획고를 연속으로 누르면 유토곡선이 매번 사라졌다 다시 서서 깜빡였음. 재계산 대기
   중에 곡선을 **지우지 않고 직전 것을 그대로 두며**, 요약줄 끝에 「다시 계산 중…」
   칩만 붙임. 재계산이 브라우저 안에서 수십 ms에 끝나므로 화면이 비는 구간이 없어짐.
   아직 한 번도 못 그렸을 때만 예전처럼 문구로 자리를 채움.

3. [쉬프트]에서 아무것도 안 골라지던 것은 **직선화된 구간이 없어서**였음(초기 계획선은
   마디마다 기울기가 달라 직선 구간이 0개). 안내를 갈라 적음 —
   「직선화된 구간이 없습니다 — [직선화]로 먼저 만드세요」 / 「…고르세요 (여러 개 가능)
   — 끝내려면 [쉬프트]를 다시 누르세요」. 직선화 안내에도 취소 방법을 덧붙임.

전체 테스트 183건 통과, `tsc --noEmit` 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:32:46 +09:00
eomsangdonandClaude Opus 5 a059c5f152 feat(B03): 파일 입력 양식 정리 — 안내는 좌측 패널, 본문은 고르는 자리만
사용자 지적(2026-09-03) — 선택 항목이 너무 크고 대중없이 놓임. 안내는 B04·B05 와 같은
공용 좌측 패널로 빼고 본문은 고르는 자리만 남김.

- `B03_FileInput_UI_Guide.ts` 신설 — 필요한 파일 / 고르는 방법 / 알아 둘 것 3묶음을
  공용 오버레이 `optionsContent` 에 실음. 문단 구획은 공용 `ui-sidebar-section`.
- 선택 영역 160px 블록 → 한 줄 바. 긴 문구는 패널로 옮기고 힌트는 한 줄로 교체.
- 카드 `min-height: 220px` 폐지, [선택]을 제목 줄 오른쪽 끝 작은 버튼으로 이동,
  빈 칸은 제목 줄만 남김. 진행바·속도·예상완료는 올라가는 동안만 표시.
- 여백 정리 — 컨테이너 패딩 32 → 20, 그룹 제목 24 → 16px, 격자 간격 24 → 12.
- 좌측 패널이 열리면 본문을 밀어내는 규칙 추가 — B03 은 일반 레이아웃이라 공용
  워크플로 레이아웃의 padding 규칙이 없어 패널이 카드를 덮었음.

검증: 카드 높이 232 → 66px(빈 칸)·117px(파일 있음), 선택 영역 160 → 47px,
문서 높이 1408px 로 한 화면 남짓. typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:31:00 +09:00
eomsangdonandClaude Opus 5 0f068a6c1d fix(B05): 구조물 측점 ▲▼ 버튼이 두 벌 생기고 가짜 변화점을 만들던 문제
같은 구조물 측점이 두 좌표로 존재했음 — 종단 정본은 원값(`85.594514`), 사이드바 목록은
표기 규칙(`n+ 0.0`)대로 0.1m 로 반올림한 값(`85.6`). 중복 제거가 누가거리 키(소수 3자리)
비교라 서로 다른 측점으로 잡혀 버튼이 두 벌 섰음.

문제는 표시만이 아니었음 — 사이드바 쪽 버튼을 누르면 정본 측점에서 몇 mm 떨어진 자리에
**가짜 변화점**이 승격돼 그 구간 기울기가 수천 %로 튀었음(실측 11,858%).

겹침 판정을 키 비교에서 **거리 비교**(0.1m 이내면 같은 측점)로 바꿈. 사이드바 목록이
0.1m 반올림이라 최대 0.05m 어긋나고, 실제로 그만큼 붙은 별개 측점은 없음.

실측(route 132, 관 11개): ▲ 버튼 75 → 65개, 근접 중복쌍 9건 → 0건.
전체 테스트 183건 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:23:36 +09:00
eomsangdonandClaude Opus 5 3d037d869e feat(B05): 종단 3D 뷰어에 방위 나침반 추가 + 나침반 위젯 공용 이관
B05 3D 뷰어에는 방위 표시가 없어 방향을 읽을 수 없었음(사용자 지적, 메인 창 경유).
B04 가 오늘 새로 만든 「지면에 누운 나침반 링」을 그대로 쓰되, 두 페이지가 함께 쓰도록
공용으로 옮김.

- `B04_PreProcess_UI_Compass.ts` → `ui_template/ui_template_compass.ts` (git mv).
  `createTerrainCompass({ sizePx, className })` 로 크기·자리를 호출부가 정함.
- 스타일도 `ui_template/ui_template_compass.css` 로 옮기고 모듈이 직접 물고 옴.
  **놓을 자리만** 페이지 CSS 몫 — B04 우하단(`b04-surface__compass`),
  B05 는 ISO 버튼 아래(`b05-route__compass`).
- B05 뷰어는 104px 로 쓰고 렌더 루프에서 카메라 오프셋으로 갱신, 지형이 없으면 감춤.
  좌표 규약이 B04 와 같음(북 −z · 동 +x · 표고 +y, `Viewer.ts:295` 정점 변환) — 그대로 맞음.

화면 검증(5174): B05 나침반 104×104, ISO 버튼 아래 8px. 도북 화살이 뷰 전환에 반응 —
TOP 에서 `M0.00 -33.30`(수직), ISO 에서 `M23.56 -13.60`. 후자는 카메라 오프셋 (d,d,d)
에 대한 투영 이론값(x=R/√2=23.56, y=−R/√6=−13.60)과 일치. B04 쪽도 그대로(84×84,
우하단 16px, 링·화살 색 토큰 유지). `tsc --noEmit` 통과, 뷰어 693줄로 제한 안.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:18:51 +09:00
eomsangdon 6313d2cf58 Merge remote-tracking branch 'origin/main_laptop_1' into sub_laptop_1 2026-09-03 20:13:26 +09:00
eomsangdonandClaude Opus 5 91a0157324 fix(B05): 유토곡선이 편집 중 계속 「다시 계산 중」에 머물던 문제
낡음 판정이 **편집 전 계획선**과 견주고 있었음. 로컬 재계산은 편집된 계획고로 횡단
설계를 갱신하는데 비교 대상은 저장분이라, 편집이 있는 동안 판정이 영원히 참으로 남아
유토곡선이 빈 화면에 문구만 남았음(사용자 보고).

- 그리기(`_Profile_Render`)와 진입 판정(`_Profile_Panel.render`) 모두 편집이 반영된
  계획선(`toDesignProfile(alignment, …)`)과 견주도록 바꿈. 특히 진입 판정은 세션에
  미저장 편집이 남은 채 새로고침하면 「어긋남 없음」으로 나와 재계산을 예약조차 하지
  않았음 — 그래서 새로고침해도 문구가 그대로였음.
- 세월교 측점은 노면이 월류 높이만큼 일부러 내려 앉으므로, 판정에서 `surface_drop_m`
  을 더해 비교. 안 그러면 계획선을 안 건드려도 늘 어긋난 것으로 나옴.

화면 검증(공용 브라우저 5174, route 132): [초기화] 직후 문구 없음·유토곡선 정상
(절토 1,113.5㎥ / 성토 1,424.1㎥). 계획고 ▲ 1클릭 시 문구 없이 즉시 갱신
(절토 1,108.3㎥ / 성토 1,428.6㎥), ↶ 로 되돌리면 원값 복귀. 임시 진단 코드는 제거함.
전체 테스트 183건 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:12:34 +09:00
eomsangdonandClaude Opus 5 b5de29679f feat(B04): 방위 표시를 지면에 누운 나침반 링으로
시안 3종 비교 뒤 사용자 선택(2026-09-03) — TerriaJS·cesium-navigation 계열 표기.
링·눈금·도북 화살을 지면 평면 도형으로 두고 카메라에 투영하므로, 링이 눌린 정도가
곧 시점 기울기이고 도북은 늘 화면의 실제 북쪽을 가리킴.

- 15° 눈금(90°마다 긴 눈금), N·E·S·W 라벨(뒤로 넘어가면 흐림).
- 표고축 침은 내려다볼수록 짧아지고, 점으로 눌리면 Z 라벨을 감춤.
- 위젯 56 → 84px — 라벨이 읽히는 최소 크기.

검증: typecheck·prettier 통과. 리로드 실측 — 위젯 84×84, 링 경로 `M0.00 −33.98…`,
도북 화살 `M0.00 −33.30 L−4.28 −17.14 L4.28 −17.14Z` 로 기본 시점 계산값과 일치.
회전 중 거동은 사용자 화면 검증 대기.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 20:07:29 +09:00
eomsangdonandClaude Opus 5 a35c8ff356 feat(B05,B06): 계획선 편집 중 횡단 재계산을 브라우저에서 수행 — 서버 왕복 제거
사용자 조작 중의 계산은 브라우저 안에서 끝나야 함(2026-09-03 사용자 확정). 계획고가
바뀔 때마다 전 측점 횡단 계산이 `POST …/cross-design/preview` 로 나가 왕복이 조작
속도를 지배했음.

- `refreshCrossDesigns` 를 로컬 계산으로 교체. 계획고는 저장 선형(`base_pvi`)에 편집
  델타를 얹어 TS `buildAlignment` 로 여기서 풂 — 호출부(B05·B06) 시그니처는 그대로라
  단일 창구가 유지됨. 서버 프리뷰는 선형 저장분이 없는 옛 데이터 폴백으로만 남음.
- 표준단면 config 기본값·암 경계 기본 오프셋을 `sections/context` 응답에서 세션에 기억
  (`rememberStandardDefaults`·`rememberRockBoundaryDefault`). 프론트에 config 수치를
  복제하지 않으면서 패널 없는 B05 도 같은 값으로 계산함.
- 디바운스 250 → 60ms — 왕복이 사라져 손을 떼는 즉시 유토곡선이 따라옴.
- 낡음 판정을 `hasStaleDesigns` 로 바꿔 첫 건에서 중단하고, 계획선 유효 샘플을
  샘플 배열당 한 번만 걸러 이진탐색(그리기 프레임당 2.33ms → 0.07ms 실측).
- 파이썬 엔진 2파일·프리뷰 라우터에 「TS 짝 파일과 한 벌」 경고 블록 추가.

검증: `tmp/tests/test_b06_cross_design_mirror.py` 10건 — 토사/암 2단계/L형 측구/포장/
세월교 하강/사면 미닫힘 등에서 파이썬과 TS 결과가 면적·설계선까지 일치. 전체 183건 통과.
`tsc --noEmit` 통과. 실측: route 127(측점 128) 전 측점 로컬 재계산 7.5ms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 19:58:09 +09:00
eomsangdonandClaude Opus 5 dcabce147e feat(B04): 지표면 3D 방위 표시를 3축 트라이어드로 교체
옛 콤파스는 방위각(`atan2(ox, oz)`)만 써서 경사에 따른 남북 압축이 빠졌음 —
사시도 프리셋(오프셋 120·95·135, 앙각 27.7°)에서 바늘 41.6°, 화면 실제 북쪽 62.4°로
20.8° 어긋났음(2026-09-03 사용자 지적).

세계 축 N(−z)·E(+x)·Z(+y)를 카메라 화면 기저(오른쪽 r, 위 u)에 투영해 선과 글자를
그림. 기저는 카메라 오프셋만으로 구함(up = +y 고정). 뒤로 누운 축(깊이 > 0.25)과
정면으로 와 짧아진 축은 흐리게 그려 겹침을 줄임.

검증: typecheck 통과. 기본 시점에서 DOM 좌표가 해석값과 일치 —
N (28.0, 11.0) · E (45.0, 28.0) · Z (28.0, 27.4). 회전 중 거동은 사용자 화면 검증 대기.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 19:54:13 +09:00
eomsangdon de41958446 Merge remote-tracking branch 'origin/main_laptop_1' into sub_laptop_1 2026-09-03 19:42:39 +09:00
eomsangdonandClaude Opus 5 c19af779e4 feat(B06): 횡단 설계 계산 TS 미러 추가 — 브라우저에서 절·성토 면적 산출
사용자 조작 중 계산은 브라우저 안에서 끝나야 함(2026-09-03 사용자 확정). 계획선을
만질 때마다 전 측점 횡단 계산이 서버로 나가 조작 속도를 왕복이 지배했음.

- `common_util_cross_design_areas.ts` — `B06_Section_Engine_Areas.py` 미러
  (사다리꼴 적분 + 절토 토사/암반 분리).
- `common_util_cross_design.ts` — `B06_Section_Engine_Design.py` 미러
  (표준횡단 설계선 구성 + 단면적). config 수치는 복제하지 않고
  `sections/context.standard_cross_section` 을 입력으로 받음.

두 파일 머리에 짝 파일·회귀 테스트를 가리키는 경고 블록을 둠 — 한쪽만 고치면 두 화면
값이 갈림. 아직 어느 화면도 이 모듈을 부르지 않음(다음 커밋에서 연결).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 19:42:31 +09:00
eomsangdonandClaude Opus 5 b908a0b10d feat(B06): 종단면도 구조물 라벨도 배수관 표기로 통일
관종·관경(`파형강관 D1200`) 대신 `배수관` 을 적음 — 횡단 카드와 같은 규칙.
판정을 `structureDisplayName()`(`_UI_Section_Common`) 한 곳으로 모아 두 렌더러가
같은 문자열을 쓰게 함. 저장 라벨은 그대로 — 재진입 이관이 라벨로 종류를 되짚음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 19:35:21 +09:00
eomsangdonandClaude Opus 5 f772401b06 feat(B06): 횡단 카드 구조물 pill 을 배수관 표기로 통일
관종·관경(`파형강관 D1200`) 대신 표시 이름 `배수관` 하나만 적음 —
2026-08-17 확정한 `PIPE_DISPLAY_NAME` 규칙과 같은 표기. 관종·관경은 툴팁에 남김.
판정은 `PIPE_TYPES` 목록으로 하고 저장 라벨은 손대지 않음 — 재진입 이관이
라벨 문자열로 구조물 종류를 되짚기 때문임.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 19:28:10 +09:00
eomsangdon c21b68f2ce @
feat(B06): 횡단 카드 제목행에 성토사면 본래 경사길이 표기

사면 미교차 경고가 붙는 제목행 우측 끝에 성토사면 경사길이를 표기함.
값은 정본 설계선(`design_line`) 기준이라 기슭막이·집수정이 사면을 끊기 전
**본래 길이**이고, 양측 성토는 좌·우 두 값을 다 냄.

- `fillSlopeLengths()` 신설 — 기존 `protectedSpan`·`meetOffset` 재사용,
  성토측만 노견 끝(측구가 있으면 측구 바깥)에서 사면 끝까지 `run × √(1+1/n²)`.
- 미교차 측점은 `≥` 하한값 — 추세 외삽은 지반이 사면과 나란한 자리에서
  수십 m 씩 튀어(740m 측점 101.53m) 길이 표기에 못 씀.
- `meetOffset` 교차점을 두 걸음 사이 선형보간으로 냄 — 반폭 맞춤(1m 올림)에는
  영향이 없고 길이 표기가 탐색 간격만큼 튀는 것만 막음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@
2026-09-03 19:16:46 +09:00
eomsangdonandClaude Opus 5 0ce6b43bdc fix(B05): 전체 측점 계획선에 종단곡선 복원 — 호가 지반고를 통과하도록 꼭짓점 반복 보정
`3651ad98` 의 `only_explicit_curves=True` 로 전체 측점 폴리라인에서 자동 종단곡선이
전부 꺼져, B05 종단 그래프의 계획선이 직선만으로 그려졌음.

- `design_ground_following_profile()` — 변화점마다 기본 L(15m) 종단곡선을 다시 삽입.
  대칭 종단곡선은 꼭짓점을 지나지 않으므로(중앙종거 |A|·L/8), 호와 측점 세로선의 교점이
  지반고가 되도록 꼭짓점 표고를 최대 12회 반복 보정 — `design_pipe_anchored_profile` 과
  같은 방식. 결과: 호의 중심이 측점 세로선 위, 좌우 직선과 접선, 계획고 = 지반고.
- `rebuild_alignment_profile()` — `GROUND_POLYLINE_BASIS` 곡선 생략 예외 제거.
  저장된 `base_pvi` 가 보정된 꼭짓점이라 편집 델타를 지우면 초기선으로 그대로 복귀함.
- 프론트는 payload `only_explicit_curves` 를 그대로 따르므로 코드 변경 없음.
- 호 크기 기준은 현행 유지(2026-09-03 사용자 결정) — L 고정·R 은 결과값, 법정 최소반경
  미만은 경고만.

검증: `tmp/tests/test_b05_ground_profile_curves.py` 4건 + 전체 173건 통과. route 127
실데이터 오프라인 산출에서 호 126개(저장분 0개), 측점 계획고−지반고 최대 0.063mm.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 19:02:03 +09:00
eomsangdon 0f5b4e4df7 auto: 2026-09-03 18:31 (ESD_LAPTOP) 2026-09-03 18:31:54 +09:00
eomsangdonandClaude Opus 5 4fdbcaf09c fix(B07): 장 확정 수량표 결함 3건 — 측점 구분·계획고·확정 해제
장 단위 확정 흐름을 실측하다 드러난 것들이다(2026-09-03, 용화 검증본 3장).

① **측점 구분 없이 역추출** — `_table_values_from_cells()` 가 도면의 표를 전부 훑어
   마지막 값을 모든 측점에 넣었다(실측: 4개 측점 전부 지반고 837.21, 도면에는
   840.87·840.33·836.45·837.21 로 제대로 그려져 있었음). 표 엔티티 id 가
   `uuid5("{도면id}:qtable")` 이라 측점을 되짚을 수 있어 그 표만 읽는다. 옛 도면은
   id 가 안 맞으므로 종전처럼 전부 훑는 폴백을 남긴다.

② **계획고가 빈 채로 나감** — 장 배치 입력의 원본에는 계획고가 없어 계획고·절토고·성토고
   세 칸이 통째로 비었다(21개 항목 중 지반고 하나만 채워짐). `_quantity_table()` 이
   횡단 설계(`design.design_elevation_m`)도 보게 했다.

③ **확정 해제가 404** — [수정]이 도면 목록을 **설계값 없이** 만들어 장 나눔이 달라졌고,
   방금 확정한 장 id 가 목록에 없어 되돌릴 수 없었다. 목록 조회·확정과 같은 인자를 쓴다.

검증(공용 브라우저·실동작) — 확정 해제 404 → **200**, 표 값 `planned=840.87 fill=0.00` 등
측점마다 다름, manifest 수량표가 측점별로 갈림(220 · 240 · 260 · 264 · 280 각각 4/21 항목
채움 — 나머지 17칸은 사용자가 CAD 에서 채우는 자리). 시험 뒤 확정은 모두 해제해 원상복구.
pytest 383 passed·17 skipped, ruff format 무변경.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 16:43:35 +09:00
eomsangdonandClaude Opus 5 e29e3cab67 feat(B07): 유역도 정보표 측점 표기도 n+ 0.0 으로 통일
토적도만 납품 표기(`120+ 0.0`)로 바꿔 두어 유역도 정보표는 `No.6` 으로 남아 있었다
(2026-09-03 사용자 지시로 통일). `station_plus_label()` 을 토적도 전용 모듈에서 공용
`_Engine_Cad` 로 올려 두 도면이 같은 함수를 쓴다. 종단도 표·횡단도 제목의 `No.n` 표기는
그대로 둔다 — 이번 지시 범위가 아니다.

검증 — 유역도 정보표 첫 줄 `(1) No.6` → `(1) 6+ 0.0`. pytest 383 passed·17 skipped,
ruff format 무변경.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 16:09:14 +09:00
eomsangdon 95fdd34351 Merge remote-tracking branch 'origin/main_laptop_1' into sub_laptop_1 2026-09-03 15:50:22 +09:00
eomsangdonandClaude Opus 5 090442bb00 fix(B04): 유역 경계 단순화 허용오차 2.0m → 1.0m (격자 한 칸)
유역 격자가 1m(DRAINAGE_GRID_SIZE_M)라 경계는 1m 계단이다. 허용오차를 격자 한 칸에
맞추면 형상 손실이 격자 오차 안으로 들어가고, 유역별로 따로 단순화해 생기던 공유 경계
어긋남도 줄어든다.

실측(min_area=0 상태, 용화/S자):
- 좌표점        622·829   → 1,749·1,987
- 면적오차      1.86%·1.42% → 1.01%·0.67%
- 유역끼리 중첩 1,043㎡·1,373㎡ → 243㎡·373㎡
- 틈            1,184㎡·2,579㎡ → 369㎡·668㎡
0.5m 이하는 1m 계단 점을 지우지 못해 좌표점만 6배(10,215)로 튄다.

브라우저 실측도 같은 값(API 좌표점 1,750·1,987, 경계 없는 유역 0개)이고 확대해도 계단이
도드라지지 않는다. 테스트 159 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 15:50:12 +09:00
eomsangdonandClaude Opus 5 5331167439 refactor(B05): 구조물 배치 폼 뼈대를 전용 조립기로 분리 (700줄 제한 1차)
`_UI_Structures_Panel` 1,078줄 → 1,024줄. 화면 요소를 세우는 몫만 `_UI_Structures_Form`
으로 옮기고 패널은 값·검증·저장·목록을 맡는다. 배치 규칙(행 순서·구분선·버튼 묶음)은
사용자 지시로 굳은 것이라 그대로 옮겼다.

아직 제한을 넘는다 — 남은 큰 덩어리는 `commit()` 약 200줄과 옵션 필드 렌더·시설 폼
로드 약 170줄이다. 둘 다 폼 상태를 깊게 만지므로 [추가]·[삭제] 실동작 검증을 붙여
따로 옮긴다.

검증 — 공용 브라우저 B05 「구조물 배치」 실측: 제목·측점 행·메모 칸·목록 1개,
버튼 [추가]·[삭제]·[리셋], 구조물군 7항목 그대로. pytest 383 passed·17 skipped,
typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 15:47:16 +09:00
eomsangdonandClaude Opus 5 754e00de19 fix(B07): 장 선택 시 정보 패널을 장 단위로 표기
장(여러 측점을 담은 횡단 도면)에는 측점 단위 지반·계획 값이 없는데도 제목이
「측점 3장 (220~264m)」으로 달려 어느 측점 값인지 오해됐다. 장이면 제목을 「장」으로 바꾸고
「이 장은 측점 여러 개를 담습니다. 지반·계획 정보는 측점 도면에서 봅니다」로 안내한다.

판정은 도면 id(`cross_s…` = 장) 로 한다 — `chainage_m` 은 장에도 첫 측점 값이 실려 와
그것으로는 갈리지 않는다(실측).

검증 — 공용 브라우저 B07: 3장(220~264m) 선택 시 `장 3장 (220~264m) · 잠정 · 이 장은 측점
여러 개를 담습니다…`, 종단도 선택 시 패널 없음(종전과 같음). typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 14:06:11 +09:00
eomsangdonandClaude Opus 5 15c2d81b49 refactor(B06): 횡단 카드 껍데기·반폭 계산 분리 (700줄 제한)
`_UI_Cross_View` 784줄 → 698줄. 도면과 무관한 제목행·하단 정보행을 `_UI_Cross_Card_Chrome`
으로 옮기고, 실효 표시 반폭 계산은 순수 계산이라 `_UI_Cross_View_Metrics` 로, 측점별 줌·팬
상태 맵은 임자인 `_UI_Cross_View_Zoom` 으로 옮겼다. 계산·판정 규칙은 그대로다.

검증 — 공용 브라우저 B06 실측: 카드 65·제목행 65·하단행 65·단면유형 pill 65·사면 미교차
경고 13, 첫 카드 제목행 `0+0.0 / 0.0m / 토사·리핑암·발파암 / 편측 성토 / BP` 로 종전과 동일.
pytest 383 passed·17 skipped, typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 13:56:01 +09:00
eomsangdonandClaude Opus 5 d6d211ef61 refactor(B06): 유토곡선 패널 조립을 전용 모듈로 분리 (700줄 제한)
`_UI_Section_View` 751줄 → 689줄. 곡선 계산 → 차트 → 범례 → 요약줄까지 한 덩어리를
`_UI_Section_View_MassHaul` 로 옮기고, 뷰 컨트롤러는 **붙일 자리**만 정한다(차트는 종단면도와
같은 부모의 형제, 범례는 스크롤 컨테이너 밖). 낡음 판정·계산은 옮긴 자리에서도 공용 모듈
그대로라 동작이 바뀌지 않는다.

검증 — 공용 브라우저 B06 실측: 요약줄 문자열 동일
(`절토(자연) 4,526.8㎥ … 최종 누가토량 −10,213.3㎥`), 범례 1·차트 1·카드 65·상태줄 빈 문자열.
pytest 383 passed·17 skipped, typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 13:50:53 +09:00
eomsangdonandClaude Opus 5 451ed97279 feat(B07): 돌쌓기 해칭 CAD 반영 + 표제란 SVG 서명 벡터 변환
해칭 — 수확기가 `g[clip-path]` 를 통째로 건너뛰어 기슭막이 형태 해칭(돌쌓기·콘크리트·
돌망태·통나무·바자)이 CAD 도면에 하나도 실리지 않았다. 클립을 쓰는 대신 **경계로 잘라서**
싣는다(2026-09-03 사용자 결정). 선분–폴리곤 교차로 안쪽 조각만 남기고, 클립 안 원(통나무
마구리)은 36각 폴리선으로 펴서 같은 방식으로 자른다. 문자는 중심점이 안일 때만 싣는다.

서명 — SVG 로 올라온 자산만 CAD 폴리선으로 바꾼다(2026-09-03 사용자 결정). DXF 로 나가도
선으로 남고 확대해도 깨지지 않는다. `B07_DesignDetail_Engine_Cad_Svg` 신설(path M·L·H·V·
C·Q·S·T·Z 지원, 곡선은 16분할, viewBox 비율 유지·y 뒤집기). PNG·JPG 는 그릴 선이 없으므로
종전대로 ImageEntity, 읽기 실패도 원래 그림을 그대로 둔다.

검증 — `tmp/tests/test_b07_signature_vector.py` 5건 신설(파싱·비율·엔티티 교체·래스터 유지·
손상 SVG), 전체 383 passed·17 skipped. typecheck·prettier·ruff 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 13:46:54 +09:00
eomsangdonandClaude Opus 5 ce4fcc1f13 feat(B07): 토적도 길이별 자동 축척 + 납품 도면 표기 8행 반영
축척 — 노선 연장에 맞춰 **한 장에 들어가는 가장 큰 그림**을 고른다(2026-09-03 사용자 결정).
후보는 도면 관행 축척(1:500~1:6,000, `DRAWING_SCALE_MASSHAUL_H_CANDIDATES`)이고 A1 작도영역
가용 폭 700mm 를 기준으로 판정한다. 실측 — 40m 노선 1:500 · 용화 1,106m 1:2,000 ·
3,465m 1:5,000. 세로는 종이 1mm=50㎥ 고정(도면끼리 비교하려면 같아야 한다).

표기 8행(사용자 확정) — ① 장비명 무대→종무대 ② 값 표기 `Q= 162.41M3`(등호 뒤 한 칸)
③ 지시선 계단형·balloon 모서리 접점 ④ 평형선·띠 경계현 빨강 ⑤ 측점 `120+ 0.0`
⑥ 표 눈금 신설(정규 빨강·추가 회색) ⑦ 행 이름 3.2mm·자간 벌림 ⑧ M.N 소수 2자리 `0+16.90`.

`MM_H` 상수를 없애고 `mm_h` 를 그리기 함수에 넘긴다 — 축척이 노선마다 달라졌기 때문.

검증 — `tmp/tests/test_b07_masshaul_basin.py` 갱신·신설(축척 3건·표기 8행·지시선·눈금),
전체 378 passed·17 skipped, ruff format 무변경.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 13:37:05 +09:00
eomsangdonandClaude Opus 5 2aaa0c594d feat(B05): 세월교 접근선 구간을 3D 패치 리본에 포함
노견 → 벽 상단 접근선 구간이 패치에서 빠져 있어 좁은 좌측 패치 사이로 원지반이 드러나
보였다(2026-09-03 사용자 확정: 「패치로 덮기」). 접근선은 벽보다 위라 덮어도 관 구멍·L자
통로를 막지 않는다 — 벽 전면·유로는 종전대로 리본에 담지 않는다(2026-08-25 사용자 ②).

접근선 줄을 `patchPoints` 앞에 담고 `fillRuns` 에 한 장으로 실어 「구간 1줄 = 리본 1장」
규칙을 그대로 따른다.

검증 — typecheck·prettier 통과. 3D 육안 확인은 카메라 조작이 필요해 다음 화면 검증
묶음에서 함께 수행.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 13:29:29 +09:00
eomsangdonandClaude Opus 5 e83171b2b3 refactor(공통): 작업 좌표계 폴백을 창구 하나로 통합 + 트림 실패 진단
같은 폴백 사다리가 네 곳에 서로 다른 모양으로 흩어져 있었고, 그중 배수유역 라우터
`_route_center_lonlat` 은 노선 CSV 의 `crs_epsg` **라벨**을 그대로 변환에 썼다(라벨과
실좌표계가 다른 사례 실측 — 2026-09-01 용화 라벨 5179 / 실제 5176).

`common_util_crs.resolve_project_crs()` 신설 — 사다리는 ① 노선 crs_input ② 파일 라벨
(원본 좌표를 읽는 자리만) ③ 지형 PRJ(작업 좌표계 정본) ④ DB epsg ⑤ EPSG:5186.
작업 좌표계는 **지형 PRJ 우선으로 확정**(2026-09-03 사용자 결정 — 서피스 격자가 모델좌표의
주인이라 현행 유지). `project_epsg_from_prj()` 도 이 창구로 위임.

더해 지표면 트림이 노선을 통째로 지울 때 노선·지표면 bbox 를 함께 로그에 남긴다 —
"겹치지 않습니다" 만으로는 좌표계 문제인지 측량 범위 문제인지 갈리지 않았다.

검증 — `tmp/tests/test_project_crs_resolution.py` 5건 신설(사다리 4·진단 1),
전체 375 passed·17 skipped, ruff format 무변경.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 13:25:20 +09:00
eomsangdon f91d589ed4 Merge remote-tracking branch 'origin/sub_laptop_1' into main_laptop_1 2026-09-03 13:16:14 +09:00
eomsangdonandClaude Opus 5 8393dfd619 fix(B04): 세부유역 최소면적 필터 제거 — 작은 유역이 통째로 안 그려지던 문제
100㎡ 미만 유역은 `polygonize_labels` 의 최소면적 필터에 걸려 폴리곤이 아예 만들어지지
않았다. 유역 목록에는 있는데 지도에는 없는 상태 — 실측에서 용화 22개 중 1개(64㎡),
S자 48개 중 1개가 그랬다. 링 목록이 조각을 싣게 된 뒤로는 버릴 이유가 없다.

실측: 폴리곤 면적 오차(셀 면적 대비 평균) 용화 5.76%→1.86%, S자 3.56%→1.42%,
경계 없는 유역 1개→0개. 좌표점은 583→622 · 806→829 로 거의 그대로다.
1차 전체 배수유역 등 다른 호출부의 기본값(100㎡)은 그대로 둔다.

S자 실사례 검증: 용화 지형 위에 스위치백 3구간 합성 노선(정점 439·연장 4,528m)으로
신규 프로젝트를 만들어 자동 체인까지 완주 — 관 48개·세부유역 48개, 경계 없는 유역 0개.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 13:13:00 +09:00
eomsangdonandClaude Opus 5 f1bcee7857 feat(B04): 세부유역 경계를 링 목록(외곽+구멍)으로 넓혀 중첩·빈공간 해소
단일 링 자료형이 곧 중첩·빈공간이었다. 아래 유역이 위 유역을 감싸면 구멍이 사라져 위
유역을 통째로 덮고(합성 실측 256㎡ 전량), 한 관의 유역이 두 조각이면 작은 쪽이 사라져
빈공간이 됐다(144㎡).

- `polygon_parts()` 신설 — 조각마다 [외곽 링, 구멍 링...], 넓은 조각부터.
- `WatershedBasin.boundary_parts` 로 교체. `boundary_xy`(가장 넓은 조각의 외곽)와
  `boundary_rings`(편 링 목록)는 파생 속성이라 옛 소비처는 그대로 동작한다.
- API 에 `polygon_rings_lonlat` 추가. 저장 GeoJSON 은 구멍을 가진 Polygon, 조각이
  여럿이면 MultiPolygon.
- 캔버스 4곳(B04 유역화면 채움·선택, B05 배수유역도 채움·선택)은 even-odd 로 한 번에
  채우고 `pointInRings()` 로 판정 — 구멍 안을 눌러도 바깥 유역이 잡히지 않는다.
  중복이던 지역 `pointInRing` 은 삭제하고 공용 것으로 통일.

검증: 단위 5건 신규(도넛 구멍 보존·조각 2개 보존·파생 속성·빈 경계·조립 경로 전체에서
링 2개), 전체 168 passed, typecheck 통과. 브라우저 — API 가 유역 22개에 링 목록을 실어
보내고, 캔버스 even-odd 실측(가운데 알파 0 / 고리 255)으로 구멍이 실제로 뚫린다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 12:40:21 +09:00
eomsangdonandClaude Opus 5 a7f6232c01 fix(B06): I형 집수정 관 하단을 벽면 안으로 제한 — 관이 벽을 관통하게
관 하단 자리는 벽 계류측 변과 원지반의 교점인데, 원지반이 벽 상단보다 높은 자리에서는
교점이 벽 상단으로 밀려 관이 벽 위에 얹혔다(측벽과 배관이 만나지 않음). ㄴ·ㄷ형은 관이
바닥판 윗면에서 시작해 벽 안에 물리는 것과 대비된다.

교점을 벽 상단에서 관경+여유(0.5m)만큼 아래로 제한한다. 원지반이 그보다 낮으면 종전대로
교점을 그대로 쓴다. 벽을 키우는 방향은 벽이 1:0.3으로 기울어 base가 계류측으로 밀리며
지반 교점이 함께 올라가 벽이 7.5m까지 자라 폐기했다.

검증 — 공용 브라우저 B06 I형 8개 단면 실측: 관 유입측 끝단과 벽의 세로 겹침
18.1~56.4px(수정 전 0 — 벽 위로 이탈). ㄴ형 대조(13+4.1을 조정창에서 ㄴ형으로 바꿔 확인)
겹침 유지, 확인 후 세션값 원복. pytest 370 passed·17 skipped, typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 10:32:20 +09:00
eomsangdonandClaude Opus 5 d140d04766 fix(B03): [LAS 없이 설계] 토글이 업로드 버튼 판정을 다시 돌리게 수정
이 토글은 LAS 카드의 필수 여부를 바꾸는데(isSlotRequired) change 핸들러가
updateUploadButton() 을 부르지 않아, 파일을 먼저 고르고 토글을 나중에 켜면 필수 조건이
채워졌는데도 [파일 업로드] 가 잠긴 채 남았다. 새로고침하거나 파일을 하나 더 골라야
풀렸다.

검증: 공용 브라우저에서 저장된 토글 표시를 지워 첫 진입 상태로 재현 — 파일 7개만 고른
상태는 비활성(안내: LAS/LAZ 필요), 토글을 켠 직후 즉시 활성, 다시 끄면 즉시 비활성.
typecheck 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 10:29:09 +09:00
eomsangdonandClaude Opus 5 16a24ace3d feat(B04): 지표면 3D 뷰어에 방위 콤파스 추가
뷰어 좌표 규약이 `x, 높이, -y` 라 세계 북쪽은 -z 다. 카메라 오프셋(카메라 − 타깃)의
수평 성분으로 도북이 화면에서 몇 도 돌아갔는지 계산해(atan2(offset.x, offset.z)) 바늘을
돌린다. 뷰어 우하단 — 축척 막대(좌하단)의 반대편에 둔다.

뷰어 파일이 이미 946줄이라 콤파스는 별도 모듈로 분리(700줄 제한). 애니메이션 루프에서
0.5° 이상 움직였을 때만 transform 을 다시 쓴다.

검증: typecheck 통과. 공용 브라우저 실측 — [상단] 시점 0°(바늘이 북쪽=화면 위),
[사시도] 41.6°, 캔버스 220px 드래그 시 218.6° 로 카메라와 함께 회전.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 10:02:15 +09:00
eomsangdonandClaude Opus 5 9b4abecf9d refactor(B05/B06): 유토곡선 일원화 — 보는 노선·횡단 재계산 창구·낡음 판정 통합
같은 데이터를 두 화면에 보여 주는 기능인데 세 곳이 갈려 값이 달랐다(실측: 절토(자연)
B06 3,704.6㎥ ↔ B05 4,526.8㎥).

① 보는 노선 — B05는 최신 경로, B06은 최신 **확정** 경로를 열어 노선을 다시 탐색한
   프로젝트에서 서로 다른 노선을 봤다(route 126 DRAFT ↔ 125 CONFIRMED, 같은 20m
   측점 성토 4.82㎡ ↔ 85.9㎡). `get_workflow_route_context()`(최신 경로) 신설해 B06
   화면 context가 그것을 쓴다. 납품 도면(B07)이 쓰는 확정 전용 창구는 그대로 둔다.

② 횡단 재계산 — 호출이 두 벌이라 인자가 갈렸다(B06만 표준 단면값·암 경계 오프셋 전달,
   보존하는 사용자 부속값도 2개 ↔ 7개). `B06_Section_Cross_Refresh.refreshCrossDesigns()`
   한 창구로 모으고 세션 편집값은 저장소에서 직접 읽어 패널 없는 B05도 같은 값을 보낸다.

③ 낡음 판정 — 「옛 암 2단계 필드 누락」 조건이 B06 페이지에만 있어 B05는 재계산을
   건너뛰었다. 공용 `staleDesignChainages()` 안으로 옮겨 두 화면이 같은 시점에 같은
   조치를 한다.

검증 — 공용 브라우저 실측: 두 화면 모두 route 126, 요약줄 문자열 완전 일치
(`절토(자연) 4,526.8㎥ · 성토 14,881.8㎥ · 토취 10,213.3㎥ · 최종 누가토량 −10,213.3㎥`).
pytest 370 passed·17 skipped(일원화 검사 4건 신설), typecheck·prettier·ruff 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 09:50:14 +09:00
eomsangdonandClaude Opus 5 6bca521516 fix(B04): 세부 배수유역 배정을 종단 마루 분수령 기준으로 교체
옛 방식은 한 칸 이웃만 보는 국소 하강이라 1m 간격 계획고의 미세 요철에 걸려 멈췄다.
용화 실측: 측점 2,138개 중 1,898개(88.8%)가 저점에 갇혀 흐름이 아니라 누가거리
최근접으로 관에 붙었고, 그 결과 도로 셀 43.2%가 자기보다 높은 관에 배정됐다
(최대 6.82m 오르막).

이웃한 두 관 사이의 최고점(마루)을 분수령으로 삼아 왼쪽은 앞 관, 오른쪽은 뒤 관이
받게 바꿈. 1차원에서 물은 마루를 넘지 못하므로 물리적으로 정확하고 미세 요철에 면역.
첫 관 앞·마지막 관 뒤는 그 관이 받는다. 관 순서는 호출자가 준 그대로 보존.

검증: 단위 5건 신규(전체 163 passed), 실측 오르막 배정 43.2% → 17.6%(최대 4.15m),
잔여 1,993셀은 전부 사그 저류 후 더 낮은 장벽으로 넘치는 경우(어긋남 0).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 09:43:38 +09:00
eomsangdonandClaude Opus 5 23b1e7e5b0 feat(B05/B06): 옛 계획고 유토곡선 노출 차단 + 사면 미교차 측점 경고
① 저장된 횡단이 지금 계획선과 어긋나면(재계산 예약 상태) 유토곡선을 그리지 않고
「횡단을 지금 계획선에 맞춰 다시 계산하는 중입니다」만 띄움. 옛 계획고로 만든 면적이
2초간 보였다가 정본으로 갈아 끼워지던 것을 없앰(2026-09-03 사용자 확정 「새 값만
보여주기」). 용화 실측 — 65측점 중 56개가 낡음, 계획고 차 −9.36~+5.83m,
저장분 성토 42,050㎥ ↔ 정본 14,881㎥.

② 사면이 계산 반폭 끝까지 원지반과 만나지 않아 면적이 잘린 측점에 카드 경고 표기.
판정은 면적을 내는 엔진 한 곳(B06_Section_Engine_Design)에서 `slope_unclosed` 로
내려 화면·수량·도면이 같은 기준을 봄. 계산은 손대지 않음(2026-09-03 사용자 확정
「영원히 못 만나는 지형이 있을 수 있으니 경고로 대체」).

검증 — 공용 브라우저 B06 실측: 2.6초 재계산 안내만 표시(옛 값 미노출), 4.4초 정본
표시, 사면 미교차 경고 13/65측점. pytest 366 passed·17 skipped, typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 09:10:46 +09:00
eomsangdonandClaude Opus 5 56b9bf5280 feat(B03): 계획노선 shapefile 의 CSV 정본화 + LAS 없는 도엽 서피스 좌표계 교정
- 자동설계 체인이 초기값 스냅샷에 `planned_route.csv` 를 함께 남김. 값은 체인이
  이미 만든 정점(사업지 좌표계·트림·조밀화 후)이라 재계산 없음.
- `load_design_route()` 는 surface_params 가 주어진 호출에 한해 그 CSV 정본을 읽음.
  트림 전 원본이 필요한 호출(도엽 범위)은 종전 경로 유지. 지표면·노선이 바뀌면
  `discard_initial_snapshot()` 이 폴더째 지워 경로가 저절로 닫힘.
- `run_sheet_surface_analysis()` 가 노선을 원본 좌표계로 읽어 도엽 서피스를 딴 자리에
  만들던 문제 교정 — `load_design_route()` 로 창구 통일, 도엽 확보 PRJ 탐색도 지형
  PRJ 폴더로 교정. shapefile 노선(5179) + 지형 PRJ(5176) 조합에서 트림이 노선을
  통째로 지우던 원인.

검증: tmp/tests 158 passed(신규 4건 포함), 공용 브라우저 실사용 경로로 용화 shapefile
한 벌 업로드 → 자동 체인 완주 → CSV 정본 643점, 원본 경로와 최대 좌표차 0.00007m.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 08:17:21 +09:00