fix(B07): 횡단면도 박스가 화면 덧그림(B06 설계선·구조물)까지 1 mm 로 감쌈

- 덧그림 범위를 서버가 화면과 같은 TS 로 셈 — Node 진입점 B07_DesignDetail_Cross_Extent_Node(최소 DOM 위에서 오프스크린 SVG 그리기 그대로) · 번들 build:b07-extent
- 화면 그리기·수확 부분을 B07_DesignDetail_Cross_Overlay 로 떼어 화면과 Node 가 한 벌로 씀
- 장 배치·블록 테두리가 측점별 덧그림 범위를 덮음(목록·장 열기·확정·수정 네 길 모두 같은 계획)
- 글자는 CAD 그리기대로 세로 가운데 · 폭은 글꼴 어림(한글 1.0 · 나머지 0.6 배)
- 번들 낡음 판정에 B07 맨 위 TS 포함
- 검증_sub4: 66개 박스 ↔ 그림(덧그림·글자 실폭 포함) 모두 1.0 mm · 잘림 0 · 겹침 0 · 20장 → 21장

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013rJwJMVL4EE31y77TB11AP
This commit is contained in:
2026-10-06 23:33:53 +09:00
co-authored by Claude Opus 5.5
parent 86e61bd69d
commit e4fa14564f
13 changed files with 986 additions and 464 deletions
@@ -434,11 +434,14 @@ def _section_window(
ground: list[tuple[float, float]],
design: list[tuple[float, float]],
margin_m: float = CROSS_SECTION_MARGIN_M,
overlay: tuple[float, float, float, float] | None = None,
) -> tuple[float, float]:
"""설계선이 원지반에서 갈라졌다가 다시 만나는 가로 범위(+여유)를 구한다.
B06 설계선은 절·성토 구간 바깥에서 원지반을 그대로 따라가므로, 표고가
갈라지는 구간이 곧 "그려야 할 단면"이다 (2026-08-29 사용자 기준).
overlay(오프셋 최소·최대, 표고 최소·최대 m)는 화면이 덧그리는 B06 설계선·구조물
범위다 — 범위가 그것까지 덮어야 박스가 덧그림을 자르지 않는다(68-3).
"""
left = right = None
for x, y in design:
@@ -452,6 +455,11 @@ def _section_window(
left, right = min(xs), max(xs)
# 여유는 선이 있는 데까지만 — 원지반 자료가 짧으면 빈 여유가 테두리를 밀어낸다(68-1).
drawn = [x for x, _y in ground] + [x for x, _y in design]
if overlay is not None:
drawn.extend(overlay[:2])
low = min(max(left - margin_m, min(drawn)), overlay[0])
high = max(min(right + margin_m, max(drawn)), overlay[1])
return (low, high)
if drawn:
return (max(left - margin_m, min(drawn)), min(right + margin_m, max(drawn)))
return (left - margin_m, right + margin_m)
@@ -487,6 +495,7 @@ def build_cross_drawing(
design_elevation_m: float | None = None,
frame: dict[str, float] | None = None,
origin: tuple[float, float] = (0.0, 0.0),
overlay: tuple[float, float, float, float] | None = None,
) -> dict[str, Any]:
"""횡단도 한 장을 지표/설계/구조물(+암 경계) 레이어 + CAD 수량 산출표로 만든다.
@@ -515,13 +524,15 @@ def build_cross_drawing(
)
# 그릴 가로 범위: 설계선이 원지반과 갈라지는 구간 + 여유.
x0, x1 = _section_window(raw_ground, raw_design)
x0, x1 = _section_window(raw_ground, raw_design, overlay=overlay)
ground_clipped = _clip_polyline(raw_ground, x0, x1)
# 세로 정렬: 이 범위 안의 선(지표+설계+암 경계) bbox 중심을 0으로.
# 세로 정렬: 이 범위 안의 선(지표+설계+암 경계+덧그림) bbox 중심을 0으로.
all_ys = [y for _x, y in ground_clipped] + [y for x, y in raw_design if x0 <= x <= x1]
if isinstance(rock_offset, (int, float)):
all_ys.extend(y + float(rock_offset) for _x, y in ground_clipped)
if overlay is not None:
all_ys.extend(overlay[2:])
dy = (min(all_ys) + max(all_ys)) / 2.0 if all_ys else 0.0
own_half_height = (max(all_ys) - min(all_ys)) / 2.0 if all_ys else 5.0