refactor(472 덧 관 자리): 관 세트 읽기 · 얹기를 B06_Section_Engine_Culvert_Sets.py 로 나눔 — 동작 같음 · 700줄 여유
- load_culvert_sets · culvert_sets_from · attach_culvert_sets · attach_culvert_specs + 얹기 상수 셋 옮김(700 → 576) - 부르는 쪽(Engine_Attach · Engine_Tilt · Router_Design_Ranges) · 시험 import 만 새 자리로 - test_b06_pipe_length 소스 읽기 = 새 파일 · 위키 B06_backend 자리 고침 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,11 +15,8 @@ from typing import Any
|
||||
|
||||
from B05_Profile.B05_Profile_Structures_Repository import load_structures
|
||||
from B05_Profile.B05_Profile_Structures_Schema import structure_type_map
|
||||
from B06_Section.B06_Section_Engine_Culvert import (
|
||||
attach_culvert_specs,
|
||||
culvert_sets_from,
|
||||
pipe_points_file,
|
||||
)
|
||||
from B06_Section.B06_Section_Engine_Culvert import pipe_points_file
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import attach_culvert_specs, culvert_sets_from
|
||||
from B06_Section.B06_Section_Engine_Structures_Wall import attach_wall_specs, wall_specs_from
|
||||
from B06_Section.B06_Section_Engine_Tilt import attach_underdrain_specs, underdrains_from
|
||||
from common_util.common_util_drainage_pipes import read_pipe_points_file
|
||||
|
||||
@@ -7,6 +7,7 @@ B05 배수유역도가 찍은 관 지점(`pipe_points.json` = 배관 정본)을
|
||||
⚠ TS 짝: `common_util/common_util_culvert_sets.ts` (2026-09-06). 한쪽만 고치면 화면과
|
||||
저장본이 갈린다 — 거울 테스트 `tmp/tests/test_b06_culvert_sets_mirror.py` 로 지킨다.
|
||||
매 상세 조회마다 도는 자리라 Node 왕복 대신 짝을 골랐다(CLAUDE.md 5장 「계산 자리」 ①).
|
||||
관 지점 읽기 · 측점에 얹기 = `B06_Section_Engine_Culvert_Sets.py`(472 덧 나눔).
|
||||
|
||||
근거(지식DB):
|
||||
· 관은 **지반선상 매설** — 뜨게 매설은 부적합 (교본 8장, 그림 8-3·8-9)
|
||||
@@ -21,7 +22,6 @@ B05 배수유역도가 찍은 관 지점(`pipe_points.json` = 배관 정본)을
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
import math
|
||||
import re
|
||||
@@ -29,9 +29,6 @@ from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from B05_Profile.B05_Profile_Structures_Schema import structure_type_map
|
||||
from common_util.common_util_drainage_pipes import parse_pipe_points
|
||||
from common_util.common_util_structure_catalog import catalog_row
|
||||
from common_util.common_util_structure_station import EDGE_TOLERANCE_M, PIPE_MATCH_M
|
||||
from config.config_system import (
|
||||
DRAINAGE_CACHE_DIRNAME,
|
||||
DRAINAGE_EDITS_DIRNAME,
|
||||
@@ -40,21 +37,6 @@ from config.config_system import (
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 관 지점과 횡단 측점을 같은 자리로 볼 허용 오차(m) — 같은 자리 거리 한 곳(323-7)
|
||||
_CHAINAGE_TOLERANCE_M = EDGE_TOLERANCE_M
|
||||
|
||||
# 세트 종류 -> 횡단 dict 키. 그림이 다른 시설끼리 소비처가 섞이지 않게 나눠 둔다.
|
||||
_SECTION_KEYS = {"ford": "ford", "box": "box", "ford_pavement": "ford_pavement"}
|
||||
|
||||
# 구조물 종류별 **인접 측점 연동**(2026-08-25 사용자 확정). 이름을 넣으면 도로 방향
|
||||
# 폭(`span_m`)의 절반만큼 앞뒤 측점에도 같은 스펙이 붙어 횡단도가 한 벌 더 그려진다.
|
||||
# 세월교·BOX암거는 끔 — 소유 측점 한 곳에만 선다. 3D는 그 측점에서 `span_m` 전체를
|
||||
# 스윕하므로 길이가 줄지 않는다(인접 측점 기준으로 자르지 않는다).
|
||||
# 물넘이포장만 켠다 — 노면을 월류 폭만큼 파는 시설이라 **범위 안 모든 횡단도**에
|
||||
# 파임이 그려져야 한다(2026-08-28 사용자 확정).
|
||||
# ※ 기슭막이 연동은 이 경로가 아니다 — 프론트 `culvertOwnerFor`가 따로 판정한다.
|
||||
_SPAN_LINKED_TYPES: frozenset[str] = frozenset({"ford_pavement"})
|
||||
|
||||
# ⚠ 교차 참조 ① 관 위 최소 토피(m). 임도 배수관 토피 규정이 지식DB에 없어 별표2
|
||||
# 교량·암거 "복토 시 흙 두께 50㎝ 이상"을 끌어왔다. B05 계획고 하향 차단 기준이다.
|
||||
MIN_PIPE_COVER_M = 0.5
|
||||
@@ -589,112 +571,3 @@ def _box_set(options: dict[str, Any] | None) -> dict[str, Any]:
|
||||
def box_body_height(box: dict[str, Any]) -> float:
|
||||
"""박스 본체 전체 높이(상판 + 내공 + 저판) — 흙막이 세트의 관경 자리(73-4)."""
|
||||
return round(box["top_thickness_m"] + box["inner_height_m"] + box["slab_thickness_m"], 3)
|
||||
|
||||
|
||||
def load_culvert_sets(project_root: Path) -> dict[float, dict[str, Any]]:
|
||||
"""관 지점 정본을 읽어 누가거리별 세트 제원을 돌려준다.
|
||||
|
||||
노선 지문은 보지 않는다 — 횡단면 자체가 현 노선에서 만들어진 것이라, 지문이
|
||||
어긋난 옛 관 지점은 매칭될 측점이 없어 자연히 걸러진다. 파일이 없거나 깨졌으면 빈 값.
|
||||
"""
|
||||
path = pipe_points_file(project_root)
|
||||
if not path.is_file():
|
||||
return {}
|
||||
try:
|
||||
document = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError):
|
||||
logger.warning("B06 배수관 세트: 관 지점 파일을 읽지 못했습니다 (%s)", path)
|
||||
return {}
|
||||
return culvert_sets_from(parse_pipe_points(document.get("points")))
|
||||
|
||||
|
||||
def culvert_sets_from(points: list[Any]) -> dict[float, dict[str, Any]]:
|
||||
"""관 지점 목록 → 누가거리(소수 2자리)별 세트 제원(TS `buildCulvertSets` 짝 · 형상 얹기 한 벌 323-4)."""
|
||||
sets: dict[float, dict[str, Any]] = {}
|
||||
for point in points:
|
||||
# 그릴 세트 = 구조물 표 형상(322-1 · TS `buildCulvertSets` 짝)
|
||||
shape = (catalog_row(point.facility) or {}).get("shape")
|
||||
if shape == "pipe_set":
|
||||
if (point.options or {}).get("pipe_diameter_mm") in (None, ""):
|
||||
continue # 관경 안 고름 = 관 없음(54-39)
|
||||
spec = _culvert_set(point.options)
|
||||
elif shape == "ford":
|
||||
spec = _ford_set(point.options)
|
||||
elif shape == "box":
|
||||
spec = _box_set(point.options)
|
||||
elif shape == "ford_pavement":
|
||||
# 구조물이 아니라 파인 노면이다 — 스펙 모양도 소비처도 다르다(2026-08-28).
|
||||
spec = _ford_pavement_set(point.options)
|
||||
elif shape == "hidden_revet":
|
||||
# 독립 기슭막이 — 배관 세트 모양이되 관을 숨긴다. `culvert` 키로 얹혀 배관
|
||||
# 경로(컴퓨트·렌더·패널·연동·경사·3D·수량)를 그대로 탄다.
|
||||
spec = _revet_set(point.options)
|
||||
else:
|
||||
continue
|
||||
sets[round(float(point.chainage_m), 2)] = spec
|
||||
return sets
|
||||
|
||||
|
||||
def attach_culvert_sets(project_root: Path, cross_sections: list[dict[str, Any]]) -> int:
|
||||
"""배관이 놓인 측점의 횡단 dict에 `culvert` 키를 얹는다. 얹은 개수를 돌려준다."""
|
||||
return attach_culvert_specs(cross_sections, load_culvert_sets(project_root))
|
||||
|
||||
|
||||
def attach_culvert_specs(
|
||||
cross_sections: list[dict[str, Any]],
|
||||
sets: dict[float, dict[str, Any]],
|
||||
missed: list[float] | None = None,
|
||||
) -> int:
|
||||
"""세트를 측점에 얹음(TS `attachCulvertSets` 짝) · 얹은 수 · 주인 먼 세트 = `missed`."""
|
||||
if not sets:
|
||||
return 0
|
||||
attached = 0
|
||||
# 주인 측점 = 가장 가까운 측점 하나(`PIPE_MATCH_M` 안 · 정수 m 측점 위 소수 관도) ·
|
||||
# 더 멀면 그 시설 측점이 없음(노선 바뀜) — 연동 이웃에도 안 얹음.
|
||||
owner: dict[float, float] = {}
|
||||
for pipe_chainage in sets:
|
||||
nearest = None
|
||||
for section in cross_sections:
|
||||
value = _number(section.get("chainage_m"), None)
|
||||
if value is None:
|
||||
continue
|
||||
if nearest is None or abs(value - pipe_chainage) < abs(nearest - pipe_chainage):
|
||||
nearest = value
|
||||
if nearest is not None and abs(nearest - pipe_chainage) < PIPE_MATCH_M:
|
||||
owner[pipe_chainage] = nearest
|
||||
elif missed is not None:
|
||||
missed.append(pipe_chainage)
|
||||
for section in cross_sections:
|
||||
chainage = _number(section.get("chainage_m"), None)
|
||||
if chainage is None:
|
||||
continue
|
||||
# ⚠ 키가 다른 시설은 같은 측점에 함께 얹는다(299-1) — 첫 시설 하나에서 멈추면 물넘이포장
|
||||
# 연동 범위(폭 절반) 안 측점의 **자기 관**이 빠졌다(95 m 배관이 90 m 물넘이에 가려짐).
|
||||
# 같은 키끼리는 소유 측점 것 → 흙막이 아닌 자기 시설 → 가까운 것 → 관 지점 차례.
|
||||
best: dict[str, tuple[tuple[Any, ...], dict[str, Any]]] = {}
|
||||
for order, (pipe_chainage, spec) in enumerate(sets.items()):
|
||||
if pipe_chainage not in owner:
|
||||
continue
|
||||
# 연동 대상 종류만 폭의 절반까지 옆 측점에 걸친다(`_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
|
||||
owned = owner.get(pipe_chainage) == chainage
|
||||
if not (abs(chainage - pipe_chainage) <= reach or owned):
|
||||
continue
|
||||
# 세월교·BOX암거·물넘이는 배수관과 그림이 달라 키를 나눈다 — 소비처가 섞이지 않는다.
|
||||
entries = [(_SECTION_KEYS.get(str(spec.get("type")), "culvert"), spec, False)]
|
||||
# 세월교 · 박스 흙막이(73-4) — 배관 흙막이와 같은 자리(`culvert`)에 함께 얹음 ·
|
||||
# 자기 관과 부딪히면 관 먼저(흙막이가 덮으면 관 그림 · 연장이 빠짐).
|
||||
if spec.get("guard"):
|
||||
entries.append(("culvert", spec["guard"], True))
|
||||
for key, value, is_guard in entries:
|
||||
rank = (not owned, is_guard, abs(chainage - pipe_chainage), order)
|
||||
if key not in best or rank < best[key][0]:
|
||||
# ⚠ 스펙에 **그 시설이 놓인 누가거리**를 함께 얹음 — 없으면 소비처가 소유 측점을
|
||||
# 못 가려 **같은 시설을 여러 측점에서 셈**(폭 절반 연동 · 관 9개에 길이 10곳).
|
||||
best[key] = (rank, {**value, "chainage_m": pipe_chainage})
|
||||
for key, (_, value) in best.items():
|
||||
section[key] = value
|
||||
attached += bool(best)
|
||||
return attached
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
"""B06 관 세트 읽기 · 측점에 얹기 — `B06_Section_Engine_Culvert.py` 에서 나눔(472 덧 · 동작 같음).
|
||||
|
||||
관 지점 정본(`pipe_points.json`) → 누가거리별 세트 제원(`culvert_sets_from`) → 횡단 dict 에
|
||||
`culvert` · `ford` · `box` · `ford_pavement` 키로 얹는다(`attach_culvert_specs`). 세트 제원 만들기
|
||||
(`_culvert_set` 등)는 `B06_Section_Engine_Culvert.py`.
|
||||
|
||||
⚠ TS 짝: `common_util/common_util_culvert_sets.ts` `buildCulvertSets` · `attachCulvertSets` —
|
||||
거울 시험 `resources/tester/test_b06_culvert_sets_mirror.py`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from B06_Section.B06_Section_Engine_Culvert import (
|
||||
_box_set,
|
||||
_culvert_set,
|
||||
_ford_pavement_set,
|
||||
_ford_set,
|
||||
_number,
|
||||
_revet_set,
|
||||
pipe_points_file,
|
||||
)
|
||||
from common_util.common_util_drainage_pipes import parse_pipe_points
|
||||
from common_util.common_util_structure_catalog import catalog_row
|
||||
from common_util.common_util_structure_station import EDGE_TOLERANCE_M, PIPE_MATCH_M
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 관 지점과 횡단 측점을 같은 자리로 볼 허용 오차(m) — 같은 자리 거리 한 곳(323-7)
|
||||
_CHAINAGE_TOLERANCE_M = EDGE_TOLERANCE_M
|
||||
|
||||
# 세트 종류 -> 횡단 dict 키. 그림이 다른 시설끼리 소비처가 섞이지 않게 나눠 둔다.
|
||||
_SECTION_KEYS = {"ford": "ford", "box": "box", "ford_pavement": "ford_pavement"}
|
||||
|
||||
# 구조물 종류별 **인접 측점 연동**(2026-08-25 사용자 확정). 이름을 넣으면 도로 방향
|
||||
# 폭(`span_m`)의 절반만큼 앞뒤 측점에도 같은 스펙이 붙어 횡단도가 한 벌 더 그려진다.
|
||||
# 세월교·BOX암거는 끔 — 소유 측점 한 곳에만 선다. 3D는 그 측점에서 `span_m` 전체를
|
||||
# 스윕하므로 길이가 줄지 않는다(인접 측점 기준으로 자르지 않는다).
|
||||
# 물넘이포장만 켠다 — 노면을 월류 폭만큼 파는 시설이라 **범위 안 모든 횡단도**에
|
||||
# 파임이 그려져야 한다(2026-08-28 사용자 확정).
|
||||
# ※ 기슭막이 연동은 이 경로가 아니다 — 프론트 `culvertOwnerFor`가 따로 판정한다.
|
||||
_SPAN_LINKED_TYPES: frozenset[str] = frozenset({"ford_pavement"})
|
||||
|
||||
|
||||
def load_culvert_sets(project_root: Path) -> dict[float, dict[str, Any]]:
|
||||
"""관 지점 정본을 읽어 누가거리별 세트 제원을 돌려준다.
|
||||
|
||||
노선 지문은 보지 않는다 — 횡단면 자체가 현 노선에서 만들어진 것이라, 지문이
|
||||
어긋난 옛 관 지점은 매칭될 측점이 없어 자연히 걸러진다. 파일이 없거나 깨졌으면 빈 값.
|
||||
"""
|
||||
path = pipe_points_file(project_root)
|
||||
if not path.is_file():
|
||||
return {}
|
||||
try:
|
||||
document = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError):
|
||||
logger.warning("B06 배수관 세트: 관 지점 파일을 읽지 못했습니다 (%s)", path)
|
||||
return {}
|
||||
return culvert_sets_from(parse_pipe_points(document.get("points")))
|
||||
|
||||
|
||||
def culvert_sets_from(points: list[Any]) -> dict[float, dict[str, Any]]:
|
||||
"""관 지점 목록 → 누가거리(소수 2자리)별 세트 제원(TS `buildCulvertSets` 짝 · 형상 얹기 한 벌 323-4)."""
|
||||
sets: dict[float, dict[str, Any]] = {}
|
||||
for point in points:
|
||||
# 그릴 세트 = 구조물 표 형상(322-1 · TS `buildCulvertSets` 짝)
|
||||
shape = (catalog_row(point.facility) or {}).get("shape")
|
||||
if shape == "pipe_set":
|
||||
if (point.options or {}).get("pipe_diameter_mm") in (None, ""):
|
||||
continue # 관경 안 고름 = 관 없음(54-39)
|
||||
spec = _culvert_set(point.options)
|
||||
elif shape == "ford":
|
||||
spec = _ford_set(point.options)
|
||||
elif shape == "box":
|
||||
spec = _box_set(point.options)
|
||||
elif shape == "ford_pavement":
|
||||
# 구조물이 아니라 파인 노면이다 — 스펙 모양도 소비처도 다르다(2026-08-28).
|
||||
spec = _ford_pavement_set(point.options)
|
||||
elif shape == "hidden_revet":
|
||||
# 독립 기슭막이 — 배관 세트 모양이되 관을 숨긴다. `culvert` 키로 얹혀 배관
|
||||
# 경로(컴퓨트·렌더·패널·연동·경사·3D·수량)를 그대로 탄다.
|
||||
spec = _revet_set(point.options)
|
||||
else:
|
||||
continue
|
||||
sets[round(float(point.chainage_m), 2)] = spec
|
||||
return sets
|
||||
|
||||
|
||||
def attach_culvert_sets(project_root: Path, cross_sections: list[dict[str, Any]]) -> int:
|
||||
"""배관이 놓인 측점의 횡단 dict에 `culvert` 키를 얹는다. 얹은 개수를 돌려준다."""
|
||||
return attach_culvert_specs(cross_sections, load_culvert_sets(project_root))
|
||||
|
||||
|
||||
def attach_culvert_specs(
|
||||
cross_sections: list[dict[str, Any]],
|
||||
sets: dict[float, dict[str, Any]],
|
||||
missed: list[float] | None = None,
|
||||
) -> int:
|
||||
"""세트를 측점에 얹음(TS `attachCulvertSets` 짝) · 얹은 수 · 주인 먼 세트 = `missed`."""
|
||||
if not sets:
|
||||
return 0
|
||||
attached = 0
|
||||
# 주인 측점 = 가장 가까운 측점 하나(`PIPE_MATCH_M` 안 · 정수 m 측점 위 소수 관도) ·
|
||||
# 더 멀면 그 시설 측점이 없음(노선 바뀜) — 연동 이웃에도 안 얹음.
|
||||
owner: dict[float, float] = {}
|
||||
for pipe_chainage in sets:
|
||||
nearest = None
|
||||
for section in cross_sections:
|
||||
value = _number(section.get("chainage_m"), None)
|
||||
if value is None:
|
||||
continue
|
||||
if nearest is None or abs(value - pipe_chainage) < abs(nearest - pipe_chainage):
|
||||
nearest = value
|
||||
if nearest is not None and abs(nearest - pipe_chainage) < PIPE_MATCH_M:
|
||||
owner[pipe_chainage] = nearest
|
||||
elif missed is not None:
|
||||
missed.append(pipe_chainage)
|
||||
for section in cross_sections:
|
||||
chainage = _number(section.get("chainage_m"), None)
|
||||
if chainage is None:
|
||||
continue
|
||||
# ⚠ 키가 다른 시설은 같은 측점에 함께 얹는다(299-1) — 첫 시설 하나에서 멈추면 물넘이포장
|
||||
# 연동 범위(폭 절반) 안 측점의 **자기 관**이 빠졌다(95 m 배관이 90 m 물넘이에 가려짐).
|
||||
# 같은 키끼리는 소유 측점 것 → 흙막이 아닌 자기 시설 → 가까운 것 → 관 지점 차례.
|
||||
best: dict[str, tuple[tuple[Any, ...], dict[str, Any]]] = {}
|
||||
for order, (pipe_chainage, spec) in enumerate(sets.items()):
|
||||
if pipe_chainage not in owner:
|
||||
continue
|
||||
# 연동 대상 종류만 폭의 절반까지 옆 측점에 걸친다(`_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
|
||||
owned = owner.get(pipe_chainage) == chainage
|
||||
if not (abs(chainage - pipe_chainage) <= reach or owned):
|
||||
continue
|
||||
# 세월교·BOX암거·물넘이는 배수관과 그림이 달라 키를 나눈다 — 소비처가 섞이지 않는다.
|
||||
entries = [(_SECTION_KEYS.get(str(spec.get("type")), "culvert"), spec, False)]
|
||||
# 세월교 · 박스 흙막이(73-4) — 배관 흙막이와 같은 자리(`culvert`)에 함께 얹음 ·
|
||||
# 자기 관과 부딪히면 관 먼저(흙막이가 덮으면 관 그림 · 연장이 빠짐).
|
||||
if spec.get("guard"):
|
||||
entries.append(("culvert", spec["guard"], True))
|
||||
for key, value, is_guard in entries:
|
||||
rank = (not owned, is_guard, abs(chainage - pipe_chainage), order)
|
||||
if key not in best or rank < best[key][0]:
|
||||
# ⚠ 스펙에 **그 시설이 놓인 누가거리**를 함께 얹음 — 없으면 소비처가 소유 측점을
|
||||
# 못 가려 **같은 시설을 여러 측점에서 셈**(폭 절반 연동 · 관 9개에 길이 10곳).
|
||||
best[key] = (rank, {**value, "chainage_m": pipe_chainage})
|
||||
for key, (_, value) in best.items():
|
||||
section[key] = value
|
||||
attached += bool(best)
|
||||
return attached
|
||||
@@ -18,7 +18,7 @@ from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from B05_Profile.B05_Profile_Structures_Repository import load_structures
|
||||
from B06_Section.B06_Section_Engine_Culvert import load_culvert_sets
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import load_culvert_sets
|
||||
from common_util.common_util_structure_catalog import catalog_row
|
||||
from common_util.common_util_structure_station import EDGE_TOLERANCE_M
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from typing import Any
|
||||
|
||||
from B05_Profile.B05_Profile_Structures_Repository import load_structures
|
||||
from B05_Profile.B05_Profile_Structures_Schema import structure_type_map
|
||||
from B06_Section.B06_Section_Engine_Culvert import load_culvert_sets
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import load_culvert_sets
|
||||
from common_util.common_util_structure_station import EDGE_TOLERANCE_M
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* common_util_culvert_sets.ts
|
||||
* 배수관 세트(배관·기슭막이·보호공·세월교·BOX암거·물넘이포장) 제원 — **브라우저 몫**.
|
||||
*
|
||||
* ⚠ 파이썬 `B06_Section/B06_Section_Engine_Culvert.py` 와 **한 벌**이다(2026-09-06).
|
||||
* ⚠ 파이썬 `B06_Section/B06_Section_Engine_Culvert.py` · `_Culvert_Sets.py`(읽기 · 얹기) 와 **한 벌**이다(2026-09-06).
|
||||
* 한쪽만 고치면 화면과 저장본이 갈린다. 거울 테스트: `resources/tester/test_b06_culvert_sets_mirror.py`
|
||||
*
|
||||
* 왜 짝으로 두나(CLAUDE.md 5장 「계산 자리」) — 이 계산은 종횡단 **상세를 읽을 때마다**
|
||||
|
||||
@@ -27,8 +27,8 @@ source: ["docs/raw/verification/2026-07-19_verify_B05_B06_UI_Station_Improvement
|
||||
| `compute_cross_design()` | `B06_Section_Engine_Design.py` | **[2단계 경사 & N-2-4 연동]** 측점별 표준단면 절/성토 단면적 및 기하선 연산 엔진 (리핑암/발파암 2단계 절토 경사, 단면유형 자동 판정, `ditch_enabled` 토글) |
|
||||
| `_split_cut_areas()` | `[[B06_Section/backend/B06_Section_Engine_Areas]]` | **[신설/2026-08-02]** 700줄 충족을 위해 분리된 암 경계선 기준 절토면적 토사/암반 정밀 적분 연산 |
|
||||
| `design_elevation_from_longitudinal()` | `B06_Section_Engine_Design.py` | 종단 계획선 계획고 선형보간 계산 헬퍼 |
|
||||
| `attach_culvert_sets()` | `B06_Section_Engine_Culvert.py` | 구조물 세트를 상세 횡단 dict에 결합; BOX암거·세월교는 소유 측점만 사용 |
|
||||
| `_SPAN_LINKED_TYPES` | `B06_Section_Engine_Culvert.py` | 인접 측점 연동 타입 집합; 현재 비어 있으며 기슭막이는 별도 프론트 경로 사용 |
|
||||
| `attach_culvert_sets()` | `B06_Section_Engine_Culvert_Sets.py` | 구조물 세트를 상세 횡단 dict에 결합; BOX암거·세월교는 소유 측점만 사용 |
|
||||
| `_SPAN_LINKED_TYPES` | `B06_Section_Engine_Culvert_Sets.py` | 인접 측점 연동 타입 집합; 현재 비어 있으며 기슭막이는 별도 프론트 경로 사용 |
|
||||
| *종횡단 생성 엔진* | `B05_Profile_Engine_Sections.py` 등 | 기존 B06 종횡단 생성 엔진 파일 3종은 **B05 노선 설계 최적화 시점에 실시간 통합 계산**하도록 B05로 이관되었습니다. |
|
||||
|
||||
## 라우터·workflow (조회, 확정, 타 프로젝트 불러오기 및 재생성)
|
||||
|
||||
@@ -72,7 +72,7 @@ def main() -> int:
|
||||
print(f"3) cross_*.json 파일={len(files)}개 구조물 표식={len(with_structure)}건 {with_structure}")
|
||||
|
||||
# 4) B06 읽기 경로 — 실제로 세트가 붙는가
|
||||
from B06_Section.B06_Section_Engine_Culvert import load_culvert_sets
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import load_culvert_sets
|
||||
|
||||
sets = load_culvert_sets(project)
|
||||
print(f"4) load_culvert_sets 세트={len(sets)}건")
|
||||
|
||||
@@ -26,7 +26,8 @@ for path in (ROOT, Path(__file__).resolve().parent):
|
||||
sys.path.insert(0, str(path))
|
||||
|
||||
import test_b06_culvert_sets_mirror as mirror # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert import attach_culvert_sets, pipe_points_file # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert import pipe_points_file # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import attach_culvert_sets # noqa: E402
|
||||
|
||||
# 검증 프로젝트 꼴 — 20 · 90 물넘이(폭 10) · 95 배관(도수로) · 100 배관 + 100.3 박스(유출 흙막이) · 60 세월교(흙막이)
|
||||
POINTS = [
|
||||
|
||||
@@ -24,7 +24,8 @@ import pytest
|
||||
from B05_Profile.B05_Profile_Engine_Sections import relabel_pipe_stations, resolve_extra_stations
|
||||
from B05_Profile.B05_Profile_Structures_Repository import structures_file_path
|
||||
from B05_Profile.B05_Profile_Structures_Schema import load_definition
|
||||
from B06_Section.B06_Section_Engine_Culvert import attach_culvert_sets, pipe_points_file
|
||||
from B06_Section.B06_Section_Engine_Culvert import pipe_points_file
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import attach_culvert_sets
|
||||
from B06_Section.B06_Section_Engine_Structures_Wall import attach_wall_structures
|
||||
from B06_Section.B06_Section_Engine_Tilt import attach_underdrains
|
||||
from common_util.common_util_drainage_pipes import parse_pipe_points
|
||||
|
||||
@@ -28,7 +28,7 @@ import B06_Section.B06_Section_Engine_Tilt as tilt_mod # noqa: E402
|
||||
import B06_Section.B06_Section_Router_Design as design_mod # noqa: E402
|
||||
import B06_Section.B06_Section_Router_Design_Ranges as ranges_mod # noqa: E402
|
||||
from B05_Profile.B05_Profile_Structures_Schema import StructureInstance # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert import culvert_sets_from # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import culvert_sets_from # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Design import compute_cross_design # noqa: E402
|
||||
from common_util.common_util_drainage_pipes import parse_pipe_points # noqa: E402
|
||||
from config.config_system_design import STANDARD_CROSS_SECTION # noqa: E402
|
||||
|
||||
@@ -29,7 +29,7 @@ import B06_Section.B06_Section_Engine_Tilt as tilt_mod # noqa: E402
|
||||
import B06_Section.B06_Section_Router_Design as design_mod # noqa: E402
|
||||
import B06_Section.B06_Section_Router_Design_Ranges as ranges_mod # noqa: E402
|
||||
from B05_Profile.B05_Profile_Structures_Schema import StructureInstance # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert import culvert_sets_from # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import culvert_sets_from # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Design import compute_cross_design # noqa: E402
|
||||
from common_util.common_util_drainage_pipes import parse_pipe_points # noqa: E402
|
||||
from config.config_system_design import ( # noqa: E402
|
||||
|
||||
@@ -20,8 +20,8 @@ if str(ROOT) not in sys.path:
|
||||
from B06_Section.B06_Section_Engine_Culvert import ( # noqa: E402
|
||||
BOX_COVER_M,
|
||||
_box_set,
|
||||
attach_culvert_sets,
|
||||
)
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import attach_culvert_sets # noqa: E402
|
||||
|
||||
|
||||
def test_box_set_defaults() -> None:
|
||||
|
||||
@@ -17,9 +17,9 @@ from B06_Section.B06_Section_Engine_Culvert import ( # noqa: E402
|
||||
MIN_PIPE_COVER_M,
|
||||
REVET_FACE_SLOPE,
|
||||
_culvert_set,
|
||||
attach_culvert_sets,
|
||||
pipe_points_file,
|
||||
)
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import attach_culvert_sets # noqa: E402
|
||||
|
||||
|
||||
def test_cross_reference_constants_match_plan():
|
||||
|
||||
@@ -19,10 +19,8 @@ if str(PROJECT_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(PROJECT_ROOT))
|
||||
|
||||
from B05_Profile.B05_Profile_Structures_Schema import structure_type_map # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert import ( # noqa: E402
|
||||
attach_culvert_sets,
|
||||
pipe_points_file,
|
||||
)
|
||||
from B06_Section.B06_Section_Engine_Culvert import pipe_points_file # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import attach_culvert_sets # noqa: E402
|
||||
|
||||
TSC = PROJECT_ROOT / "config" / "node_modules" / "typescript" / "bin" / "tsc"
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ from B06_Section.B06_Section_Engine_Culvert import ( # noqa: E402
|
||||
FORD_SLAB_THICKNESS_M,
|
||||
FORD_WALL_THICKNESS_M,
|
||||
_ford_set,
|
||||
attach_culvert_sets,
|
||||
)
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import attach_culvert_sets # noqa: E402
|
||||
|
||||
|
||||
def test_ford_set_defaults() -> None:
|
||||
|
||||
@@ -9,11 +9,8 @@
|
||||
import json
|
||||
import math
|
||||
|
||||
from B06_Section.B06_Section_Engine_Culvert import (
|
||||
FORD_PAVEMENT_DEFAULT_WIDTH_M,
|
||||
attach_culvert_sets,
|
||||
load_culvert_sets,
|
||||
)
|
||||
from B06_Section.B06_Section_Engine_Culvert import FORD_PAVEMENT_DEFAULT_WIDTH_M
|
||||
from B06_Section.B06_Section_Engine_Culvert_Sets import attach_culvert_sets, load_culvert_sets
|
||||
from B06_Section.B06_Section_Router_Design import paved_at, pavement_ranges
|
||||
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ def test_소유_측점에만_싣는다():
|
||||
layouts = _LAYOUTS.read_text(encoding="utf-8")
|
||||
assert "ownerChainage" in layouts, "소유 측점을 안 가리고 있다"
|
||||
assert "isOwner(section.culvert.chainage_m)" in layouts, "관이 놓인 자리를 안 읽고 있다"
|
||||
py = (PROJECT_ROOT / "B06_Section" / "B06_Section_Engine_Culvert.py").read_text(
|
||||
py = (PROJECT_ROOT / "B06_Section" / "B06_Section_Engine_Culvert_Sets.py").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
ts = (PROJECT_ROOT / "common_util" / "common_util_culvert_sets.ts").read_text(encoding="utf-8")
|
||||
|
||||
Reference in New Issue
Block a user