feat(B06): 절토 비탈 법정 기울기 검사 — 별표2 범위 밖이면 카드에 경고

법정 위반 표시가 없던 유일한 자리였음(평면 곡선반경·성토사면 길이는 이미 있음).
절토 경사비는 표준 횡단면 설정에서 오는 입력값일 뿐이라 범위를 벗어나도 아무 표시가 없었음.

- 기준 — 별표2(지식DB `01_임도/02_상세설계/절토_비탈면.md` §1): 경암 1:0.3~0.8 ·
  연암 1:0.5~1.2 · 토사 1:0.8~1.5. **작업임도는 규정 없음 → 검사 제외.**
- 판정은 **구간별 경사**(`cut_slope_segments`)로 함. 소단이 서면 실효 경사가 완만해져
  **위반이 사라진 것처럼** 보임(폭 1.0·간격 2 이면 1:1 이 1:1.71). 그 함정을 시험으로 못박음.
- 표시는 **기존 방식 그대로** — 성토사면·미폐합 경고와 같은 자리·같은 클래스. 새 방식 안 만듦.
- 지반유형(리핑암·발파암) → 별표2 줄 매핑은 법령 근거가 아니라 **프로그램 설정**이라
  표준 횡단면 설정에서 **사용자가 고르게** 함(2026-09-07 사용자 확정). 기본값 리핑암 → 연암 ·
  발파암 → 경암. 표준단면과 함께 저장돼 이미 사용자 값 계통임.
- 기준값은 서버가 컨텍스트로 내려보냄 — 화면에 상수를 복제하지 않음.

시험 7건 — 별표2 값 · 작업임도 제외 · 매핑이 기본값일 뿐 · 구간별 판정 ·
**소단이 있어도 위반이 안 사라짐** · 경계값 통과 · 카드에 같은 방식으로 붙는지.

⚠ 실화면 — 사용자 선택 칸은 섰음(리핑암 연암 · 발파암 경암). 다만 이 프로젝트 저장분
63측점에 `cut_slope_segments` 가 아직 없어(오늘 새로 생긴 키) 경고가 뜨는 것은 못 봄.
재계산이 한 번 돌면 채워짐 — 지금 경고 0건은 맞는 동작임.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-07 16:20:42 +09:00
co-authored by Claude Opus 5
parent d48302898f
commit 973128f798
8 changed files with 252 additions and 2 deletions
@@ -13,6 +13,7 @@ import {
buildRockBoundaryControl,
sectionModeLabel,
} from "./B06_Section_UI_Cross_Design";
import { limitLabel, violationsOf } from "./B06_Section_Cut_Slope_Check";
import { type FillSlopeLength, fillSlopeLengths } from "./B06_Section_UI_Cross_Fit";
import {
type DesignChangeHandler,
@@ -85,6 +86,26 @@ export function appendCardHeader(
openSlope.title = L("B06_Cross_SlopeUnclosed_Tip");
meta.append(openSlope);
}
// 절토 비탈 법정 기울기(별표2) 위반 — 성토사면·미폐합 경고와 같은 자리·같은 모양이다.
// 소단이 서면 실효 경사가 완만해져 위반이 사라진 것처럼 보이므로, 판정은 **구간별**
// 경사(`cut_slope_segments`)로 한다(2026-09-07).
const cutViolations = violationsOf(section);
if (cutViolations.length) {
const worst = cutViolations[0];
const badge = document.createElement("span");
badge.className = "b06-cross-card__warning";
badge.textContent = `⚠ 절토 1:${worst.ratio.toFixed(2)}`;
badge.title = cutViolations
.map(
(item) =>
`${item.side === "left" ? "좌" : "우"} 1:${item.ratio.toFixed(2)}` +
`${limitLabel(item.limitKey)} 법정 1:${item.limit.min}~${item.limit.max}` +
` 범위 밖(${item.kind === "steep" ? "너무 급함" : "너무 완만함"})` +
` · ${item.startOffsetM.toFixed(2)}~${item.endOffsetM.toFixed(2)}m`,
)
.join("\n");
meta.append(badge);
}
const structureName = section.structure;
if (structureName) {
const structure = document.createElement("span");