feat(485-1 B07 축척): 도면 X · Y 축척 서버 — 프로젝트마다 drawing_scales.json · GET/PUT /api/projects/{id}/drawing-scales · 엔진 drawing_scale(kind) 문맥 변수 · 종단 · 횡단(X ≠ Y) · 토적 · 전개도 · 바뀐 종류 저장본 풂 · 덧그림 mm_per_m_x · _y · 범위 밖 400 · 시험 test_280_5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-19 22:23:02 +09:00
co-authored by Claude Opus 5.5
parent afe6e4a799
commit 8c53124348
15 changed files with 732 additions and 58 deletions
@@ -30,6 +30,7 @@ from B07_DesignDetail.B07_DesignDetail_Engine_Cad import (
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Development import station_text, table_rows
from B07_DesignDetail.B07_DesignDetail_Engine_Template import (
drawing_area,
drawing_scale,
frame_entities,
scale_fields,
)
@@ -201,7 +202,10 @@ def fill_entities(seed: str, form: str, group: str, box: tuple[float, float, flo
def _vertical(rows: list[dict[str, Any]], mm_h: float) -> float:
"""세로 mm/m — 가로와 같게 두되 가장 높은 박스가 12~40 mm 안에 들게."""
"""세로 mm/m — 가로와 같게 두되 가장 높은 박스가 12~40 mm 안에 들게 · 정했으면 그 값(485)."""
fixed = drawing_scale("development")["y"]
if fixed:
return 1000.0 / fixed
tallest = max((r["height_m"] for r in rows if r["height_m"]), default=None)
if not tallest:
return _MIN_H
@@ -239,7 +243,12 @@ def layout(rows, area, table_box, mm_h, strict=True):
def _choose(rows, area, table_box):
"""처음 드는 축척 — 끝까지 안 들면 가장 작은 축척으로 그대로(도각이 넘침 경고)."""
"""처음 드는 축척 — 끝까지 안 들면 가장 작은 축척으로 그대로(도각이 넘침 경고).
가로 축척을 정했으면(485) 그 값 하나만 — 넘쳐도 그대로."""
fixed = drawing_scale("development")["x"]
if fixed:
return fixed, layout(rows, area, table_box, 1000.0 / fixed, strict=False)
for denominator in SCALES:
placed = layout(rows, area, table_box, 1000.0 / denominator)
if placed is not None:
@@ -366,6 +375,18 @@ def build_development_drawing(
table_w, table_h = sum(_COLUMNS), _ROW_H * (len(lines) + 3)
table_box = (ax1 - _MARGIN - table_w, ay0 + _MARGIN, ax1 - _MARGIN, ay0 + _MARGIN + table_h)
denominator, placed = _choose(rows, area, table_box)
vertical = drawing_scale("development")["y"]
# 세로를 정했고 가로와 다르면 이름표(H · V) — 자동 세로는 지금처럼 가로만(485)
scales = (
(("H", denominator), ("V", vertical))
if vertical and vertical != denominator
else (("", denominator),)
)
scale_text = (
f"H=1:{denominator:,} V=1:{vertical:,}"
if vertical and vertical != denominator
else f"S=1:{denominator:,}"
)
def station(chainage: float) -> str:
return station_text(chainage, interval_m)
@@ -382,7 +403,7 @@ def build_development_drawing(
),
_text_entity(
f"{drawing_id}:scale",
f"S=1:{denominator:,}",
scale_text,
ax1 - _MARGIN,
ay1 - 14.0,
LABEL_LAYER_ID,
@@ -425,7 +446,7 @@ def build_development_drawing(
area,
fit=False,
bottom_left=True,
fields={"도면명": title, **scale_fields(("", denominator))},
fields={"도면명": title, **scale_fields(*scales)},
)
return {
"format": DRAWING_FORMAT,