"""측구터파기 단면적을 토사/암으로 가르는 규칙 (2026-09-09). 별표2 Ⅰ.1.나.(5) 「측구터파기 단면적」이 횡단도 표의 법정 칸이라 반만 채워 나가면 안 된다. ⚠ **새 입력을 만들지 않는다** — 절토 분리와 같은 근거(지반 유형 + 암반 경계선)를 쓰고, 근거가 없으면 **나누지 않고 사유를 낸다**. 절반을 임의로 가르는 것이 가장 나쁘다. """ from __future__ import annotations import sys from pathlib import Path import pytest PROJECT_ROOT = Path(__file__).resolve().parents[2] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from B06_Section.B06_Section_Engine_Areas import _split_ditch_area # noqa: E402 from B06_Section.B06_Section_Engine_Design import compute_cross_design # noqa: E402 _STANDARD = {"type": "standard", "top_width_m": 0.9, "bottom_width_m": 0.3, "depth_m": 0.3} _L_TYPE = {"type": "l_type", "width_m": 0.6, "depth_m": 0.3} _TOTAL_STANDARD = (0.9 + 0.3) / 2 * 0.3 def test_경계선이_바닥보다_깊으면_전량_토사() -> None: soil, rock = _split_ditch_area(_STANDARD, 5.0) assert soil == pytest.approx(_TOTAL_STANDARD) assert rock == pytest.approx(0.0) def test_경계선이_상단_위면_전량_암() -> None: soil, rock = _split_ditch_area(_STANDARD, -1.0) assert soil == pytest.approx(0.0) assert rock == pytest.approx(_TOTAL_STANDARD) def test_중간이면_사다리꼴을_가로로_가른다() -> None: """깊이 절반 지점 — 위쪽이 넓어 토사분이 절반보다 크다.""" soil, rock = _split_ditch_area(_STANDARD, 0.15) assert soil + rock == pytest.approx(_TOTAL_STANDARD) assert soil > _TOTAL_STANDARD / 2 # 위가 넓다 # 폭 W(d) = 0.9 − 2·d 를 0~0.15 적분: 0.9·0.15 − 2·0.15²/2 assert soil == pytest.approx(0.9 * 0.15 - (0.9 - 0.3) * 0.15**2 / (2 * 0.3)) def test_L형도_합이_보존된다() -> None: total = 0.6 * 0.3 / 2 for depth in (0.0, 0.1, 0.2, 0.3, 1.0): soil, rock = _split_ditch_area(_L_TYPE, depth) assert soil + rock == pytest.approx(total), depth def test_측구가_없으면_둘_다_0() -> None: assert _split_ditch_area({"type": "none"}, 0.2) == (0.0, 0.0) def _ground(slope: float = 0.5) -> list[dict]: return [ {"offset_m": offset / 2.0, "elevation_m": 100.0 - (offset / 2.0) * slope} for offset in range(-24, 25) ] def test_토사_지반은_전량_토사이고_사유가_남는다() -> None: result = compute_cross_design(_ground(), 100.0, ground_type="soil", section_mode="left_cut") assert result["ditch_split_basis"] in {"soil_ground", "no_ditch"} assert result["ditch_rock_area_m2"] == 0.0 assert result["ditch_soil_area_m2"] + result["ditch_rock_area_m2"] == pytest.approx( result["ditch_area_m2"] ) def test_암_지반에_경계선이_없으면_전량_암() -> None: result = compute_cross_design( _ground(), 100.0, ground_type="ripping_rock", section_mode="left_cut", rock_boundary_offset_m=None, ditch_enabled=True, ) if result["ditch_split_basis"] == "no_ditch": pytest.skip("이 표본에는 측구가 안 선다") assert result["ditch_split_basis"] == "rock_ground_no_boundary" assert result["ditch_soil_area_m2"] == 0.0 def test_암_지반에_경계선이_있으면_그것으로_가른다() -> None: result = compute_cross_design( _ground(), 100.0, ground_type="ripping_rock", section_mode="left_cut", rock_boundary_offset_m=0.5, ditch_enabled=True, ) if result["ditch_split_basis"] == "no_ditch": pytest.skip("이 표본에는 측구가 안 선다") assert result["ditch_split_basis"] == "rock_boundary" assert result["ditch_soil_area_m2"] + result["ditch_rock_area_m2"] == pytest.approx( result["ditch_area_m2"] ) def test_합계_키는_그대로_남는다() -> None: """B08 이 읽는 `ditch_area_m2` 를 안 깨뜨린다 — 갈래는 덧붙인 것이다.""" result = compute_cross_design(_ground(), 100.0, ground_type="soil", section_mode="left_cut") assert "ditch_area_m2" in result