Files
Aislo/resources/tester/test_180_2_b07_cross_scale.py
T
eomsangdonandClaude Opus 5.5 303342a56e feat(b07): 횡단 장 측점마다 도면층 · 옛 확정 장 원지반 잠금 풂(212-1 · 212-2)
- 까닭: 새로 만든 장은 서버 · CAD 걸름 모두 원지반이 잡힘 — 안 잡힌 것은 180-1 앞에 원지반 층 잠금째 저장된 확정 장 또는 반영 전 서버 · 페이지 메모리의 옛 도면
- 확정 장을 열 때 원지반 층 잠금 풂 · 측점 층 없는 확정 장은 stale_layers 안내([수정] 때 새 꼴)
- 장의 측점마다 층 하나(b08-station-{측점} · 「횡단 No.3」) = 원지반 · 계획선 · 구조물 · 암 그림(자식 선까지) · 종류는 색 · 선 꼴 · 표 · 글은 수량표 층 · 종류 층 지움
- 개체 id · groupId 그대로 · placement 에 layer_id · design_ids — 화면 덧그림도 측점 층 · 서버 설계선은 id 로 걷음
- DXF 층 이름 = 측점 층 id
- 새 시험 test_212 · 174 · 180 · 180_2 원지반 찾기를 색으로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNMXVCZXMpHpVvqmFkeChL
2026-10-10 15:29:22 +09:00

171 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""180-2 B07 횡단 장 — 표 · 표 위 글 배율(모든 장 한 값 · 0.5~2.0 · 기본 1).
못박는 것
- 배율 1.5 = 표 폭 162 · 높이 60 · 글 줄 높이 × 1.5 · 표 아래선은 칸 아래 + 여백 그대로.
- 그림 아래 끝 = 글(없으면 표) 위 8 mm(간격은 배율 안 탐) · 넓은 표가 칸을 넘으면 overflow_cells.
- 배율 1 = 배율 칸 없는 배치와 같은 엔티티.
- cross_layout.json 이 배율을 지킴 · 범위 밖 = 거절 · 배율만 바꾸면 확정 장 안 풂.
- 지금과 다른 배율로 확정된 장 = 그대로 + stale_scale 안내.
"""
import json
from pathlib import Path
import pytest
from B07_DesignDetail.B07_DesignDetail_Engine_Cad import DRAWING_FORMAT, GROUND_COLOR
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Sheet import (
CELL_TABLE_PAD_MM,
build_cross_sheet,
plan_cross_sheets,
)
from B07_DesignDetail.B07_DesignDetail_Engine_Template import (
entities_bbox,
usable_area,
use_project_templates,
)
from B07_DesignDetail.B07_DesignDetail_Router_Support import (
CROSS_SHEET_LAYOUT,
_cross_sheet_plan,
_read_drawing,
_read_manifest,
_write_manifest,
read_cross_layout,
write_cross_layout,
)
NOTE = {"structure_note": "L형 측구\n집수정 보강"}
def _source(chainage: float, lo: int = -5, hi: int = 5) -> dict:
return {
"chainage_m": chainage,
"samples": [
{"valid": True, "offset_m": float(x), "elevation_m": 100.0 + 0.05 * x}
for x in range(lo, hi + 1)
],
}
def _drawing(layout: dict, designs: list[dict | None]) -> tuple[dict, dict]:
use_project_templates(None)
sources = [_source(i * 20.0) for i in range(len(designs))]
sheet = plan_cross_sheets([s["chainage_m"] for s in sources], layout)[0]
sections = [
{
"chainage": s["chainage_m"],
"source": s,
"design": design,
"quantity_table": {"ground": 1.0, "planned": 0.5},
"title": "No.0",
}
for s, design in zip(sources, designs, strict=True)
]
return sheet, build_cross_sheet(sheet, sections)
def _tables(drawing: dict) -> list[dict]:
return [e for e in drawing["entities"] if e["type"] == "Table"]
def test_배율_15_표_크기와_쌓기() -> None:
sheet, drawing = _drawing({"default": [2, 2], "table_scale": 1.5}, [NOTE, None])
assert sheet["table_scale"] == 1.5
_w, h = usable_area()
tables = _tables(drawing)
for table, slot in zip(tables, sheet["slots"], strict=True):
shape = table["shapeData"]
assert sum(shape["columnWidths"]) == pytest.approx(162.0)
assert sum(shape["rowHeights"]) == pytest.approx(60.0)
bottom = shape["origin"]["y"] - sum(shape["rowHeights"])
assert bottom == pytest.approx(slot[1] - h / 4 + CELL_TABLE_PAD_MM) # 표 아래선 그대로
grounds = [
entities_bbox([e])
for e in drawing["entities"]
if e.get("type") == "PolyLine" and e.get("lineColor") == GROUND_COLOR
]
# 글 2 줄 × 3.0 × 1.5 = 9 mm · 간격 8 mm 는 배율 안 탐
tops = [t["shapeData"]["origin"]["y"] for t in tables]
assert grounds[0][1] == pytest.approx(tops[0] + 9.0 + 8.0)
assert grounds[1][1] == pytest.approx(tops[1] + 8.0)
def test_배율_1_은_지금과_같음() -> None:
_s, plain = _drawing({"default": [2, 2]}, [NOTE, None])
_s, one = _drawing({"default": [2, 2], "table_scale": 1.0}, [NOTE, None])
assert one["entities"] == plain["entities"]
assert sum(_tables(one)[0]["shapeData"]["columnWidths"]) == pytest.approx(108.0)
def test_넓은_표_넘침() -> None:
w, _h = usable_area()
# 4 × 4 칸 폭 192.5 — 표 108 × 2.0 = 216 이 칸을 넘음
_s, drawing = _drawing({"default": [4, 4], "table_scale": 2.0}, [None])
assert w / 4 < 216.0
assert len(drawing["overflow_cells"]) == 1
_s, drawing = _drawing({"default": [4, 4], "table_scale": 1.0}, [None])
assert drawing["overflow_cells"] == []
def _project(tmp_path: Path, count: int) -> tuple[Path, Path]:
root = tmp_path / "project"
cross_dir = root / "B06_Section" / "cross_sections"
cross_dir.mkdir(parents=True)
longitudinal_path = root / "B06_Section" / "longitudinal" / "longitudinal.json"
longitudinal_path.parent.mkdir(parents=True)
stations = []
for i in range(count):
chainage = i * 20
stations.append({"chainage_m": float(chainage), "center_x": 0.0, "center_y": 0.0})
(cross_dir / f"cross_{chainage:05d}m.json").write_text(
json.dumps(_source(float(chainage))), "utf-8"
)
longitudinal_path.write_text(json.dumps({"stations": stations}), "utf-8")
return root, longitudinal_path
def test_배치_파일_배율_저장_범위(tmp_path: Path) -> None:
root, longitudinal_path = _project(tmp_path, 5)
ids = [s["id"] for s in _cross_sheet_plan(root, longitudinal_path)]
manifest = _read_manifest(root)
manifest["drawings"] = {i: {"confirmed": True} for i in ids}
_write_manifest(root, manifest)
# 배율만 바꿈 — 담긴 측점 그대로라 확정 장 안 풂
assert (
write_cross_layout(root, longitudinal_path, {"default": [4, 4], "table_scale": 1.3}) == []
)
assert read_cross_layout(root)["table_scale"] == 1.3
assert _read_manifest(root)["drawings"][ids[0]]["confirmed"] is True
assert _cross_sheet_plan(root, longitudinal_path)[0]["table_scale"] == 1.3
for bad in (0.4, 2.1, "1.2", True):
with pytest.raises(ValueError):
write_cross_layout(root, longitudinal_path, {"default": [4, 4], "table_scale": bad})
assert read_cross_layout(root)["table_scale"] == 1.3
def test_옛_배율_확정_장_안내(tmp_path: Path) -> None:
stage = tmp_path / "B07_DesignDetail"
(stage / "drawings").mkdir(parents=True)
saved = {"format": DRAWING_FORMAT, "entities": [], "layers": []}
(stage / "drawings" / "cross_s00000m.json").write_text(json.dumps(saved), encoding="utf-8")
entry = {"kind": "cross", "label": "1장", "confirmed": True, "layout": CROSS_SHEET_LAYOUT}
manifest = {"drawings": {"cross_s00000m": entry}}
(stage / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
def read() -> dict:
_k, _l, drawing, confirmed, _t = _read_drawing(
tmp_path, tmp_path / "x.json", "cross_s00000m"
)
assert confirmed
return drawing
assert "stale_scale" not in read() # 배율 적힘 없음 = 1 · 지금도 1
(stage / "cross_layout.json").write_text(
json.dumps({"default": [4, 4], "sheets": {}, "table_scale": 1.5}), encoding="utf-8"
)
assert read().get("stale_scale") is True
entry["table_scale"] = 1.5
(stage / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
assert "stale_scale" not in read()