Merge remote-tracking branch 'origin/main_laptop_1' into sub_desktop_1

This commit is contained in:
2026-09-09 21:28:30 +09:00
7 changed files with 254 additions and 8 deletions
@@ -639,6 +639,56 @@ def _num(value: Any, fallback: float = 0.0) -> float:
return float(value) if isinstance(value, (int, float)) else fallback
#: 벽 두께를 **사용자가 덮어쓰는 칸** — 비우면 실무 구조물도 식으로 돈다(확정 2차 ② 후반
#: 「사용자가 값을 바꿀 수 있게」). 야면석 계수·채움 강도와 같은 자리다.
WALL_THICKNESS_KEYS: tuple[str, str] = ("thickness_top_m", "thickness_bottom_m")
def wall_thickness(
options: dict[str, Any], *, back_cm: float, height_m: float
) -> tuple[float, float, str]:
"""(상부 두께 m, 하부 두께 m, 근거 문구) — **사용자가 넣은 값이 식을 이긴다.**
⚠ 빈 칸은 「안 정함」이다 — 자동으로 나온 값을 저장에 박지 않는다(`face_slope_ratio`
와 같은 태도). 상부만 넣으면 하부는 **그 상부 위에서** 식을 이어 간다 — 벽 모양
(아래로 벌어지는 기울기)을 사용자 값 위에 그대로 얹는 것이 자연스럽다.
"""
def given(key: str) -> float | None:
raw = options.get(key)
if raw in (None, ""):
return None
try:
value = float(raw)
except (TypeError, ValueError):
return None
return value if value > 0 else None
constants = STONE_MASONRY
back_m = back_cm / 100.0
top_given = given(WALL_THICKNESS_KEYS[0])
top = top_given if top_given is not None else back_m + constants["thickness_top_add_m"]
rise = constants["thickness_slope_per_m"] * max(
height_m - constants["thickness_height_base_m"], 0.0
)
bottom_given = given(WALL_THICKNESS_KEYS[1])
bottom = bottom_given if bottom_given is not None else top + rise
top_basis = (
f"상부 {top:.2f}(사용자 입력)"
if top_given is not None
else f"상부 {top:.2f}(뒷길이 {back_cm:g}㎝ + {constants['thickness_top_add_m']:g})"
)
bottom_basis = (
f"하부 {bottom:.2f}(사용자 입력)"
if bottom_given is not None
else (
f"하부 {bottom:.2f}(상부 + {constants['thickness_slope_per_m']:g}"
f"×(H−{constants['thickness_height_base_m']:g}))"
)
)
return top, bottom, f"실무 구조물도 식 — {top_basis} · {bottom_basis}"
#: 큰돌쌓기(품셈 13-6) 직경 갈래 — **저장 제원 `stone_cm` 과 글자까지 같다**(레지스트리 확인).
#: ⚠ 돌쌓기(13-4)의 **뒷길이** 축과 섞지 않는다. 앞서 섞여 있어 직경 60~80 짜리가
#: 「뒷길이 45㎝」 계수로 돌던 자리다.
@@ -871,16 +921,12 @@ def stone_masonry(
# 실무 시트의 「정면적 × 1.04」가 바로 이 값이다(1:0.3 에서 1.0440 ≈ 1.04).
masonry_area = face_area * math.hypot(1.0, slope_ratio)
# 벽 두께 — 실무 구조물도 식(확정 2차 ②). **뒷길이가 들어간다.**
back_m = back_cm / 100.0
top_thickness = back_m + constants["thickness_top_add_m"]
bottom_thickness = top_thickness + constants["thickness_slope_per_m"] * max(
height_m - constants["thickness_height_base_m"], 0.0
# ⚠ 표준도 제원에 상부·하부 두께 칸이 있으면 **그 값이 식을 이긴다**(확정 ② 후반).
back_m = back_cm / 100.0 # 석적(아래)이 뒷길이를 m 로 쓴다
top_thickness, bottom_thickness, thickness_basis = wall_thickness(
options, back_cm=back_cm, height_m=height_m
)
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 = [