feat(B07): 횡단도 수량표 바로 위 B06 [상세] 글 여러 줄 · 칸 이름 「도면 표 위 글」(150-3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JywHxQuWPk6UYXTebyrBoU
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
"""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"]))
|
||||
Reference in New Issue
Block a user