chore: 네 창 작업 269건 main 반영 (2026-09-09) #13

Merged
eomsangdon merged 269 commits from main_desktop_1 into main 2026-09-09 18:21:28 +09:00
2 changed files with 53 additions and 21 deletions
Showing only changes of commit fa7b4e515c - Show all commits
@@ -3,9 +3,10 @@
실무 원본 탭이 「위 치수조서 + 아래 수량산출서」인데, 아래 표는 1단계에서 섰고 여기가 위다.
⚠ **기울기를 값으로 받는다 — 0.3 을 박지 않는다.**
품셈 표준경사 표 자동 판정이 다른 창에서 붙는 중이고, 붙으면 이 그림이 **그 값으로**
기울어져야 한다. `face_slope_ratio` 가 비면(=자동 미구현·미입력) 교본 7-3 기본 0.3 으
리되 **그 사실을 그림에 적는다**.
판정은 **B08 `face_slope_ratio()` 한 벌**을 그대로 부른다(품셈 13-4-4 [주]⑪ 표준경사 —
직고·메찰·성절토). 사용자가 정했으면 그 값이 이긴다(확정 ⑨). 그림은 **수량이 쓴 바
값**으로 기울고, 근거 문구도 같이 받아 그림에 적는다 — 판정을 두 벌로 짜면 그림과
수량이 갈린다.
⚠ **수량이 쓰는 그 상수로 그린다** — `B08_Quantity_Engine_UnitQuantity.STONE_MASONRY` 를
직접 읽는다. 치수를 여기서 다시 적으면 **그림과 표가 갈린다**(CLAUDE.md 5장).
@@ -31,7 +32,7 @@ from B07_DesignDetail.B07_DesignDetail_Engine_Cad import (
_text_entity,
polyline_entity,
)
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import STONE_MASONRY
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import STONE_MASONRY, face_slope_ratio
#: 그림 축척 — 1/25(1m = 40㎜). 표(줄 높이 9㎜) 위에 얹어도 한 면에 드는 크기다.
SCALE_MM_PER_M = 40.0
@@ -39,19 +40,25 @@ SCALE_MM_PER_M = 40.0
#: 이 그림을 그리는 종류. 옹벽·집수정처럼 단면이 다른 것은 아직 그리지 않는다.
FIGURE_TYPE_IDS: frozenset[str] = frozenset({"masonry_wet", "masonry_dry", "boulder_masonry"})
#: 기울기를 못 받았을 때 쓰는 값 — 교본 7-3 「돌 찰쌓기 3.0m 이하 1:0.3」.
DEFAULT_SLOPE_RATIO = 0.3
_LABEL_FONT = 4.0
_DIM_FONT = 3.4
def slope_ratio_of(options: dict[str, Any] | None) -> tuple[float, bool]:
"""전면 기울기와 **그것이 입력된 값인지**. 비어 있으면 `(0.3, False)`."""
raw = (options or {}).get("face_slope_ratio")
if isinstance(raw, (int, float)) and float(raw) > 0:
return float(raw), True
return DEFAULT_SLOPE_RATIO, False
def slope_of(sheet: dict[str, Any]) -> tuple[float, str]:
"""장 하나의 전면 기울기와 근거 문구 — **판정은 B08 한 벌**을 그대로 쓴다.
메/찰은 종류에서 온다. 큰돌쌓기는 `bond` 칸(메쌓기/찰쌓기)이 그것이고, 안 고르면
찰쌓기로 본다 — 품셈 13-6 은 둘 다 「1:0.3 **이상**」이라 그림 기울기가 갈리지 않는다.
"""
options = sheet.get("options") or {}
type_id = str(sheet.get("type_id") or "")
if type_id == "masonry_dry":
wet = False
elif type_id == "boulder_masonry":
wet = options.get("bond") != "메쌓기"
else:
wet = True
return face_slope_ratio(options, wet=wet, height_m=float(sheet.get("height_m") or 0.0))
def section_points(height_m: float, slope_ratio: float) -> list[tuple[float, float]]:
@@ -87,7 +94,7 @@ def build_figure(
return [], 0.0
options = sheet.get("options") or {}
slope, slope_given = slope_ratio_of(options)
slope, slope_note = slope_of(sheet)
scale = SCALE_MM_PER_M
ox, oy = origin
@@ -148,11 +155,7 @@ def build_figure(
(f"H = {height_m:g} m", (-0.28, height_m / 2.0), "right"),
(f"상부 {top_t:.2f} m", (slope * height_m + top_t / 2.0, height_m + 0.14), "center"),
(f"하부 {bottom_t:.2f} m", (bottom_t / 2.0, -0.30), "center"),
(
f"1 : {slope:g}" + ("" if slope_given else " (자동 판정 전 — 교본 기본값)"),
(slope * height_m / 2.0 - 0.30, height_m * 0.72),
"right",
),
(f"1 : {slope:g}", (slope * height_m / 2.0 - 0.30, height_m * 0.72), "right"),
(
f"터파기 폭 {dig_width:.2f} m (평균두께 {average_t:.2f} + 0.20)",
(dig_width + 0.16, height_m * 0.92),
@@ -185,6 +188,21 @@ def build_figure(
)
)
# 기울기 근거는 **그림 밑에** 한 줄 — 「사용자 지정」인지 「품셈 표준경사」인지 보여야 한다.
note_x, note_y = mm((0.0, -0.62))
entities.append(
_text_entity(
f"{drawing_id}:fig:slopenote",
f"전면 기울기 — {slope_note}",
note_x,
note_y,
layer_id,
_DIM_FONT,
label_color,
"left",
)
)
title_x, title_y = mm((0.0, height_m + 0.52))
entities.append(
_text_entity(
@@ -76,6 +76,18 @@ def sheet_key(structure: dict[str, Any]) -> str:
return json.dumps(payload, ensure_ascii=False, sort_keys=True)
def _slope_or_none(structure: dict[str, Any]) -> float | None:
"""돌쌓기 계열이면 판정된 전면 기울기, 아니면 `None`. 판정은 그림 모듈이 가진 한 벌."""
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_StandardFigure import (
FIGURE_TYPE_IDS,
slope_of,
)
if str(structure.get("type_id") or "") not in FIGURE_TYPE_IDS:
return None
return slope_of(structure)[0]
def sheet_title(structure: dict[str, Any]) -> str:
"""장 제목 — 「이름 H=2.0 1:0.3 뒷길이 45㎝」처럼 **무엇이 갈랐는지**가 보이게."""
parts = [str(structure.get("name") or structure.get("type_id") or "구조물")]
@@ -83,9 +95,11 @@ def sheet_title(structure: dict[str, Any]) -> str:
if height > 0:
parts.append(f"H={height:g}")
options = structure.get("options") or {}
slope = options.get("face_slope_ratio")
# 기울기는 **판정 결과**를 적는다 — 사용자가 안 정해도 품셈 표준경사로 갈린다(확정 ⑨).
# 판정이 안 되는 종류(옹벽 등)는 안 적는다.
slope = _slope_or_none(structure)
if slope is not None:
parts.append(f"1:{float(slope):g}")
parts.append(f"1:{slope:g}")
back = options.get("back_len_cm") or options.get("stone_back_length_cm")
if back:
parts.append(f"뒷길이 {int(back)}")