fix(B06): BOX암거·세월교를 소유 측점 횡단도 한 장에만 그림

attach_culvert_sets()가 도로 방향 폭(span_m)의 절반을 reach로 잡아 소유 측점
전후 측점에도 같은 스펙을 붙였다. BOX암거는 폭 2.4m라 0.92m 떨어진 옆 측점까지
걸려 횡단도가 한 벌 더 그려졌고, 같은 값을 읽는 3D도 박스 솔리드를 어긋난 채
두 벌 만들었다.

구조물 종류별 연동 표(_SPAN_LINKED_TYPES)를 두고 reach를 분기한다. 지금은 빈
집합이라 세월교·BOX암거 모두 소유 측점 한 곳에만 선다. 3D 스윕 길이는 소유
측점이 span_m으로 직접 내므로 줄지 않는다.

기슭막이 연동은 프론트 culvertOwnerFor 별도 경로라 그대로 살아 있고, 집수정은
이미 링크 카드에서 빠져 있다.

검증(프로젝트 c1bb453f route 85): pytest 208 passed. 횡단도 200.0m 카드에서
box-barrel 사라지고 200.92m에만 남음. 3D 솔리드 42 -> 32, 200.0m 10 -> 0,
200.92m 10 유지, span_m 2.4 불변.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 17:41:40 +09:00
co-authored by Claude Opus 5
parent 6e87dd6cdf
commit 07fb2ccf46
+11 -2
View File
@@ -42,6 +42,13 @@ logger = logging.getLogger(__name__)
# 관 지점과 횡단 측점을 같은 자리로 볼 허용 오차(m). 정본이 누가거리를 0.01m로 끊어 쓴다.
_CHAINAGE_TOLERANCE_M = 0.02
# 구조물 종류별 **인접 측점 연동**(2026-08-25 사용자 확정). 이름을 넣으면 도로 방향
# 폭(`span_m`)의 절반만큼 앞뒤 측점에도 같은 스펙이 붙어 횡단도가 한 벌 더 그려진다.
# 지금은 전부 끔 — 세월교·BOX암거 모두 소유 측점 한 곳에만 선다. 3D는 그 측점에서
# `span_m` 전체를 스윕하므로 길이가 줄지 않는다(인접 측점 기준으로 자르지 않는다).
# ※ 기슭막이 연동은 이 경로가 아니다 — 프론트 `culvertOwnerFor`가 따로 판정한다.
_SPAN_LINKED_TYPES: frozenset[str] = frozenset()
# ⚠ 교차 참조 ① 관 위 최소 토피(m). 임도 배수관 토피 규정이 지식DB에 없어 별표2
# 교량·암거 "복토 시 흙 두께 50㎝ 이상"을 끌어왔다. B05 계획고 하향 차단 기준이다.
MIN_PIPE_COVER_M = 0.5
@@ -322,8 +329,10 @@ def attach_culvert_sets(project_root: Path, cross_sections: list[dict[str, Any]]
if chainage is None:
continue
for pipe_chainage, spec in sets.items():
# 세월교 구체·BOX암거는 폭만큼 이어지므로 기준 측점 전후 절반까지 같은 단면이다.
reach = _CHAINAGE_TOLERANCE_M + (_number(spec.get("span_m"), 0.0) or 0.0) / 2
# 연동 대상 종류만 폭의 절반까지 옆 측점에 걸친다(`_SPAN_LINKED_TYPES`).
reach = _CHAINAGE_TOLERANCE_M
if spec.get("type") in _SPAN_LINKED_TYPES:
reach += (_number(spec.get("span_m"), 0.0) or 0.0) / 2
if abs(chainage - pipe_chainage) <= reach:
# 세월교·BOX암거는 배수관과 그림이 달라 키를 나눈다 — 소비처가 섞이지 않는다.
kind = spec.get("type")