Commit Graph
541 Commits
Author SHA1 Message Date
eomsangdonandClaude Opus 5 2da4ecb038 feat(B05): 날개벽 탑뷰 투영 — 판 풋프린트 + 성토끝 사다리꼴 박스
날개벽 링은 노선이 아니라 날개 축을 탄다. 그래서 링 폴리곤의 편거리가 노선
편거리가 아니라 패널 두께(±0.10m)라 노견 클립 max(−0.10, +2)에 걸려 날개벽
투영 고리가 0개였다. 실측: 링 좌향과 노선 좌향 정렬 align=0.71, 링 중심의 노선
편거리 2.74~4.16(좌)·−4.01~−2.60(우) — 이미 노견 밖이다.

- `CorridorStructure.wing` 표식 신설, `_Structures_Wing.ts`가 붙인다.
- 날개벽은 도로부 클립을 생략하고 링 위치로 측을 가린다 — 판 두께 × 날개 길이
  직사각형이 나온다.
- `wing-box` 커브 신설(주황) — 밑변은 날개 시작~끝 모서리, 양 옆선은 구조물 축
  (측점 좌향 벡터)과 평행한 고정 직선, 바깥 변은 원본 성토 최하단 끝선 그대로.
  노선 곡률을 따라 각도가 바뀌지 않는다(사용자 확정).
- 성토 끝선은 세트 ±40m만 잘라 쓰고 사거리 15m로 조인다 — 안 조이면 헤어핀
  건너편 끝선에 걸려 −29m짜리 박스(점 115개)가 나온다.
- 교점 탐색은 광선이 아니라 양방향 직선이다 — 세월교 날개는 끝이 성토 끝선
  밖이라(4.16 vs 2.60) 바깥으로만 쏘면 통째로 빠진다.
- `BUILD_VERSION` 32 → 33.

실측: 판 고리가 측당 2장씩 n=11로 살아났다. 박스는 200.92 4/4, 149.73 3/4.
박스 바깥 변의 점은 전부 성토 끝선 위(이탈 0.000m). 149.73 우측 날개 1장은
그 자리에 끝선이 없어 안 그린다 — 처리 방침은 사용자 확정 대기.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 17:47:12 +09:00
eomsangdonandClaude Opus 5 5c8986d46c fix(B05): 구조물 투영 커브를 부재별로 표기 · 저장본 판번호 상향
화면이 안 바뀐 원인은 저장본 캐시였다. `BUILD_VERSION`을 안 올려 코리도 해시가
그대로였고 서버 저장본(planCurves 20개)이 재사용됐다. 실측으로 확인 — 저장본
hash 95cafe53 vs 새 코드 hash 0e67c470. 31 → 32로 올려 만료시킨다.

그리고 겹친 부재를 하나로 머지하지 않는다(사용자: "구조물은 머지하지 말고
표현할 것, 나중에 한번에 진행 예정"). 링 경로 그룹핑·구간 병합을 빼고 부재마다
고리 하나를 낸다.

배관은 투영 면적에서 계속 뺀다 — 다른 부재가 감싸고 있는 구조라는 사용자 확정.

실측(링 횡단선 되투영, 이탈 최대 0.0000m): 84.3 고리 4개 — 집수정 상·하단
2.000~2.650 각 31점, 기슭막이 상단 −2.946~−2.000·하단 −3.250~−2.000 각 47점.
149.73 8개, 200.92 10개(날개벽 4장 각각), 275.71 4개.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 17:25:41 +09:00
eomsangdonandClaude Opus 5 b29113ba22 fix(B05): 구조물 탑뷰 풋프린트를 링별 편거리 병합으로 재구현
기하 합집합(`_Corridor_Union.ts`)이 겹친 스트립에서 무너졌다. "같은 토막이
짝수 번 나오면 버린다"는 내부 칸막이 제거 규칙이 **외곽의 공유 변까지** 지웠다.
4+4.3(84.3m)에서 집수정 두 단은 탑뷰 사각형이 완전히 같아 네 변 전부 소멸해
좌측 커브가 0개였고, 기슭막이 두 단은 안쪽 변 −1.98을 공유해 23칸이 소멸,
0.34×0.92m 쪼가리만 남았다.

합집합을 버리고 구조물이 스윕 솔리드라는 성질을 그대로 쓴다 — 링 경로가 같은
부재끼리 묶고, 링마다 편거리 창을 도로 밖으로 자른 뒤 1차원 병합해 레인으로
잇는다. 기하 불리언이 없어 퇴화 케이스가 원리적으로 없다.

- `_Corridor_Plan_Footprint.ts` 신규 — 위 알고리즘.
- `_Corridor_Plan.ts` — `structureLoops` 제거, 신규 모듈 호출.
- `_Corridor_Carve.ts` — 죽은 `outlineLoops()` 제거(`outerAt`은 유지).
- `_Corridor_Union.ts` — 죽은 `unionOutline`·`insideQuad`·`splitEdges` 제거.
  `UnionQuad`/`unionQuadOf`는 `outerAt`이 계속 쓴다. 189 → 34줄.

실측: 커브 각 점을 가장 가까운 링 횡단선에 되투영해 편거리를 읽었다 — 링선
이탈 최대 0.0000m. 84.3 좌(집수정) 2.000~2.650 31점, 우(기슭막이) −3.250~−2.000
47점으로 전 링이 살아난다. 275.71·149.73·200.92 세트도 날개벽까지 각각 나온다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 17:18:47 +09:00
eomsangdonandClaude Opus 5 25ae04b2cd fix(B05): 변형 실루엣 투영 커브를 행마다 지반선에 트림
실루엣은 소유 측점 단면 한 장이라 그대로 밀면 구간 내내 같은 폭이 됐다.
0.5m 행마다 종단경사만큼 올린 뒤 `trimSlopeToGround`로 그 행 지반과 만나는
자리까지 잘라 실제 발끝을 따라가게 한다. 표기 커브만 바뀐다 — 서피스 절단·
패치는 손대지 않았다(`CARVE_APPLY` 계속 false, 사용자 지시).

4+4.3 우측 실측: 바깥끝 offset −3.25 고정 → −2.96~−4.42(지형 따라), 행 11 → 21.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 16:24:56 +09:00
eomsangdonandClaude Opus 5 5a3b2ebe39 feat(B05): 구조물 탑뷰 투영 커브 재작성 — 세트별 상단+5m 평면·유입/유출 분리
구조물 추가 뒤 3D 투영 영역이 제대로 안 만들어지던 문제. 평면고가 구조물과
무관한 모델 전체 최고표고였고, 구조물 커브와 비탈 커브가 다른 기준으로 따로
나왔으며, 성토면 표면 위에도 절단 투영선이 겹쳐 그려져 이중 표기였다.

- `_Corridor_Plan.ts` 신규 — 구조물 세트(같은 측점 소유)별로 투영 평면을
  그 세트 구조물 최고표고 +5m에 잡고, 유입/유출을 나눠 커브를 만든다.
  세트당 구조물·비탈(변형 실루엣)·비탈(원본 성토선) × 유입/유출.
  도로부(노견 안쪽)는 전 커브에서 빼 좌우가 끊긴 두 루프가 된다.
- `_Corridor_Carve.ts` — 투영 전용 함수(풋프린트 평면 투영·유입유출 판정·
  절단 트레이스 조립) 삭제, `ringEdges` 공개. 패치 리본 경로만 남겼다.
- `_Corridor_Build.ts` — 성토면 위 절단 투영선(`carveTraces`) 생성 삭제,
  `structurePlan`/`fillPlan` → `planCurves` 하나로 교체.
- `_Corridor_Mesh.ts` — 표면 위 투영선 그리기 삭제. 커브를 각자 평면고에
  종류별 색(구조물 노랑/변형 분홍/원본 하늘), 유입 실선·유출 파선으로 그린다.
- `_Corridor.ts` — 저장 코리도 봉투에 `planCurves` 포함, 형식 버전 1→2.
  안 담으면 저장본으로 복원한 코리도에서 커브가 통째로 사라진다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 09:42:35 +09:00
eomsangdonandClaude Opus 5 f6296fa7c5 feat(B05·B06): 구조물 3D 투영 표기 · 직교 카메라 · 조정창 템플릿 일원화
3D 구조물과 성토면의 관계를 "잘라내기"에서 "투영 표기"로 바꾸고, 세월교·BOX암거
조정창을 기슭막이 템플릿으로 통일했다.

B05 코리도
- 구조물 탑뷰 투영 산출(_Corridor_Carve.ts 신규): 구조물 솔리드 링 사이 실좌표
  사각형 + 변형 성토면 영역. 노선 파라미터가 아니라 행 횡단선과 실좌표로 교차시켜
  곡선 구간·날개벽 벌어짐이 그대로 잡힌다.
- 사각형 합집합 경계(_Corridor_Union.ts 신규): 변을 교점에서 토막 내고 내부·공유
  토막을 버려 최외곽 윤곽만 남긴다(측정 133 -> 13 루프).
- 표기 모드(CARVE_APPLY=false): 서피스를 자르지 않고 ① 성토면 위 절단 투영선
  ② 원지반 최고 표고 위 Z평면에 구조물 윤곽(노랑)과 유입·유출 성토부 윤곽
  (하늘·주황)을 따로 그린다. 구조물 커브는 성토면 없다고 보고, 성토부 커브는
  구조물 없다고 보고 만든다.
- 구조물 실루엣 공용화(_Corridor_Station_Structure.ts 신규): 기슭막이·BOX암거·
  세월교 실루엣을 한 자료형으로. 성토면 강제 변형은 스위치로 끄고
  (STRUCTURE_SILHOUETTE_OVERRIDE), 노견 확장만 상시 적용(shoulderSpans).
- 평면 영역 분리(_Corridor_Region.ts), 절단기 일반화(clipGeometry가 영역 배열·
  전체 정점 속성 보간 — 리본 UV 유지). 지형은 코리도 스트립만 도려낸다.
- BOX암거 3D를 측점 프레임 직선 압출로(노선 추종 금지), 날개벽 계산 공용화
  (_Corridor_Structures_Wing.ts 신규) 후 세월교에도 날개벽 4매 추가.
- 세월교 보어를 관 련수만큼 뚫고, 보어 밴드를 단면 표고로 클램프해 구멍 찌그러짐
  제거. 날개벽 뿌리를 벽 외측면 모서리로 교정.
- 직교 카메라(_Viewer_Camera.ts 신규) — 원근 왜곡 없이 탑뷰 판독. 커서 피벗 줌이
  직교에서 camera.zoom을 함께 조인다.

B06 횡단
- 조정창 공용 부품(_Cross_Panel_Base.ts 신규): 머리줄·2행 항목·D-pad·키보드
  방향키. 세월교·BOX 조정창을 같은 템플릿으로 옮기고 십자 세트를 창 맨 아래로.
- 세월교 조정창에 날개벽 항목 추가(설치·짧은쪽 높이·길이·각도) — 정본
  pipe_points 되쓰기, 바닥판 연장은 길이×cos각으로 즉시 재계산.
- 세월교 좌우 이동을 집수정 규칙으로: 노견 수평 확장 + 상하 이동분만 성토선.

BUILD_VERSION 19 -> 31(저장 코리도 캐시 무효화). typecheck·prettier 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 20:03:42 +09:00
eomsangdonandClaude Opus 5 07fb2ccf46 fix(B06): BOX암거·세월교를 소유 측점 횡단도 한 장에만 그림
attach_culvert_sets()가 도로 방향 폭(span_m)의 절반을 reach로 잡아 소유 측점
전후 측점에도 같은 스펙을 붙였다. BOX암거는 폭 2.4m라 0.92m 떨어진 옆 측점까지
걸려 횡단도가 한 벌 더 그려졌고, 같은 값을 읽는 3D도 박스 솔리드를 어긋난 채
두 벌 만들었다.

구조물 종류별 연동 표(_SPAN_LINKED_TYPES)를 두고 reach를 분기한다. 지금은 빈
집합이라 세월교·BOX암거 모두 소유 측점 한 곳에만 선다. 3D 스윕 길이는 소유
측점이 span_m으로 직접 내므로 줄지 않는다.

기슭막이 연동은 프론트 culvertOwnerFor 별도 경로라 그대로 살아 있고, 집수정은
이미 링크 카드에서 빠져 있다.

검증(프로젝트 c1bb453f route 85): pytest 208 passed. 횡단도 200.0m 카드에서
box-barrel 사라지고 200.92m에만 남음. 3D 솔리드 42 -> 32, 200.0m 10 -> 0,
200.92m 10 유지, span_m 2.4 불변.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 17:41:40 +09:00
eomsangdonandClaude Opus 5 6e87dd6cdf fix(B05): BOX암거 날개벽을 구체 모서리에 붙이고 에이프런을 평면 사다리꼴로
날개벽 시작점을 측점 중앙 프레임으로 잡아 곡선 구간에서 구체 끝과 0.15m 어긋났다.
그 모서리 링의 프레임으로 잡아 정확히 붙인다.

또 에이프런이 평면에서 직사각형이라 각도만큼 벌어진 날개벽 발치가 바닥 밖으로
나갔다. 날개벽 선을 따라 안쪽 변이 물러나는 **사다리꼴**로 바꿔 발치를 받는다
(2026-08-25 사용자 지적).

검증(10+0.9): 날개벽 4매 모두 구체 모서리와 거리 0.000m,
에이프런 링별 안쪽 변 [4.158, 2.744, 2.744, 4.158] — 바깥 링에서 폭 0으로 닫힌다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 15:41:31 +09:00
eomsangdonandClaude Opus 5 a87182496e feat(B06·B05): BOX암거 조정창 · 구체 기울기 · 3D 벽 구간 정리
조정창에서 좌·우 끝을 따로 잡는다 — ◀▶는 구체 길이, ▲▼는 그 끝의 구체 표고를
0.1m씩 움직인다. 좌·우 표고가 달라지면 구체가 기울고, 날개벽 구간 바닥(에이프런)은
각 끝 표고에서 수평을 지킨다(2026-08-25 사용자).

- `computeBoxLayout`이 좌·우를 따로 푼다: 끝 표고·길이·성토선·에이프런
- 성토선은 그쪽 표고 기준으로 물매 1:1.2를 지키므로 표고를 내리면 구체가 길어진다
- 조정창 `_Cross_Box_Panel.ts` + 제어 `createBoxControls` + `design.box_adjust` 저장
  (세션 → 캐시 → 확정 payload, 세월교와 같은 체계)
- 3D: 구체 밖(날개벽 구간)에 서 있던 벽을 없앴다 — 천장 없는 통로가 생기던 자리는
  날개벽 몫이다. 이제 상판·구체 저판·측벽 2매·에이프런 2매 + 날개벽 4매로 나뉜다
- 카드 렌더러의 구체 배선(선택 토글·강조·조정창)을 `_Cross_View_Bodies.ts`로 분리,
  연동 플래그 세션은 `_Page_Link_Session.ts`로 분리(700줄 제한)

검증(10+0.9): 구체 5.34m·수평 → ◀ 1회 5.44m → ▼ 2회 표고 −0.2m·물매 1:28.4,
에이프런 두 장 모두 수평 유지, ↺ 원복. 3D 솔리드 10개(측벽 링 0.2m).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 15:03:53 +09:00
eomsangdonandClaude Opus 5 2fe8f617da fix(B06): BOX암거 성토선을 박스 최상단 모서리에서 끝냄
모서리 밖은 구체 개구부·날개벽이라 성토가 아니다(2026-08-25 사용자). 원지반까지
잇던 구간을 지운다 — 성토선은 노견 → (수평 연장) → 박스 최상단까지만이다.

검증(10+0.9): 좌 [(2, 535.821) → (2.744, 535.201)],
우 [(−2, 535.701) → 수평 → (−2.744, 535.201)] — 두 선 모두 상단 표고에서 종료.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 12:55:00 +09:00
eomsangdonandClaude Opus 5 55e97b8925 fix(B06): BOX암거 성토선 추가 — 박스 최상단을 지나고 노견은 수평 연장
박스 위 성토선이 빠져 있었다. 물매 1:1.2를 고정하고 성토선이 **박스 최상단
모서리**를 지나게 하면, 박스를 길게 잡을수록 노견이 저절로 수평 연장되고 각도는
그대로다(기슭막이 "벽이 밖으로 나간 만큼 노폭 연장"과 같은 규칙, 2026-08-25 사용자).

- 구체 길이 = 노폭 + 2 × (노면 − 박스 상단) × 1.2. 노면이 크라운이라 좌·우 필요량이
  다르므로 큰 쪽에 맞춰 대칭으로 잡고, 남는 쪽은 노견을 수평 연장한다
- 성토선 = 노견 → (수평 연장) → 박스 최상단 모서리 → 1:1.2로 원지반까지
- 노견 밖 설계선은 이 성토선이 대신하므로 다시 트림한다

검증(10+0.9): 구체 ±2.744m, 저판 8.32m, 좌 성토선 물매 1.200·1.200,
우 성토선 수평 0.144m 뒤 1.200·1.200.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 12:52:40 +09:00
eomsangdonandClaude Opus 5 d4c8de738a feat(B05·B06): BOX암거 횡단도 · 3D 중공 셸·날개벽·관통 보어
BOX암거를 세월교와 같은 계류 방향 절단면으로 그리고, 3D는 속이 빈 서피스 셸로
만든다. 관통 컷·중공 튜브는 배수관 세트와 세월교에도 함께 적용한다.

B06 횡단도
- `_box_set()` — 내공 폭·높이(B05 옵션), 부재 두께 세월교 승계(측벽 0.2·상하판 0.3),
  복토 0.5m(별표2 교차 참조), 날개벽 투영 저판 연장
- 상판 윗면 = 노면 − 복토, 구체는 수평 설치(교본 3장). 계류 하상과의 고저차는 툴팁 표기
- 구체가 노면 아래 묻히므로 계획선은 자르지 않는다(세월교와 다른 점)

3D
- 로프트가 **링별 폴리곤**을 받는다 — 구조물을 위·아래 조각으로 갈라 링마다 틈을
  벌려 빈 공간을 만든다. 틈 0이면 속 찬 단면 그대로라 토폴로지가 유지된다
- BOX = 내공 구간만 틈을 벌려 측벽이 저절로 생기는 셸 + 날개벽 4매(날개 축 프레임)
- 관통 보어 = 링 y에서 틈 높이 2·√(r²−(y−y₀)²) → 배관 외측 기준 원형 구멍.
  기슭막이·집수정·세월교 측벽에 적용
- 배관은 중공 튜브(바깥·안쪽 원통 + 양 끝 고리)로 내부 유로를 보인다

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 12:45:32 +09:00
eomsangdonandClaude Opus 5 98380056cc fix(B06): 세월교 관 위 성토 채움 삭제
채움 색이 --color-chart-0(파랑 rgb 91,141,239)이라 관 선 색(rgb 79,142,247)과
겹쳐 관 일부처럼 읽혔다. 사용자 확정에 따라 면 자체를 지운다 — 배수관 세트와
같이 관 위는 비워 둔다.

- FordLayout.fill·FordSideLayout.roadFace와 전용 보조 함수 제거
- .b06-chart__ford-fill 스타일 삭제

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 12:12:55 +09:00
eomsangdonandClaude Opus 5 81bb505cc4 feat(B05·B06): 세월교 횡단 구체·조정창·3D 예상형상
B05 세월교 옵션에 BOX암거 날개벽 한 벌(설치·짧은쪽 높이 1m·길이 2m·각도 45°)을
그대로 붙이고, B06 횡단도에 세월교 구체를 그린다. 구체는 양측 ㄴ형 집수정 측벽 +
그 사이를 잇는 바닥판 + 바닥판 상면에 안힌 관 + 관 위 성토(노체) 채움이다.

- 바닥판 편측 연장 = 날개벽 길이 × cos(각도) — 각도는 관축 기준 벌어짐각
- 측벽은 buildBasin 재사용이라 1:0.3 기움·좌우·상하 대각 이동·계류측 성토부선이
  집수정과 같은 규칙으로 따라온다 (기슭막이 다단·재질과는 연계하지 않음)
- 구체는 월류 폭만큼 도로 방향으로 이어져 기준 측점 전후 절반까지 붙는다
- 조정창: 측벽 높이·좌우·상하, 관경·수량(정본 pipe_points 되쓰기).
  높이·좌우·상하는 세션 + design.ford_adjust에 저장
- 3D 예상형상: 구체 부재는 월류 폭 구간 스윕, 관은 련수만큼 폭 안 등간격
- 부재 두께: 바닥판 0.3m(교본 물넘이 물받이 최소 30cm), 측벽 0.2m(집수정 승계)

700줄 제한으로 카드 렌더러·측점 제어기·페이지에서 배선을 분리했다
(_Cross_View_Ford, _Page_Ford_Controls, _Page_Patches, Culvert_Const 구간값 헬퍼).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 12:05:42 +09:00
eomsangdonandClaude Opus 5 0e2309f5ce fix(B05): 지운 구조물 부활 차단 · 임시저장이 캐시 수정분을 저장하도록
사용자 확정 모델: 초기 계산값은 **원복용으로 그대로 두고**, 사용자가 제어한 수정
1세트가 최종본이다. 여러 세트는 두지 않는다. 두 곳이 이 모델을 어기고 있었다.

① 지운 구조물이 되살아난다 — B05는 그려질 때마다 종단 정본의 비정규 측점을 모아
   `/structures/migrate`를 부른다. 서버의 "멱등" 기준이 **지금 그 자리에 구조물이
   있는가**여서, 사용자가 지우면 자리가 비고 다음 진입에서 같은 구조물이 다시
   생성됐다(진행단계 오버레이로 오가면 매번). 옮긴 자리를 `structures.json`의
   `migrated_legacy`에 **이력으로** 남기고, 이력에 있으면 구조물이 없어도 다시 만들지
   않는다. 원천(비정규 측점)은 원복용으로 손대지 않는다. 이력은 일반 저장 경로에서도
   보존한다 — 사라지면 삭제분이 부활한다.

② 임시저장이 캐시 수정분을 버린다 — B05 [임시저장]이 `cross_patches`를 보내지 않고
   `invalidateSectionDetail`로 공유 캐시를 비웠다. B06에서 만져 캐시에 얹힌 구조물
   조정(4축·다단·연동·표시 반폭)이 영구저장소에 못 가고 사라졌다. 계획선·비정규 측점
   저장 **뒤에** 캐시 수정분을 `saveSections`로 남기고, 그 다음에 캐시를 비운다 —
   순서가 뒤바뀌면 재계산이 사용자 수정을 덮는다.

`saveCachedCrossPatches`·`crossPatchesFromCache`는 공유 캐시 모듈에 뒀다 — B05 페이지
파일이 이미 700줄을 넘겨 더 불리지 않기 위함이다(기존 부채).

tsc/ruff/prettier 통과, pytest 200 passed(기존 실패 1건 유지).
신규 검증: tmp/tests/test_b05_structures_migration_history.py 4건.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 19:56:40 +09:00
eomsangdonandClaude Opus 5 38fd7e49e0 fix(B05): 구조물 성토 비탈 Z 반전 — 유출측 실루엣 배열 방향 정규화
사용자 3D 제보: 구조물 자리의 성토가 경사 방향이 뒤집혀 위로 솟는다.

원인은 직전 커밋(b5ceb861)에서 유출측 편거리 정렬을 뺀 것이다. 뒤쪽 코드가 비탈의
도로측 끝점을 **배열 위치**로 집는다 — `slopeRelative`(Corridor_Station)와 코리도
빌더(Corridor_Build)가 `side === "right" ? points.at(-1) : points[0]`로 잡고,
비탈 보간기도 오름차순 배열을 전제한다. 유출이 우측인 측점은 수집 순서(도로 → 바깥)가
편거리 내림차순이라 **바깥 끝을 도로측으로** 잡았고, 그만큼 비탈이 뒤집혀 얹혔다.

정렬로 되돌리면 다단 계단 순서가 다시 깨지므로, 체인은 그대로 두고 **배열 방향만**
오름차순으로 뒤집는다(첫 점이 마지막 점보다 바깥이면 reverse). 점 순서(성토선 >
본 기슭막이 > 추가 성토선 > 추가 기슭막이)는 보존된다.

BUILD_VERSION 18 → 19(저장 코리도 만료).
tsc/prettier 통과, pytest 196 passed(기존 실패 1건 유지).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 19:42:07 +09:00
eomsangdonandClaude Opus 5 b5ceb8613a fix(B05·B06): 기슭막이 조작의 3D 즉시 반영 · 성토 비탈 실루엣 순서 복구
사용자 보고: 기슭막이 위치(본·연동)를 바꿔도, 추가(다단) 기슭막이를 세워도 3D가
바뀌지 않는다. 형상은 성토선 > 본 기슭막이 > 추가 성토선 > 추가 기슭막이 순이어야
한다. 원인이 둘이었다.

① 조작값이 캐시에 안 실렸다 — 사용자 확정 흐름은 "영구저장소 → 브라우저 캐시 →
   3D는 캐시로 플롯, 편집하면 캐시를 갱신하고 그 캐시로 다시 플롯"이다. 그런데
   조정창 조작값(4축·다단 단 수·유입 구조물·집수정·연동 플래그)은 sessionStorage에만
   있고 확정·임시저장 때만 design에 실렸다. 이제 편집 즉시 `section.design`(B05·B06이
   공유하는 같은 객체)에 함께 기록한다. 세션은 리로드 복원용 사본으로 남는다.
② 기하 캐시가 낡았다 — `culvertLayoutOf`의 WeakMap이 측점 객체만 키로 써서, 캐시를
   제자리 고치면 옛 기하가 그대로 살아남는다. 입력 요약 해시를 함께 담아 무효화한다.
③ 비탈 실루엣이 순서를 잃었다 — 수집한 점을 편거리로 정렬한 뒤 재추출했다. 기슭막이
   앞면이 거의 수직이라 편거리 정렬은 순서를 보장하지 못하고, 다단 계단은 안팎을 오가
   뒤섞인다. 유출측은 수집 순서를 그대로 잇고, 추가 성토선과 추가 기슭막이를 번갈아
   밀어 계단 순서를 맞춘다. 유입측(집수정·절토)은 범위 밖이라 종전 정렬 유지.
④ 성토 조각 해상도 20 → 48열 — 호길이 균등 재추출이 수직면을 뭉갠다. 열을 꼭짓점에
   맞춰 배분하면 측점마다 열 수가 달라 리본이 꼬이므로, 파라미터화는 그대로 두고
   해상도로 해결했다. 절토는 20 유지(다단이 붙지 않는다).

성토 물매 불변: 이번 수정은 trimSlope·outletFill 점을 만들지 않는다 — 잇는 순서와
재추출 열 수만 바꿨고, 물매 산출 경로(layout.fillSlope.ratio)는 손대지 않았다.

BUILD_VERSION 17 → 18(저장 코리도 만료).
tsc/prettier 통과, pytest 196 passed(기존 실패 1건 유지).
작업이력·자체검증 기록: docs/raw/PLAN.md §4-10.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 19:37:14 +09:00
eomsangdonandClaude Opus 5 cd8d14f105 feat(B05·B06): 기슭막이 구간값 조정창 · 연동 기슭막이 옵션 · 가림 구간 선 정리
기슭막이 범위(길이·기준측점 전/후)를 B06 횡단도 조정창에서 지정하게 하고, 그
범위가 덮는 옆 측점의 기슭막이를 "연동" 파생물로 다루도록 체계를 세웠다.
값의 원천은 배수관 옵션(pipe_points) 하나다 — 같은 숫자를 B06 정본에 따로 담으면
B05 배수관 카드와 갈려 어느 쪽이 참인지 알 수 없다.

① 집수정 전/후 필드 신설 — inlet_basin_before_m·after_m(기본 각 1m), 길이 2m 유지.
   종방향 구간 계산을 revetSpanOfSpec·basinSpanOfSpec 한 곳으로 모아 2D 링크 판정과
   3D 스윕이 같은 값을 쓰게 했다.
② B06 조정창에 길이·전·후 행 — 기슭막이(유입·유출)·집수정 모두. 캐시를 고쳐 즉시
   보여주고 저장은 조작이 멎으면 한 번만 나간다(세부유역 재계산이 매번 돌지 않게).
   길이를 바꾸면 늘어난 몫만 지금 비율대로 나눠 담는다 — 총길이에서 비율로 다시
   계산하면 0.1m 반올림이 쌓여 5.0/5.0이 5.6/5.4로 어긋난다.
③ 링크 카드 선택 허용 — "소유 측점 통째 복사"에서 "위치 4축만 물려받고 원지반
   접합은 이 측점 지형으로 재계산"으로 바꿨다. 구조물 형식은 언제나 소유 측점 값이다.
   손대기 전에도 어긋나지 않게 소유 측점이 실제로 적용한 4축(revetShift)을 명시값으로
   물려준다.
④ 연동(측점별)·경사(전체 공통) 토글 — 연동 조작은 소유 측점 키에 실리고 그 연장이
   덮는 측점을 함께 다시 그린다. 경사는 3D 전용 스위치다(끄면 스윕 프레임 dz=0).
   횡단도까지 -dz로 밀면 노견에서 출발하는 성토선까지 내려가 노견과 벌어진다.
⑤ 가림 구간 선 정리 — 유입부 접속선과 유출부 접지 후 절토선을 2D·3D 모두에서
   빼되 기하는 남긴다. 면적·수량 계산은 건드리지 않았다(전면 개편 대상).
⑥ 집수정은 소유 측점 횡단도 하나에만 — 링크 카드에서 집수정·계류측 다단을 뺀다.
⑦ 3D 구간 겹침 정리 — 측점 간격이 구조물 연장보다 좁으면 두 구간 제어점이 번갈아
   서서 짧은 쪽(집수정 2m)이 잘려 보였다. 두 소유 측점의 중간에서 끊는다.
⑧ 조정창 정리 — 십자·9키를 맨 아래로, 창을 위쪽 기준 오버레이로(낮은 횡단도에서
   제목이 잘리던 문제), 연동·경사를 1행 토글 버튼으로, 스크롤 자리 유지.

파일 분리: B06_Section_UI_Cross_View_Structure.ts(조정창 배선),
B06_Section_Api_Culvert_Options.ts(구간값 저장) — 700줄 제한.
BUILD_VERSION 14 → 17(저장 코리도 만료).
tsc/ruff/prettier 통과, pytest 196 passed(기존 실패 1건 유지).
작업이력·자체검증 기록: docs/raw/PLAN.md §4-9.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 19:26:35 +09:00
eomsangdonandClaude Opus 5 83eb58a251 feat(B05·B06): 배수관 측점 정본화 · 코리도 단차 제거 · 인접 측점 기슭막이 링크
3D 예상형상은 종단·횡단 확정 뒤의 최종 산출물이고 3D 쪽 편집 경로는 없다
(2026-08-24 사용자 확정). 그런데 구조물(비정규) 측점은 횡단 정본 자체가 없어
조회할 때마다 프리뷰 기본값이 재계산됐고, 조정창 조작값은 세션에서 사라졌다.
정본 경로를 열고, 그 위에서 코리도 단차를 걷어냈다.

① 구조물 측점 정본화 — 확정·임시저장이 종단 정본 stations 중 DB 행이 없는
   측점을 대상에 넣어 upsert. cross_sections 19 → 23행.
② 조정창 조작값 정본화 — 기슭막이 4축(x·d·h·m)·다단 단 수를 design.revet_adjust
   / extra_wall_counts로 저장하고, 3D culvertLayoutOf가 그 값을 기하 입력으로 쓴다.
   카드 우선순위는 세션 → 정본 → 자동.
③ 노폭 연장의 노견 편입 — PIECE_COLS.shoulder 2→3으로 원 노견 끝 꺾임을 남기고,
   조기 return을 없애 확폭이 구조물 구간 내내 유지되게 했다.
④ 종단 기울기 반영 — 구조물 구간 복사 단면에 계획고 차이를 전량 얹는다.
   노견 표고 단차 0.49~0.61m 제거.
⑤ 접속 테이퍼 — 구간 경계를 제어점으로 세워 "복사 vs 보간" 두 규칙을 하나로
   통합. 노폭 3.0m·성토비탈 8.1m 단차 제거. 접속 길이 = 인접 측점까지.
   제어점 생성은 B05_Profile_UI_Corridor_Frames.ts로 분리(Build 699 → 635줄).
⑥ 인접 측점 링크 — 기슭막이 연장(기본 10m)이 덮는 옆 측점 횡단도에도 소유 측점
   단면을 계획고 차이만 얹어 그린다. 요소별 연장 판정(관·집수정 제외), 표시 전용.

BUILD_VERSION 11 → 14 (저장 코리도 만료).
tsc/ruff/prettier 통과, pytest 192 passed (기존 실패 1건 유지).
작업이력·자체검증 기록: docs/raw/PLAN.md §4-8.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 17:11:21 +09:00
eomsangdonandClaude Opus 5 22d4df5aff feat(B05): 3D 예상형상에 배수관 세트 구조물 반영
B06 횡단(computeCulvertLayout)을 그대로 재사용해 3D 코리도에 기슭막이·집수정·
배관을 세우고, 그 구간 성토/절토 단면을 횡단도와 같은 형상으로 다시 그린다.

구조물 솔리드(_Corridor_Structures.ts 신규)
- 기슭막이: 단면 폴리곤을 노선 따라 1m 간격 로프트 스윕(직선 압출 아님)
- 집수정: 부재 외곽 직육면체, 연장 basin_length_m(기본 2m) 전후 균등
- 배관: 관 하단선 축 원통(관경 지름)
- 스윕 프레임에 계획고 차(dz)를 실어 종단 경사 반영
- flat 법선 + EdgesGeometry 모서리 검은선(성토부·노폭 리본과 같은 규칙)

단면 재구성(_Corridor_Station.ts)
- 구조물 측 비탈 = 노견 → (노폭 연장) → 구조물 상단 → 전면 → 벽 하단 성토부선
  → 다단 기슭막이 → 지반/절토선 끝 한 줄(PIECE_COLS cut·fill 9 -> 20)
- 성토로 늘어난 노폭은 비탈이 아니라 노견 리본을 넓힌다
- 집수정 계류측 cutLine까지 이어 원지반을 그만큼 걷어낸다

구간 처리(_Corridor_Build.ts)
- 구조물 점유 구간(기준측점 전/후)이 다음 측점을 넘어가도 같은 단면 유지
- 그 구간은 지반 트림 생략, 비탈 앵커를 노견 조각 바깥 끝으로 통일

길이·전후 입력
- 레지스트리 pipe 옵션 추가: inlet/outlet_revet_before_m·after_m(5/5),
  inlet_basin_length_m(2)
- B05 배수관 서브폼에 기준측점 전/후 칸(전+후=길이 연동)·집수정 길이 칸
- _side_spec이 전/후·집수정 길이를 CulvertSideSpec으로 전달

비정규 측점 프레임 정정(_Page_Helpers.ts)
- left_xy 선형보간(단위길이 깨짐·방향이 현 쪽으로 누움) -> 노선 폴리라인 접선에서
  직접 산출(left = (-ty, tx)), 폴백은 각도 보간

BUILD_VERSION 10 — 저장본 자동 만료

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 21:46:48 +09:00
eomsangdonandClaude Fable 5 5371534fc3 feat(B06): 기슭막이 높이·자리 체계 개편 + 조정창 방향키 조작
- 조정창 십자 키패드 키보드 방향키 조작(집수정 9키는 십자 축만)
- 배관 기슭막이 높이 = 순수 높이(바닥~상단), 하한·기본 = 관경+1.0m (고정 2.0m 폐기)
- 매몰 시 전면 발끝 지반 추적 바닥 심화 삭제 — 바닥 = invert-0.5 고정
- 상하(d) 0점 = 성토선 0 지점(벽 상단=노견), 기본 자리 = 성토사면 경사길이 4m 지점
  (d=null 자동, 저장·표시·정수맞춤 pinned 판정 연동, 구세션 d=0 호환)
- 유입 접속 절토선: 지반 교차 없으면 1m 공간 확보에서 끝
- 자동 집수정 기본 형상 L형 -> I형 (선택지 밖 구조물 그려지던 불일치)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 20:34:30 +09:00
eomsangdon 7217747e81 auto: 2026-08-23 19:34 (ESD_LAPTOP) 2026-08-23 19:34:26 +09:00
eomsangdonandClaude Opus 5 eb41202bf4 fix(B06): 교차점 자동 줌아웃이 5m 사면 규칙에 잘리던 문제
자동 줌아웃 판정이 배수관용 slopeToeOffset(성토사면 5m에서 컷오프)을 써서, 사면이
5m를 넘는 측점은 필요 폭을 과소 산정했고 교차점이 화면 밖에 남았다(2026-08-23
사용자 보고).

- _UI_Cross_Fit 재작성: 설계선(design_line)과 지반선의 **실제 교차점**을 0.1m
  간격으로 훑어 찾는다(노면·노견·측구 구간은 건너뜀). 설계선이 만나기 전에 끝나면
  끝단 기울기 차로 외삽하고 1m 올림.
- 카드 자동 줌아웃(effectiveHalfWidth)이 이 값을 쓴다. 보유 샘플 밖으로는 넓히지
  않는다(지반이 없어 빈 화면이 될 뿐).
- [적용]은 전 측점 중 필요한 최대 폭까지 함께 넓힌다 — 20m를 넘으면 그 값으로
  재생성해 각 카드가 자동 줌아웃할 지반을 확보한다.

자체검증: node tmp/tests/test_toe_extrapolate.mjs (사면 18m 교차점을 5m 컷오프
없이 탐색, 설계선이 15m에서 끊겨도 외삽으로 같은 자리), tsc --noEmit 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:54:38 +09:00
eomsangdonandClaude Opus 5 91f843b5bb fix(B06): 표고(Y) 눈금 최소 단위 1m
확대하면 0.5m·0.2m 눈금까지 내려가 도면에서 읽을 일 없는 값이 표기됐다
(2026-08-23 사용자 지시). 횡단·종단 모두 표고 눈금 간격을 1m로 하한을 둔다
— 라벨은 항상 정수. 편거리(X) 눈금은 종전대로.

자체검증: node tmp/tests/test_cross_y_ticks.mjs (모든 눈금 정수·간격 1m 이상),
test_cross_axes_zoom.mjs 재실행, tsc --noEmit 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:50:19 +09:00
eomsangdonandClaude Opus 5 8f9e628b0b fix(B06): 횡단 보기 설정 한 줄 정렬
ui-field가 세로 배치(라벨·입력·오류 슬롯)라 [적용]이 오류 슬롯 높이만큼 내려가
수평이 안 맞았다. 이 줄에서만 필드를 가로로 눕히고(라벨-입력-버튼) 오류 슬롯을
접어 한 줄에 정렬한다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:48:56 +09:00
eomsangdonandClaude Opus 5 dff1e3aff9 feat(B06): 횡단 보기 반폭을 별도 컨테이너로 분리 + 사이드 양식 B05 정렬
- 「횡단 보기 설정」 컨테이너 신설: 반폭 입력 + [적용] 버튼 한 줄. 표준 횡단면
  설정의 [전체 측점 반영]에 물려 있던 반폭 적용을 떼어냈다 — 보유 샘플(20m) 안이면
  전 측점 설계 재계산 없이 즉시 반영된다.
- 표준 횡단면 설정 컨테이너는 기본 접힘.
- 사이드 컨테이너 양식(여백·글자 크기·색)을 B05 .b05-route__panel-section 값으로
  맞춤. 접힘 토글·외곽선은 이미 공용(ui-collapsible / ui-sidebar-section)이었다.
  표준단면 「변수 위치 안내」 모식도 스타일은 현행 유지.
- 표준패널의 미사용 extraControl 인자 제거.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:47:36 +09:00
eomsangdonandClaude Opus 5 bab1f6b2c2 fix(B06): 재생성이 구조물(비정규) 측점을 지우던 문제
_regeneration_options가 extra_stations를 넘기지 않아, 반폭 재생성 한 번에
구조물 측점 횡단도가 통째로 사라졌다(2026-08-23 사용자 보고). 옵션 스냅샷
(data.options.extra_stations)에서 목록을 읽어 재생성 옵션에 실어 준다.

자체검증: ./venv/Scripts/python.exe -m pytest tmp/tests/test_regeneration_extra_stations.py -q (2 passed)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:43:32 +09:00
eomsangdonandClaude Opus 5 5ac61cb4cc fix(B06): ⤢(오토핏) 기본값을 전역 횡단 반폭 보기값으로
⤢가 항상 교차점 맞춤 폭으로 가서 전역 보기값보다 좁아지기도 했다. 이제 초기화는
전역 보기값이 기본이고, 그 폭에서 절·성토선과 원지반 교차점이 안 보이는 측점만
교차점이 보이는 폭(그 측점의 기본값)으로 되돌린다(2026-08-23 사용자 지시).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:34:50 +09:00
eomsangdonandClaude Opus 5 b344ffe60e fix(B06): 원배율에서도 캐시 범위 팬 허용 + 면적표 좌측 상단 이동
- 팬 한계를 배율과 무관하게 그려진 범위(캐시 보유분)까지 연다. 확대해야만 움직여
  "팬이 안 된다"고 보고됐다(2026-08-23). 캐시가 표시 폭과 같으면 종전처럼 이동 0.
- 절·성토 면적표를 그래프 가운데 상단 → **좌측 상단**(축선 안쪽 58px)으로. 세로
  자리는 그대로.

화면 검증(공용 브라우저): 원배율 가운데 드래그로 translate 0→100.3px, X 눈금
-10~10 → -5~15로 캐시 구간 노출. 면적표 좌측 오프셋 58px·상단 8px 확인.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:32:06 +09:00
eomsangdonandClaude Opus 5 082e679672 fix(B06): + 버튼이 배율 확대를 못 하던 문제
원배율에서 +를 표시 반폭 좁히기로 돌려놨더니 배율이 1에서 올라가지 않았고,
가운데 버튼 팬은 배율>1에서만 열리므로 팬도 함께 막혔다(2026-08-23 사용자 보고).
+는 언제나 배율 확대, −만 원배율에서 표시 반폭 +1m로 되돌린다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:26:24 +09:00
eomsangdonandClaude Opus 5 ea29cc2e59 feat(B06): 확대 상태 팬으로 캐시 보유 범위까지 열람
- 도형(지반선·면적 밴드·설계선·암 경계선)을 표시 반폭으로 자르지 않고 **캐시 보유
  전 구간**으로 그린다. 표시 반폭 밖은 기존 clip이 가리므로 원배율 화면은 그대로다.
- 팬 한계(clampPan)를 그려진 범위까지 확장 — 배율 1에서는 종전대로 이동 0으로 묶고,
  확대 상태에서만 캐시 끝까지 가운데 버튼 드래그로 끌어다 볼 수 있다.
- 축 눈금은 팬 상태를 역산해 다시 그리므로(_UI_Cross_Axes) X·Y 값이 따라 움직인다.

자체검증: node tmp/tests/test_cross_pan_bounds.mjs (배율 1 고정, 2배에서 좌우 한계가
캐시 끝과 일치, 범위 밖 이탈 없음, content 없을 때 옛 규칙 유지),
test_cross_axes_zoom.mjs 재실행, tsc --noEmit 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:24:23 +09:00
eomsangdonandClaude Opus 5 0d80d03b96 fix(B06): 횡단 줌·팬에 X·Y 축 눈금 동기화
도형만 transform으로 확대되고 축은 고정이라 확대·이동 후 눈금값이 실제 위치와
어긋났다(2026-08-23 사용자 보고). 축·격자를 별도 레이어(_UI_Cross_Axes)로 옮기고
줌·팬 상태가 바뀔 때마다 보이는 범위를 역산해 다시 그린다.

- 눈금 개수·간격도 그때 보이는 범위로 다시 고른다(1·2·5 계열, X 목표 7·Y 목표 10,
  라벨 겹침 하한 X 48px·Y 14px). 확대할수록 촘촘·소수 단위로 자동 전환.
- X 눈금이 7등분 고정(비정수 간격)이던 것도 같은 규칙으로 정리.
- Cross_View는 축 코드가 빠져 622줄.

자체검증: node tmp/tests/test_cross_axes_zoom.mjs (원배율·4배 확대에서 눈금이
플롯 안에 있고, 같은 offset의 도형 자리와 눈금 자리가 일치), tsc --noEmit 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:20:22 +09:00
eomsangdonandClaude Opus 5 f2ad5508f5 feat(B06): 횡단 줌 조작 일원화 + 교차점 맞춤 자동 확대
- 카드 하단 ◀/▶/↺(개별 표시 반폭) 삭제. 조작구는 우측 상단 줌 버튼 하나로.
- 줌 버튼 역할 확장(원배율에서만 반폭 조작):
  − 배율>1이면 축소, 원배율이면 표시 반폭 +1m
  + 배율>1이면 확대, 원배율이면 표시 반폭 −1m(하한 2m)
  ⤢ 배율 원복 + 절·성토 교차점이 다 보이는 폭으로 맞춤
- 교차점 맞춤(_UI_Cross_Fit): 보유 샘플(계산 반폭 20m) 안에서 교차점을 찾고,
  샘플 끝까지 안 만나면 끝단 사면·지반 기울기 차로 만나는 자리를 추세 외삽해
  올림 +1m을 요청 반폭으로 쓴다(상한 60m).
- 요청 반폭 > 보유 샘플이면 그 폭으로 재생성(regenerate) 후 해당 측점만 세션
  반폭으로 넓게 표시. 계산 기본 20m·캐시는 그대로, 확정 시 기존 경로대로
  display_half_width_m에 영구 저장.
- 재생성 로직을 _UI_Page_Common.createSampleWidener로 분리(700줄 제한),
  [전체 측점 반영]도 같은 경로 사용. 연타 중복 요청 차단.

자체검증: node tmp/tests/test_toe_extrapolate.mjs (외삽 좌/우·발산 지형·+1m 올림),
tsc --noEmit 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 18:16:31 +09:00
eomsangdonandClaude Opus 5 ec514a4560 fix(B06): 횡단 Y축 눈금이 X축 아래로 삐져나오던 문제
눈금 범위를 elevationMid 중심(±displaySpan/2)으로 잡아, displayMax에 들어간
면적표 여유(AREA_OVERLAY_HEADROOM_PX/2)만큼 아래로 밀려 최하단 격자선·라벨이
X축 라벨 줄 아래에 그려졌다. 범위를 실제 표시 상·하단(displayMax 기준)에서
역산해 플롯 안에만 눈금이 오게 한다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 17:53:52 +09:00
eomsangdonandClaude Opus 5 c10fb3400e fix(B06): 횡단면도 Y축 눈금도 정수·1·2·5 계열로 정의
- 5등분 고정(소수 표기) → 종단면도와 같은 niceTickStep 규칙 적용.
- niceTickStep을 _UI_Section_Common으로 옮겨 종·횡단이 공유(정의 한 곳).
- 횡단은 카드 높이가 낮아 라벨 간격 하한 14px(종단 16px)로 개수 상한 산정.
- 횡단 표고 여유는 기존 crossPlotMetrics의 8% 패딩 그대로.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 17:51:38 +09:00
eomsangdonandClaude Opus 5 2cea6203be fix(B06): 종단 Y축 눈금 정수화 + 최대·최소 표고 여유
- 0.25 비율 고정 5눈금(소수 표기) → 1·2·5×10^n 중 10칸에 가장 가까운
  간격으로 자동 선택. 눈금값이 딱 떨어져 표고를 읽을 수 있다.
- 라벨 겹침 방지로 눈금 간격 16px 하한(plotHeight/16 개수 상한).
- 자동 스케일(B05)은 표고 범위에 위아래 10%씩 여유 — 최고·최저점이
  축선에 붙지 않는다. 공통 Y스케일(B06 yScaleOptions)은 불변.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 17:49:28 +09:00
eomsangdonandClaude Fable 5 76df1e9335 fix(B05): 종단 계획고 변경을 횡단 설계에 자동 반영 - B05 진입 시에도 재계산
2026-08-23 사용자 보고: 종단 그래프의 계획고 변화가 B06 횡단도에 반영 안 됨.

원인: 횡단 설계는 계산 당시 계획고(design.design_elevation_m) 기준으로 설계선
좌표를 굳혀 둔다. 계획선이 뒤에 바뀌면(사용자 편집·확정, 배수 최소고 같은
백엔드 규칙 도입) 설계선은 옛 자리에 남는데, 화면의 계획고 십자선과 3D
예상형상은 최신 계획선을 쓴다 - 두 기준이 어긋난다. 실측으로 한 노선에서
최대 2.21m 어긋남 확인. 지금까지 이 보정은 B06 진입 때만 돌아서, B05의 횡단
기준 유토곡선과 3D는 옛 설계선을 계속 썼다.

- staleDesignChainages() 신설(B06_Section_UI_Section_Common) - 계획선 보간값과
  계산 기준의 차이로 재계산 대상을 판정하는 B05·B06 공용 규칙.
- B05 Profile_Panel: 진입 렌더에서 어긋남이 있으면 프리뷰 1회로 맞춘다.
- B06 Page: 같은 공용 규칙을 쓰도록 통일(옛 암 2단계 필드 누락 조건은 유지).

검증: tsc 통과 · pytest 191 passed(신규 stale 판정 6건) · 공용 브라우저 실측 -
계획고·지반고 배치 대조(전 측점 일치, 렌더 역산 RMS 0.004~0.03m), 측점 중심
좌표가 노선 폴리라인과 거리 0, 인위 stale 1건을 B05 진입으로 자동 복구(stale
1 to 0, 계획고 540.895 복원).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 17:40:48 +09:00
eomsangdonandClaude Fable 5 d8080109c1 feat(B05): 쉬프트 재정의(힌지 승격) + 최소고 판정점을 제어점으로
2026-08-23 사용자 개념 확정 반영.

- 틸트는 그 지점을 라운드로 주변 직선과 잇는 조작이고, 측점·횡단배수 지점의
  수직선에는 라운드 중심점이 놓인다. 따라서 최소고 판정도 제어점 z 기준이어야
  한다(controlElevationAt) - 곡선 샘플 계획고로 재던 탓에 배수 지점 옆을
  틸팅해 라운드 형상만 바뀌어도 락이 걸렸다.
- 쉬프트 재정의(shiftMovingPoints): 구간 끝이 사용자 틸팅점이면 그 점이 직접
  움직이고, 고정점(BP·EP·횡단배수 앵커)이면 움직이지 않는다. 대신 구간 안쪽
  미틸트 측점의 외곽 2개를 힌지로 승격해 라운드를 만들고 그 사이 직선을
  평행이동한다. 힌지 둘을 못 만드는 구간(안쪽 측점 2개 미만)은 쉬프트 대상이
  아니므로 ⬆⬇ 버튼을 만들지 않는다(canShift).
- shiftSegment 되먹임 보정 - 라운드 중앙종거가 낀 자리에서도 화면 계획고가
  정확히 1스텝 움직인다.

검증: tsc 통과 · pytest 185 passed(힌지 규칙 4건 신규) · 공용 브라우저 실측 -
구간 0~84 ⬆에서 힌지(20·80)만 이동하고 BP·앵커 오프셋 미생성, 두 힌지 계획고
정확히 +0.1000m(구배 보존), 앵커 이웃 80.0m ▼ 차단 해제, 앵커 84.3m ▼ 차단 유지.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 17:01:45 +09:00
eomsangdonandClaude Fable 5 eb716ffbb1 fix(B05): 종단 편집 최소고 가드 개편 - 구간 쉬프트 차단 + 시설별 산식
2026-08-23 사용자 보고: 횡단배수 최소고를 어기고 구간 쉬프트가 되는 경우
있음(가드가 측점 ▼에만, 관경 고정 산식).

- 가드 개편(blocksMinCover): 편집 후보로 정렬을 계산해 시설별 최소고
  (minCoverPoints 원천 - 배수관 관경+토피, BOX암거 구체높이+토피, 세월교
  +물넘이, 물넘이포장 제외) 위반이 새로 생기거나 커지면 차단. 측점 ▲▼와
  구간 ⇧⇩ 모두 적용, 이웃 틸트가 종단곡선을 거쳐 배관 계획고를 내리는
  경로까지 커버. 이미 위반이면 악화만 차단(복구 편집 허용). 기존
  blocksPipeLowering(측점 ▼ 전용·관경 1000 고정)은 제거.
- shiftSegment 시딩 수정: 초기 오프셋을 곡선 샘플 계획고(PVI z - 중앙종거)
  대신 변화점 실제 z로 계산 - 첫 이동에서 변화점이 내려앉아 상승 후 하강
  복귀가 비대칭이던 화면 실측 버그 해소.
- MinCover 낡은 주석 정정(구현은 세월교 포함, 물넘이포장만 제외).

검증: tsc 통과 · pytest 182 passed(가드·시딩 신규 8건) · 공용 브라우저
실조작 - 배수관 앵커 구간 ⬇ 즉시 차단(+1.5), BOX암거 구간 차단(+2.5),
⬆/⬇ 대칭 복귀, 검증 상태 전부 원복.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 16:27:41 +09:00
eomsangdonandClaude Fable 5 8393d22c23 feat(B05): 절성토 완전 분리(행 지반 트림) · 그랩 팬 · 측점 그룹 라이브 갱신
2026-08-23 사용자 지시 3건:
- 절성토 완전 분리: 전환 구간을 상대 측점의 폭 0 축퇴점으로 모핑하던 방식
  제거. 비탈을 측구와 같은 도로부 앵커 상대 좌표로 보간하고, 행마다 두 측점
  지반선을 섞은 행 지반선과 직접 교차시켜 종결(trimSlopeToGround). 지반이
  반대편인 행은 조각 드롭 - 절토가 지반으로 내려가거나 서피스끼리 침범하던
  문제 해소. 클리핑 외곽도 행 실점유(비탈-측구-노견)로 일치.
  700줄 제한: 측점 분류·트림 유틸을 Corridor_Station.ts로 분리(Build 494줄).
- 그랩 팬: 가운데 드래그를 커서 아래 지형점이 1:1로 따라오는 팬으로 직접
  구현(B04_PreProcess_UI_Camera). OrbitControls 기본 PAN은 카메라-target
  거리 비례라 커서 피벗 회전·줌 후 극단적으로 느려졌다. B04 뷰어도 공용.
- 측점 그룹 갱신: Profile_Panel이 라이브 alignment.samples 노출, Page의
  측점 바 계획고·코리도 designSamples가 그걸 사용, 종단 편집 디바운스에서
  renderStationLines 동반 호출. BUILD_VERSION 4-5로 저장본 만료.

검증: tsc 통과 · pytest 175 passed(신규 separation 8건) · 사용자 화면 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 16:06:03 +09:00
eomsangdonandClaude Opus 5 0e3bdb145d feat(B05): 측구·절토 종점을 계획선-지반선 교차점으로 계산
측점 사이 어딘가에서 계획선이 지면선을 통과한다 - 그 자리가 절토+측구의 종점이고
거기서부터 성토로 넘어간다(2026-08-23 사용자 확정). 임시로 쓰던 "측점 사이 중간에서
끊기"를 이 계산으로 대체한다.

- buildCrossingFinder(): 종단 계획선 샘플의 (계획고 - 지반고) 부호가 뒤집히는 구간을
  선형보간해 전환 누가거리를 낸다. 구간 안쪽 교차만 인정 - BP·EP는 정의상 지반과
  만나므로 경계의 0을 거르지 않으면 측구·절토가 0.4m 만에 끝난다(실측으로 확인)
- 측구는 그 지점까지 그리고 마감벽으로 닫는다(위치는 계속 노견을 따라간다)
- 절·성토는 전환점에서 폭 0이 되도록 보간 구간을 다시 잡는다. 구간 전체에 걸쳐
  서서히 사라지던 것을 실제 절토가 끝나고 성토가 시작되는 자리에 맞춘다
- 전환점을 못 찾으면(전 구간 절토 또는 전 구간 성토) 종전대로 중간에서 나눈다

측구 형식(일반/L형)은 3D에 이미 반영되고 있음을 확인했다 - 폭은 형식별 필드
(top_width_m / width_m)를 구분해 쓰고, 단면 형상은 엔진이 만든 design_line을
잘라오므로 사다리꼴과 L형이 그대로 올라온다.

BUILD_VERSION 4로 올려 옛 저장본을 만료시킨다.

검증: 실측 측구·절토 유효구간 0.00~2.80m(계산 교차점 2.83m, 0.2m 세분 격자),
이전 0.00~10.00m. pytest 167 passed(전환점 경계·측구 형식 5건 신규), tsc 통과

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 15:38:34 +09:00
eomsangdonandClaude Opus 5 8f6cf5bba6 fix(B05): 도로부(차도·노견·측구) 위치를 한 몸으로 제어 + 빌드 판번호로 캐시 만료
측구가 노견에서 떨어지던 문제
- 측구는 있는 측점과 없는 측점이 갈려 절대 좌표로 따로 보간되고 있었다. 도로 끝은
  다음 측점을 향해 내려가는데 측구만 제자리에 남아, 측점에서 멀어질수록 벌어졌다
  (실측 ch2.0 0.18m / ch5.0 0.46m / ch9.8 0.90m - 측구 폭 0.69m보다 큰 틈)
- 측구 조각을 road edge 기준 상대 좌표로 들고 있다가 프레임의 도로 끝에 얹는다.
  "측점 사이 중간에서 끊기" 규칙은 표시 구간만 자르고 위치는 항상 노견을 따라간다
- 비탈 안쪽 끝도 그 프레임의 도로부 바깥 끝(측구 끝 또는 노견 끝)에 스냅.
  종단 보정분을 얹어 노면과 높이를 맞춘다
- 실측: 차도-노견, 노견-측구, 측구-절토 경계가 전부 0.0000 m.
  측구 단면(폭 0.690 / 깊이 0.300)은 구간 전체에서 유지

저장본 캐시 만료
- 해시가 종횡단 입력만 요약해, 빌드 코드를 고쳐도 입력이 같으면 옛 저장본을 그대로
  다시 썼다(사용자 보고: 수정이 반영 안 되다 갑자기 반영됨). BUILD_VERSION을 해시에
  섞어 기하를 바꾸는 수정마다 저장본이 만료되게 한다

검증: pytest 162 passed, tsc 통과, 화면 실측

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 15:21:12 +09:00
eomsangdonandClaude Opus 5 1f631bc3d4 fix(B05): 코리도 평면 궤적 스플라인화 + 좌표 정밀도 + 편집 되돌리기 곡선반경 보존
평면 궤적 (사용자 제안 채택)
- 노선 정점을 직선으로 잇던 것을 centripetal Catmull-Rom으로 교체.
  실측 노선은 정점 135개·평균 간격 2.61m·꺾임각 최대 42.4°라, 0.1m로 잘게
  쪼개도 정점 이음매의 각짐은 그대로였다
- 스플라인 도입으로 세분은 0.2m로 되돌림 — 데이터·연산 절반

좌표 정밀도 (지그재그의 진짜 원인)
- 코리도 좌표는 EPSG 절대값(183,494 / 489,290)이라 Float32에 담으면 해상도가
  0.14m까지 떨어져, 0.2m 세분 점들이 양자화 계단을 타며 최대 35°짜리 각도
  노이즈가 생겼다. positions를 Float64로 올린다(화면에 올릴 때 원점을 빼며
  Float32로 줄이므로 렌더 비용은 그대로)
- 실측: 중심선 꺾임 평균 4.271° → 0.704°, 5° 초과 838개 → 25개

편집 되돌리기
- resetAll이 자동 계획선이 역산해 저장한 curve_radii까지 비워, 프론트가 기본
  R로 다시 그리며 화면 계획고가 정본과 어긋났다(세월교 지점 0.22m 낮음 →
  최소고 경고 오탐). 사용자 편집 측점만 지우고 곡선반경은 저장분으로 되돌린다

검증: pytest 14/14(스플라인 제어점 통과·오버슈트 없음 3건 신규), tsc 통과,
화면 실측 — 경고 소거, 줌인 시 곡선 매끄러움 확인

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 14:40:56 +09:00
eomsangdonandClaude Opus 5 59ca25b182 fix(B05): 종단 세분 하한이 0.1m 지정을 0.5m로 깎던 문제
steps 계산의 Math.max(0.5, step)가 사용자가 지정한 0.1m 세분을 통째로
무시하고 있었다. 저장본이 702행(=350m/0.5m)으로 남아 있어 확인했다.
하한을 0으로 나누는 것만 막는 값(0.01)으로 낮춘다.

검증: 저장본 3,503행 · 평균 간격 0.100m 확인, 줌인 시 곡선 구간이
매끄럽게 이어짐. 편집 시 최대 프레임 갭 348ms(200ms 초과 1회)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 14:28:45 +09:00
eomsangdonandClaude Opus 5 ea55ad1c73 fix(B05): 세월교 요구 여유 = 배수관 산식 + 물넘이 몫, 물넘이포장은 여유 없음
세월교는 배관을 여러 개 묶어 다리 형태로 만든 것이라 배수관과 같은 산식을 쓰되,
그 위에 물넘이가 얹히므로 0.5m를 더 얹는다(2026-08-23 사용자 확정).
물넘이포장은 도로 위에 그대로 만드는 시설이라 들어 올릴 이유가 없다.

- 세월교 Ø1000 → 1.0 + 0.5(토피) + 0.5(물넘이) = 2.0
- 물넘이포장 → 0.0
- 앞서 쓰던 월류 높이(ford_height_m) 기준은 폐기

검증: 계획선 재생성 실측 — 세월교 지점 계획고-지반고 2.00 일치
(배수관 1.50/1.30, BOX 2.50도 유지). pytest 6/6, tsc 통과

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 14:19:57 +09:00
eomsangdonandClaude Opus 5 e1d0d6dda3 feat(B05): 계획 종단선이 횡단배수 최소고를 자동 확보
계획선의 변화점(PVI)은 배수유역이 확정한 배관 배치 측점이다. 그 자리 계획고를
지반고와 같게 두면 관·구체가 들어갈 자리가 없어, 시설 제원만큼 들어 올린다.

- common_util_drainage_pipes: facility_clearance_m()/pipe_anchor_clearances() 신설
  (정본 산식) — 배수관 관경+토피 0.5, BOX암거 구체높이+토피 0.5,
  물넘이·세월교는 좌측 패널이 설계유량으로 산출한 월류 높이(ford_height_m)
- Engine_Sections: 관 지점에서 시설 여유를 함께 읽어(_load_pipe_anchors) 전달
- Engine_Grade_Profile: 앵커 목표 표고 = 지반고 + 시설 여유
- Profile_MinCover(화면 경고): 세월교·물넘이를 월류 높이 기준으로 추가.
  백엔드가 정본이고 이쪽은 편집 중 즉시 경고용 사본 — 값 일치는 테스트로 잠금

검증: 재생성한 계획선의 배관 측점 실측 — Ø1000 +1.50 / 세월교 +0.30 /
BOX +2.50 / Ø800 +1.30 (전부 요구 여유와 일치), 화면 경고 소거 확인.
pytest 10/10, tsc·ruff 통과

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 14:12:38 +09:00
eomsangdonandClaude Opus 5 af9d2b5530 feat(B05): 측구 끊김 마감·0.1m 종단 세분·지형 near/far 분할·횡단배수 최소고 경고
측구 표현
- 한쪽 측점에만 있으면 측점 사이 중간에서 끊고, 끊긴 자리를 도로 가장자리
  높이까지 벽으로 막는다(공중에서 끊겨 보이던 문제)

품질·성능
- 종단 세분 2m → 0.1m (사용자 지정). 프레임 갭 실측 145ms로 사용 가능
- Corridor_Split(신규): 노선 밴드(코리도 AABB + 80m)로 지형을 1회만 갈라
  편집마다 near만 재트림, far는 재사용. 정점 버퍼 공유라 분할 비용은 인덱스
  복사뿐이며, 코리도가 밴드를 벗어날 때만 다시 가른다

횡단배수 최소 계획고
- Profile_MinCover(신규): 배수관 Ø1000 → 지반고 +1.5m, BOX 2.0×2.0 → +2.5m
  (관경·구체높이 + 토피 0.5m, B06 MIN_PIPE_COVER_M과 동일 값)
- 계획선이 밑돌면 종단 표시줄 경고 + 측점별 부족량 툴팁. 세월교·물넘이는 제외
- 자동 계획선 생성 시 제약 반영은 후속(선형 재구성 규칙 협의 필요)

검증: tsc·pytest 9/9, 화면 실측(경고 문구·측구 마감·클리핑 삼각형 수)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 13:58:00 +09:00
eomsangdonandClaude Opus 5 fdfc0fb893 fix(B05): 코리도 클리핑 크래시·지형 렌더 복구 + 측구 구간 분할 + 종단 스무딩
클리핑 정상화 (절토가 원지반에 묻혀 안 보이던 원인)
- 정점 버퍼를 count 길이로 잘라 복사 — 'offset is out of bounds'로 클리핑
  전체가 죽어 원지반이 하나도 안 잘리고 있었다(삼각형 485,358 → 477,239 확인)
- 정점색을 원본 배열 타입·normalized 그대로 복사(GLB는 정규화 Uint8 RGBA)
- 원본에 법선이 없으면 클리핑본도 만들지 않는다 — 직접 계산하면 감기 방향이
  원본과 달라 지형이 새까맣게 렌더됐다

표현 규칙
- 측구가 한쪽 측점에만 있으면 측점 사이 중간에서 끊는다(사용자 확정).
  폭 0 축퇴로 잇던 방식을 걷어내 없는 자리의 서피스·윤곽선 제거
- 리본을 조각이 존재하는 연속 구간별로 분리 생성
- 종단 세분 2m → 1m, 측점 사이 표고를 종단 계획선(종단곡선 포함) 기준으로
  보정 — 도로·측구는 전량, 비탈은 지반 접점까지 감쇠
- 측점 가로선을 예상형상 표시 중에는 계획고 위로 올림
- 지형 기본 표시를 흑백으로

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 13:42:16 +09:00
eomsangdonandClaude Opus 5 7fdbb343ab feat(B05): 코리도 편집 즉시 반영 + 프리즈 제거 + 구분 품질 4종
편집 반영
- Profile_Panel 프리뷰를 full_designs로 올려 설계선까지 갱신, 갱신 후
  onCrossDesignsUpdated 콜백 → Page가 코리도 재빌드(500ms 디바운스)
- 종단 계획고를 올리면 3D 예상형상이 그 자리에서 따라 바뀐다

프리즈 제거 (프레임 갭 실측 3603ms → 100ms, 100ms 초과 0회)
- Corridor_Terrain(신규): 지형 XZ 균일격자 높이 색인. 심 보정 raycast가
  BVH 없이 전 삼각형을 훑어 3.6초 단일 블록을 만들던 것을 버킷 조회로 대체.
  지형 로드당 1회만 구축
- Corridor_Clip: 스트립 셀·경계선분 균일격자 색인, 핫루프를 정점 복사에서
  인덱스 재구성으로 전환(원본 버퍼 재사용, 잘린 조각만 덧붙임)

구분 품질 (사용자 확정 4종)
- 색 재설계: 지형 고도색(주황~녹)과 겹치던 적갈/초록을 자주(절토)·청록(성토)
  으로, 도로계는 무채색, 측구 하늘색
- 종류 경계 윤곽선, 절·성토 빗금(해칭) 텍스처 방향 구분(절 우상향/성 좌상향)
- 시·종점 마구리 봉인 — 설계선↔지반선 절단면 스트립(저장 왕복 포함)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 13:11:49 +09:00
eomsangdonandClaude Opus 5 3b997963e3 feat(B05): 3D 예상형상 — 계획노선 코리도 서피스·원지반 경계 재절단·영구저장
- Corridor_Build: design_line을 차도/노견/측구/절토/성토 5종으로 분류,
  catch point(설계선-지반 교차)로 점유 폭 산출, 노선 폴리라인 2m 세분
  중간 프레임 보간 (계산식 재구현 없이 백엔드 design_line 소비만)
- Corridor_Mesh: 종류별 색 리본 BufferGeometry 조합(멀티 스윕)
- Corridor_Clip: catch line 스트립으로 지형 삼각형 경계 재절단(셀 단위
  판정·정점색 보간), 원본 보존 — [예상형상] 토글 OFF 시 원지반 완전체 복원
- Viewer: 원본/클리핑 지형 두 벌 스왑, 비탈 최외곽 z 지형 투영(심 보정),
  클립 rAF 비동기, 흑백·dispose 연동
- Panel: [예상형상] 토글 (기본 ON)
- Corridor 엔트리: 설계 입력 FNV-1a 해시 버전, base64 Float32 JSON 직렬화,
  최초 빌드 즉시 저장 + 임시저장·페이지 이동 시 dirty 저장, SPA 메모리 캐시
- Router_Corridor(신규)+main 등록: GET/PUT corridor 파일 보관
  (B05_Profile/corridor/, atomic, 64MB 상한)
- 검증: tsc·ruff·pytest 5/5, 공용 브라우저 실조작(토글·B06 변경 왕복·
  저장 왕복 네트워크 실측), 저장본 리본 수치 대조

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 12:28:37 +09:00