Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JywHxQuWPk6UYXTebyrBoU
92 lines
3.6 KiB
Python
92 lines
3.6 KiB
Python
"""B07 횡단도 — B06 [상세] 글(`design.structure_note`)이 수량표 바로 위 여러 줄로 찍힘(150-3).
|
|
|
|
글 줄마다 Text(표 왼쪽 맞춤 · 표 윗변 아래로 줄 수만큼 내림) · 블록 높이도 같은 만큼 · 글 없으면 그대로.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Cad import FRAME_LAYER_ID, build_cross_drawing
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Sheet import section_block_size
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Table import (
|
|
cross_note_height,
|
|
cross_note_lines,
|
|
)
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Template import entities_bbox
|
|
|
|
_SOURCE = {
|
|
"chainage_m": 20.0,
|
|
"samples": [
|
|
{"valid": True, "offset_m": float(x), "elevation_m": 100.0 + 0.3 * x}
|
|
for x in range(-10, 11)
|
|
],
|
|
}
|
|
_TABLE = {"ground": 100.0, "planned": 99.5}
|
|
|
|
|
|
def _draw(design: dict | None) -> dict:
|
|
return build_cross_drawing(_SOURCE, "cross_00020m", None, design, _TABLE, "No.1")
|
|
|
|
|
|
def _table(drawing: dict) -> dict:
|
|
return next(e for e in drawing["entities"] if e["type"] == "Table")
|
|
|
|
|
|
def _frame_height(drawing: dict) -> float:
|
|
frame = [e for e in drawing["entities"] if e.get("layerId") == FRAME_LAYER_ID]
|
|
_x0, y0, _x1, y1 = entities_bbox(frame)
|
|
return y1 - y0
|
|
|
|
|
|
def test_글_줄_나눔() -> None:
|
|
assert cross_note_lines(None) == []
|
|
assert cross_note_lines({"structure_note": " "}) == []
|
|
assert cross_note_lines({"structure_note": "\nL형 측구 \n\n집수정 보강\n"}) == [
|
|
"L형 측구",
|
|
"",
|
|
"집수정 보강",
|
|
]
|
|
|
|
|
|
def test_글_없으면_그대로() -> None:
|
|
plain = _draw(None)
|
|
empty = _draw({"structure_note": ""})
|
|
assert _table(plain)["shapeData"] == _table(empty)["shapeData"]
|
|
assert not [e for e in empty["entities"] if e["type"] == "Text"]
|
|
|
|
|
|
def test_글_두_줄은_표_위_Text_둘_표는_내려감() -> None:
|
|
plain = _draw(None)
|
|
noted = _draw({"structure_note": "L형 측구\n집수정 보강"})
|
|
texts = [e for e in noted["entities"] if e["type"] == "Text"]
|
|
assert [t["shapeData"]["label"] for t in texts] == ["L형 측구", "집수정 보강"]
|
|
|
|
plain_top = _table(plain)["shapeData"]["origin"]["y"]
|
|
noted_top = _table(noted)["shapeData"]["origin"]["y"]
|
|
drop = cross_note_height(["a", "b"])
|
|
assert plain_top - noted_top == pytest.approx(drop)
|
|
|
|
# 표 왼쪽 맞춤 · 위에서 아래로 · 모두 표 윗변과 옛 윗변 사이
|
|
left = _table(noted)["shapeData"]["origin"]["x"]
|
|
for text in texts:
|
|
base = text["shapeData"]["basePoint"]
|
|
assert base["x"] == pytest.approx(left)
|
|
assert text["shapeData"]["options"]["textAlign"] == "left"
|
|
assert noted_top < base["y"] < plain_top
|
|
assert texts[0]["shapeData"]["basePoint"]["y"] > texts[1]["shapeData"]["basePoint"]["y"]
|
|
|
|
# 블록(테두리) 높이 = 글 높이만큼 커짐 · 블록 크기 계산도 같은 규칙
|
|
assert _frame_height(noted) - _frame_height(plain) == pytest.approx(drop)
|
|
_w, plain_h = section_block_size(_SOURCE, None)
|
|
_w, noted_h = section_block_size(
|
|
_SOURCE, None, design={"structure_note": "L형 측구\n집수정 보강"}
|
|
)
|
|
assert noted_h - plain_h == pytest.approx(drop)
|
|
|
|
|
|
def test_빈_줄은_자리만() -> None:
|
|
noted = _draw({"structure_note": "윗줄\n\n아랫줄"})
|
|
texts = [e for e in noted["entities"] if e["type"] == "Text"]
|
|
assert [t["shapeData"]["label"] for t in texts] == ["윗줄", "아랫줄"]
|
|
gap = texts[0]["shapeData"]["basePoint"]["y"] - texts[1]["shapeData"]["basePoint"]["y"]
|
|
assert gap == pytest.approx(cross_note_height(["a", "b"]))
|