feat(B08): 돌쌓기 벽 두께를 실무 구조물도 식으로 교체 (확정 2차 ②)

- 상부 = 뒷길이(ℓ3) + 0.30 · 하부 = 상부 + 0.30 × (H − 1.0) · 평균이 두께
- 옛 식(0.45 + 0.10H / 0.45 + 0.40H)에는 뒷길이가 없어 35↔45 를 바꿔도
  돌 부피·막자갈·터파기가 같은 값으로 섰음
- H ≤ 1.0 은 (H−1) 몫을 0 으로 눅여 하부가 상부보다 얇아지지 않게 함
- 산출근거 문구에 식을 남김 — 막자갈·터파기 두 줄
- tmp/tests/test_b08_wall_thickness.py 신설(7건), 옛 두께를 못 박던
  test_b08_stone_kind.py 의 막자갈 밑값 15.130 → 12.630 정정

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-08 21:31:23 +09:00
co-authored by Claude Opus 5
parent b6bc9b9a54
commit 8141eb34e4
@@ -139,9 +139,18 @@ STONE_MASONRY = {
# ⚠ 하드코딩하면 안 되는 값이다 — 큰돌쌓기는 「1:0.3 **이상**」이라 기울기가
# 바뀔 수 있고, 그때 1.04 는 틀린 값이 되지만 `hypot` 은 따라간다.
"sheet_check_factor_at_0_3": 1.04, # 1:0.3 에서 시트값과 맞는지 대조하는 자리
"thickness_base_m": 0.45, # 평균두께 식의 밑돌 두께
"thickness_top_coeff": 0.10, # 상부 두께 계수 (0.45 + 0.10·H)
"thickness_bottom_coeff": 0.40, # 하부 두께 계수 (0.45 + 0.40·H)
# ⭐ 2026-09-09 확정 2차 ② — **실무 구조물도 식**으로 갈았음(랩탑 보조가 소광리 원본
# 네 탭에서 찾아 실측과 소수점까지 대조).
# 상부 두께 = 뒷길이(3) + 0.30
# 하부 두께 = 상부 + 0.30 × (H 1.0)
# ⚠ **옛 식에는 뒷길이가 없었다**(0.45 + 0.10·H / 0.45 + 0.40·H) — 뒷길이를 35 로
# 바꿔도 두께가 안 바뀌어 돌 부피·막자갈·터파기가 다 같은 값으로 섰다.
# ⚠ 정본 xls 의 「상부 0.75 · 하부 0.90」은 **H=1.5 규칙값을 다른 높이 탭에 복사**한
# 흔적이라 그대로 쓰면 H=1.5 밖에서 틀린다.
# ⚠ 돌조공(H=0.5 · 0.55/0.65)은 이 규칙 밖 — 다른 시설이라 여기서 다루지 않는다.
"thickness_top_add_m": 0.30, # 상부 = 뒷길이 + 0.30
"thickness_slope_per_m": 0.30, # 하부 = 상부 + 0.30 × (H 1.0)
"thickness_height_base_m": 1.0, # 그 식의 기준 높이
# ⚠ 미결 — 법은 「2~3 ㎡당 1개소 **이상**」(구조물_수량.md §물구멍)이고 2.0 은 **실무 관측값**이다.
# 범위의 한쪽 끝을 쓰는 것이라 사용자 확정 전까지 잠정이다. 식이 아니라 여기 있으니 갈아끼우면 된다.
"weep_hole_area_m2": 2.0, # 물구멍 1개소당 벽면적
@@ -588,10 +597,16 @@ def stone_masonry(
# 돌쌓기 면적 = 정면적 × √(1+n²) — 기울어진 만큼 길어진다. **기울기 몫은 한 번만.**
# 실무 시트의 「정면적 × 1.04」가 바로 이 값이다(1:0.3 에서 1.0440 ≈ 1.04).
masonry_area = face_area * math.hypot(1.0, slope_ratio)
thickness = (
(constants["thickness_base_m"] + constants["thickness_top_coeff"] * height_m)
+ (constants["thickness_base_m"] + constants["thickness_bottom_coeff"] * height_m)
) / 2.0
# 벽 두께 — 실무 구조물도 식(확정 2차 ②). **뒷길이가 들어간다.**
top_thickness = back_cm / 100.0 + constants["thickness_top_add_m"]
bottom_thickness = top_thickness + constants["thickness_slope_per_m"] * max(
height_m - constants["thickness_height_base_m"], 0.0
)
thickness = (top_thickness + bottom_thickness) / 2.0
thickness_basis = (
f"실무 구조물도 식 — 상부 {top_thickness:.2f}(뒷길이 {back_cm}㎝ + 0.30) ·"
f" 하부 {bottom_thickness:.2f}(상부 + 0.30×(H1))"
)
volume = face_area * thickness # 입적
components = [
@@ -651,7 +666,7 @@ def stone_masonry(
"",
rubble,
DESTINATION["막자갈"],
f"입적 (면적×뒷길이×{body_ratio:.4g} + 고임돌)"
f"입적 (면적×뒷길이×{body_ratio:.4g} + 고임돌) · {thickness_basis}"
+ (f" · {kind_label}" if kind_label else ""),
)
)
@@ -728,7 +743,11 @@ def stone_masonry(
components.extend(
[
Component(
"터파기", "", excavation, DESTINATION["터파기"], "높이 × (평균두께+0.2) × 연장"
"터파기",
"",
excavation,
DESTINATION["터파기"],
f"높이 × (평균두께 {thickness:.2f}+0.2) × 연장 · {thickness_basis}",
),
Component("되메우기", "", backfill, DESTINATION["되메우기"], "높이 × 0.2 × 연장"),
Component(