diff --git a/B08_Quantity/B08_Quantity_Engine_UnitQuantity.py b/B08_Quantity/B08_Quantity_Engine_UnitQuantity.py index ab920281..398fe2de 100644 --- a/B08_Quantity/B08_Quantity_Engine_UnitQuantity.py +++ b/B08_Quantity/B08_Quantity_Engine_UnitQuantity.py @@ -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×(H−1))" + ) 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(