- frame_entities bottom_left 선택 — 종단도만 좌하단 맞춤(나머지 중심 맞춤 그대로) - longitudinal_chunks: 30측점 묶음이 A1 작도영역을 넘으면 측점을 줄여 장을 더 나눔 · 축척 H 1/1,000 · V 1/200 고정 - 원·호 엔티티 헬퍼를 Engine_Cad.py 로 옮김(Long.py 700줄 아래) - 검증_sub4 종단 3장 그림 좌하단(도각 기준) 180,132 · 180,193 · 363,220 → 모두 47.05,52.04 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013rJwJMVL4EE31y77TB11AP
60 lines
2.5 KiB
Python
60 lines
2.5 KiB
Python
"""B07 종단도 — 장마다 그림 좌하단 = 작도영역 좌하단 · 고정 축척 · 넘치면 장을 더 나눔 (59-3)."""
|
|
|
|
import pytest
|
|
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Cad import FRAME_LAYER_ID
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Long import (
|
|
build_longitudinal_drawing,
|
|
longitudinal_chunks,
|
|
)
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Template import entities_bbox, usable_area
|
|
|
|
|
|
def _longitudinal(count: int, interval: float, slope: float) -> dict:
|
|
xs = [index * interval for index in range(count)]
|
|
return {
|
|
"samples": [{"valid": True, "chainage_m": x, "elevation_m": 100.0 + slope * x} for x in xs],
|
|
"stations": [{"chainage_m": x} for x in xs],
|
|
"design_profiles": [
|
|
{"samples": [{"chainage_m": x, "elevation_m": 100.5 + slope * x} for x in xs]}
|
|
],
|
|
}
|
|
|
|
|
|
def _sheets(longitudinal: dict) -> list[tuple[tuple, tuple]]:
|
|
result = []
|
|
for chunk in longitudinal_chunks(longitudinal):
|
|
entities = build_longitudinal_drawing(longitudinal, chunk["id"], chunk)["entities"]
|
|
content = entities_bbox([e for e in entities if e.get("layerId") != FRAME_LAYER_ID])
|
|
frame = entities_bbox([e for e in entities if e.get("layerId") == FRAME_LAYER_ID])
|
|
result.append((content, frame))
|
|
return result
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("count", "interval", "slope"),
|
|
[(66, 20.0, 0.05), (40, 40.0, 0.0), (40, 20.0, 0.25)],
|
|
)
|
|
def test_every_sheet_fits_and_starts_at_same_corner(count, interval, slope) -> None:
|
|
longitudinal = _longitudinal(count, interval, slope)
|
|
sheets = _sheets(longitudinal)
|
|
usable_w, usable_h = usable_area()
|
|
corners = set()
|
|
for content, frame in sheets:
|
|
assert content[2] - content[0] <= usable_w + 1e-6
|
|
assert content[3] - content[1] <= usable_h + 1e-6
|
|
corners.add((round(content[0] - frame[0], 3), round(content[1] - frame[1], 3)))
|
|
assert len(corners) == 1
|
|
chunks = longitudinal_chunks(longitudinal)
|
|
# 이어지는 장은 경계 측점 하나를 나눠 갖고 끝까지 덮는다.
|
|
assert chunks[0]["start_m"] == 0.0
|
|
assert chunks[-1]["end_m"] == (count - 1) * interval
|
|
for before, after in zip(chunks, chunks[1:]):
|
|
assert before["end_m"] == after["start_m"]
|
|
|
|
|
|
def test_wide_interval_splits_more() -> None:
|
|
# 40 m 간격 30측점 = 1,160 mm > 작도영역 폭 → 30개보다 적게 담는다
|
|
chunks = longitudinal_chunks(_longitudinal(40, 40.0, 0.0))
|
|
assert len(chunks) > 2
|