fix(472 덧 관 자리): 관 파일 누가거리를 그대로 읽던 남은 서버 자리 = 지금 노선에 얹은 관 자리(route_pipe_points 한 벌)
- 옛 노선 지문 관 파일(옛 누가거리 394 · 좌표 351) — 측점 계획 · 관 지점 GET · 화면 · 상세 얹기는 351 인데 세월교 노면 하강(ford_surface_drops) · 물넘이포장 구간(ford_pavement_ranges · tilt_ranges) · 카드 이름 (relabel_pipe_stations) · B07 관 글 재료(load_note_sources) · 옛 비정규 측점 이관 심는 자리만 394 로 읽음 → [저장] 재계산 · [확정] · 상세 값이 화면과 갈림 - B05_Profile_Engine_Sections.route_pipe_points — 관 지점 정본을 지금 노선에 얹어 읽음(_load_pipe_points 이월) · 노선 경로 안 줌 = 노선 파일 하나(ROUTE_DATA_FILE · 노선 풀기도 같은 이름을 씀) · 노선 못 읽으면 저장분 그대로 - load_culvert_sets · attach_saved_shapes(saved_pipes 걷음) · relabel_pipe_stations(상세 GET 은 노선 경로 넘김) · B07 load_note_sources · Structures_Router 이관 심는 자리 = 이 한 벌 - 시험 test_472_d_route_pipe_readers(옛 코드 빨강 2) · test_472_d_pipe_route_attach 「노선 모름 = 파일 누가거리」 단언은 옛 동작이라 「노선 파일 하나 = 351」로 고침 · 위키 rules · calculations 줄 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ from typing import Any
|
||||
|
||||
from B05_Profile.B05_Profile_Debug import log_b05_debug
|
||||
from B05_Profile.B05_Profile_Engine_RidgeValley import solve_ridge_valley_route
|
||||
from B05_Profile.B05_Profile_Engine_Sections import ROUTE_DATA_FILE
|
||||
from B05_Profile.B05_Profile_Engine_Solver import solve_optimal_route
|
||||
from common_util.common_util_json import atomic_write_json
|
||||
|
||||
@@ -142,7 +143,7 @@ def run_route_design(
|
||||
|
||||
route_dir = project_root / _ROUTE_SUBDIR
|
||||
route_dir.mkdir(parents=True, exist_ok=True)
|
||||
geojson_path = route_dir / "route_main.geojson"
|
||||
geojson_path = project_root / ROUTE_DATA_FILE
|
||||
atomic_write_json(geojson_path, _route_geojson(polyline))
|
||||
log_b05_debug(
|
||||
logger,
|
||||
|
||||
@@ -30,8 +30,9 @@ from B05_Profile.B05_Profile_Structures_Schema import (
|
||||
from common_util.common_util_drainage_pipes import (
|
||||
PipePoint,
|
||||
load_pipe_points_file,
|
||||
parse_pipe_points,
|
||||
pipe_anchor_clearances,
|
||||
pipe_points_path_in,
|
||||
read_pipe_points_file,
|
||||
route_signature,
|
||||
)
|
||||
from common_util.common_util_json import atomic_write_json
|
||||
@@ -54,6 +55,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
_STAGE_SUBDIR = Path("B06_Section")
|
||||
_MODELS_SUBDIR = Path("B04_PreProcess") / "models"
|
||||
# 노선 파일 하나 — 노선 풀기(`B05_Profile_Engine`)가 쓰고 DB `routes.route_data_path` 가 가리킴
|
||||
ROUTE_DATA_FILE = "B05_Profile/route/route_main.geojson"
|
||||
|
||||
|
||||
def _load_route_polyline(project_root: Path, route_data_path: str) -> list[list[float]]:
|
||||
@@ -243,6 +246,20 @@ def _load_pipe_points(project_root: Path, polyline: list[list[float]]) -> list[P
|
||||
return points
|
||||
|
||||
|
||||
def route_pipe_points(project_root: Path, route_data_path: str | None = None) -> list[PipePoint]:
|
||||
"""관 지점 정본을 **지금 노선에 얹어** 읽음(472 덧 · 관 = 좌표 주인) — 측점 계획 · 관 지점 GET ·
|
||||
화면과 같은 이월(`_load_pipe_points`) · 지문이 어긋난 옛 저장분도 같은 자리.
|
||||
|
||||
노선 경로 안 줌 = 노선 파일 하나(`ROUTE_DATA_FILE`) · 노선을 못 읽으면 저장분 그대로."""
|
||||
try:
|
||||
polyline = _load_route_polyline(project_root, route_data_path or ROUTE_DATA_FILE)
|
||||
except (OSError, ValueError):
|
||||
if route_data_path:
|
||||
logger.warning("관 지점: 노선을 못 읽어 저장분 그대로 씀 (%s)", route_data_path)
|
||||
return read_pipe_points_file(pipe_points_path_in(project_root))
|
||||
return _load_pipe_points(project_root, polyline)
|
||||
|
||||
|
||||
def pipe_station_label(pipe: PipePoint, types: dict[str, Any]) -> str | None:
|
||||
"""관 지점 측점 라벨 = 표 카드 이름(322-1 · 배관 = 「관종 D관경」 · 빈칸 = 정의 기본값)."""
|
||||
if pipe.facility not in types:
|
||||
@@ -250,24 +267,16 @@ def pipe_station_label(pipe: PipePoint, types: dict[str, Any]) -> str | None:
|
||||
return card_title(pipe.facility, pipe.options)
|
||||
|
||||
|
||||
def relabel_pipe_stations(project_root: Path, cross_sections: list[dict[str, Any]]) -> None:
|
||||
def relabel_pipe_stations(
|
||||
project_root: Path, cross_sections: list[dict[str, Any]], route_data_path: str | None = None
|
||||
) -> None:
|
||||
"""횡단 측점 라벨을 **지금 관 지점 종류**로 맞춘다(54-4).
|
||||
|
||||
라벨은 측점 생성 때 적혀 파일에 남는다 — 저장으로 종류만 바꾸면(배관 → BOX암거) 측점은
|
||||
다시 안 만들어져 카드 제목이 옛 종류로 남는다. 관 지점 라벨(종류 이름 · 「관종 D관경」)인
|
||||
측점만 고치고 다른 구조물 라벨은 건드리지 않는다.
|
||||
측점만 고치고 다른 구조물 라벨은 건드리지 않는다. 관 = 지금 노선에 얹은 자리(472 덧).
|
||||
"""
|
||||
path = (
|
||||
project_root
|
||||
/ "B04_PreProcess"
|
||||
/ DRAINAGE_CACHE_DIRNAME
|
||||
/ DRAINAGE_EDITS_DIRNAME
|
||||
/ DRAINAGE_PIPE_POINTS_FILENAME
|
||||
)
|
||||
try:
|
||||
points = parse_pipe_points(json.loads(path.read_text(encoding="utf-8")).get("points"))
|
||||
except (OSError, ValueError, AttributeError):
|
||||
return
|
||||
points = route_pipe_points(project_root, route_data_path)
|
||||
types = structure_type_map()
|
||||
pipe_names = {row["name"] for row in catalog().values() if row["owner"] == "pipe_points"}
|
||||
for section in cross_sections:
|
||||
|
||||
@@ -298,12 +298,13 @@ async def migrate_structures(project_id: UUID, payload: StructureMigrateRequest)
|
||||
migrated_before = load_migrated_legacy(root)
|
||||
# 정본이 이미 심는 자리(측점 계획 · 323-7) — 이름이 아니라 자리로 가름(옛 이름 되짚기 걷음)
|
||||
# · 추가 측점(368-2 · 이름 없는 일반측점)도 심는 자리 — 「기타」 구조물로 옮기지 않음
|
||||
from B05_Profile.B05_Profile_Engine_Sections import route_pipe_points
|
||||
from B05_Profile.B05_Profile_Plus_Stations import plus_chainages
|
||||
|
||||
planted = [
|
||||
float(station["chainage_m"])
|
||||
for station in plan_stations(
|
||||
read_pipe_points_file(pipe_points_path_in(Path(root))),
|
||||
route_pipe_points(Path(root)), # 관 = 지금 노선에 얹은 자리(472 덧)
|
||||
existing,
|
||||
plus_chainages(root),
|
||||
)
|
||||
|
||||
@@ -15,11 +15,9 @@ 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 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
|
||||
from common_util.common_util_structure_catalog import catalog_row, field_name, type_ids_with
|
||||
from common_util.common_util_structure_pavement import (
|
||||
attach_pavement_specs,
|
||||
@@ -138,32 +136,14 @@ def attach_shapes(
|
||||
return misses
|
||||
|
||||
|
||||
def saved_pipes(project_root: Path, route_data_path: str | None = None) -> list[Any]:
|
||||
"""관 지점 정본 — 노선 경로를 주면 그 노선에 얹어 읽음(472 덧) · 없으면 파일 그대로.
|
||||
|
||||
측점 계획(`_load_pipe_points`) · 관 지점 GET · 화면과 같은 이월 — 지문이 어긋난 옛 저장분도
|
||||
측점이 선 자리에 관 세트가 얹힘."""
|
||||
if route_data_path:
|
||||
from B05_Profile.B05_Profile_Engine_Sections import (
|
||||
_load_pipe_points,
|
||||
_load_route_polyline,
|
||||
)
|
||||
|
||||
try:
|
||||
return _load_pipe_points(
|
||||
project_root, _load_route_polyline(project_root, route_data_path)
|
||||
)
|
||||
except (FileNotFoundError, ValueError):
|
||||
logger.warning("B06 관 지점: 노선을 못 읽어 저장분 그대로 얹음 (%s)", route_data_path)
|
||||
return read_pipe_points_file(pipe_points_file(project_root))
|
||||
|
||||
|
||||
def attach_saved_shapes(
|
||||
project_root: Path, sections: list[dict[str, Any]], route_data_path: str | None = None
|
||||
) -> None:
|
||||
"""저장분 현황(관 지점 · 구조물 정본)으로 얹음 — 관 = 그 노선에 얹은 것(`saved_pipes`) ·
|
||||
"""저장분 현황(관 지점 · 구조물 정본)으로 얹음 — 관 = 그 노선에 얹은 것(`route_pipe_points`) ·
|
||||
구조물 정본을 못 읽으면 관만(횡단 조회는 이어 감)."""
|
||||
pipes = saved_pipes(project_root, route_data_path)
|
||||
from B05_Profile.B05_Profile_Engine_Sections import route_pipe_points
|
||||
|
||||
pipes = route_pipe_points(project_root, route_data_path)
|
||||
try:
|
||||
structures = load_structures(str(project_root))[1]
|
||||
except Exception: # noqa: BLE001 — 정본을 못 읽어도 횡단 조회는 이어 간다
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
@@ -22,9 +21,7 @@ from B06_Section.B06_Section_Engine_Culvert import (
|
||||
_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
|
||||
|
||||
@@ -47,20 +44,14 @@ _SPAN_LINKED_TYPES: frozenset[str] = frozenset({"ford_pavement"})
|
||||
|
||||
|
||||
def load_culvert_sets(project_root: Path) -> dict[float, dict[str, Any]]:
|
||||
"""관 지점 정본을 읽어 누가거리별 세트 제원을 돌려준다.
|
||||
"""관 지점 정본 → 누가거리별 세트 제원 — 관 = 지금 노선에 얹은 자리(472 덧 · 측점 계획과 같음).
|
||||
|
||||
노선 지문은 보지 않는다 — 횡단면 자체가 현 노선에서 만들어진 것이라, 지문이
|
||||
어긋난 옛 관 지점은 매칭될 측점이 없어 자연히 걸러진다. 파일이 없거나 깨졌으면 빈 값.
|
||||
파일 누가거리를 그대로 읽으면 지문이 어긋난 옛 저장분에서 세월교 노면 하강 · 물넘이포장 구간이
|
||||
측점 계획 · 화면과 다른 자리에 걸렸다. 파일이 없거나 깨졌으면 빈 값.
|
||||
"""
|
||||
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")))
|
||||
from B05_Profile.B05_Profile_Engine_Sections import route_pipe_points
|
||||
|
||||
return culvert_sets_from(route_pipe_points(project_root))
|
||||
|
||||
|
||||
def culvert_sets_from(points: list[Any]) -> dict[float, dict[str, Any]]:
|
||||
|
||||
@@ -261,7 +261,8 @@ def _read_section_detail(
|
||||
raise ValueError("종횡단 상세 파일 형식이 올바르지 않습니다.")
|
||||
# 측점 그림 자료(관 세트 · 벽 · 포장 · 맹암거 · 빈칸 경고) = 형상 얹기 한 벌(323-4 · 화면 짝 attachShapes)
|
||||
attach_saved_shapes(root, cross_sections, route_data_path)
|
||||
relabel_pipe_stations(root, cross_sections) # 저장으로 종류만 바꾼 관 — 카드 제목(54-4)
|
||||
# 저장으로 종류만 바꾼 관 — 카드 제목(54-4)
|
||||
relabel_pipe_stations(root, cross_sections, route_data_path)
|
||||
return {"longitudinal": longitudinal, "cross_sections": cross_sections}
|
||||
|
||||
|
||||
|
||||
@@ -14,17 +14,17 @@ B06 [상세] 모달을 한 번도 안 연 측점(칸 = 없음)에 B07 이 같은
|
||||
좌표 = 도면 mm(글 2.0 · 줄 3.0) · 칸 왼쪽 위 = (0, 0) · 아래로 음수.
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import math
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from B05_Profile.B05_Profile_Engine_Sections import route_pipe_points
|
||||
from B05_Profile.B05_Profile_Structures_Repository import load_structures
|
||||
from B05_Profile.B05_Profile_Structures_Schema import load_definition, load_structure_types
|
||||
from B06_Section.B06_Section_Engine_Culvert import _culvert_set, pipe_points_file
|
||||
from common_util.common_util_drainage_pipes import PIPE_FACILITY_PIPE, parse_pipe_points
|
||||
from B06_Section.B06_Section_Engine_Culvert import _culvert_set
|
||||
from common_util.common_util_drainage_pipes import PIPE_FACILITY_PIPE
|
||||
from common_util.common_util_node_bundle import run_bundle_json
|
||||
from common_util.common_util_structure_station import PIPE_MATCH_M # 같은 자리 폭 한 곳(323-7)
|
||||
|
||||
@@ -272,11 +272,7 @@ def with_option_lines(things: list[Thing]) -> list[Thing]:
|
||||
|
||||
def load_note_sources(project_root: Path) -> tuple[list[Pipe], list[Thing]]:
|
||||
"""정본 재료 — (원형 마크 배수관 · 관경 안 고름 = 없음, 글 줄 재료 = 관 지점 + 구조물 배치)."""
|
||||
try:
|
||||
document = json.loads(pipe_points_file(project_root).read_text(encoding="utf-8"))
|
||||
points = parse_pipe_points(document.get("points"))
|
||||
except (OSError, json.JSONDecodeError):
|
||||
points = []
|
||||
points = route_pipe_points(project_root) # 관 = 지금 노선에 얹은 자리(472 덧)
|
||||
pipes: list[Pipe] = []
|
||||
for point in points:
|
||||
options = dict(point.options or {})
|
||||
|
||||
@@ -44,7 +44,7 @@ source: ["docs/raw/조사/2026-10-19_472_구조다시세움_목록.md", "PLAN.md
|
||||
| F1 | 시설 따라감(노선 바뀜) | `common_util_route_follow.ts:291` · `logic/B05_Profile_Pipeline_Follow.ts` · `logic/B05_Profile_Structure_Follow.ts` | `common_util_route_follow.py:120` | — | 짝 · `test_410_follow_xy` · `test_344_2_route_pairs` |
|
||||
| F2 | 추가 측점 따라감 | `B05_Profile_Api_PlusStations.ts` followPlusDraft | `B05_Profile_Plus_Stations.py:82` | — | 짝 · `test_459_route_seat_mirror` |
|
||||
| F3 | 시설 측점 계획 | `common_util_structure_station.ts` | `common_util_structure_station.py` | — | 짝 · `test_322_3_plan_mirror` |
|
||||
| F4 | 형상 얹기(관 세트 · 벽 · 포장 그림 자료) — 관 = 지금 노선에 얹은 저장분(서버 `saved_pipes` = 측점 계획 · 관 지점 GET 과 같은 이월) | `common_util_structure_attach.ts:130` | `B06_Section_Engine_Attach.py:114` | — | 짝 · `test_323_4_attach_mirror` · `test_472_d_pipe_route_attach` |
|
||||
| F4 | 형상 얹기(관 세트 · 벽 · 포장 그림 자료) — 관 = 지금 노선에 얹은 저장분(서버 `route_pipe_points` = 측점 계획 · 관 지점 GET 과 같은 이월) | `common_util_structure_attach.ts:130` | `B06_Section_Engine_Attach.py:114` | — | 짝 · `test_323_4_attach_mirror` · `test_472_d_pipe_route_attach` |
|
||||
| F5 | 관 세트(관경 · 날개벽 · 집수정) | `common_util_culvert_sets.ts` · `logic/B06_Section_UI_Cross_Culvert_Const.ts` | `B06_Section_Engine_Culvert.py` | Const = sc · co · ex | 짝 · `test_b06_culvert_sets_mirror` · `test_b06_pipe_wall_height_mirror` |
|
||||
| F6 | 벽 · 포장 | `common_util_structure_walls.ts` · `common_util_structure_pavement.ts` | `B06_Section_Engine_Structures_Wall.py` · `common_util_structure_pavement.py` | — | 짝 · `test_b06_structure_walls_mirror` · `test_b06_structure_pavement_mirror` |
|
||||
| F7 | 관 길이 · 구조물 면적 · 다단 벽 | `B06_Section_Structure_Layouts.ts:95 · 287` · `design_structure_pipe_calc.ts` · `common_util_cross_structure_areas.ts` | — | sc | ② · `test_b06_pipe_length` · `test_299_ford_span_pipe` |
|
||||
|
||||
@@ -32,7 +32,7 @@ source: ["CLAUDE.md §5", "docs/raw/조사/2026-10-19_465_요구272_값안변함
|
||||
| B05 · B06 캐시 = 한 벌 · [저장] 한 번에 함께 나감 | `design_shared.ts:395-448` · `design_save.ts:237` | — |
|
||||
| 관 · 구조물 주인 = 가게 칸 하나 — 화면 사본은 가게 알림으로 맞춤(제 쓰기는 같은 값 · 남 고침은 다시 실음) | `design_view_profile.ts` 가게 구독 · `design_view_cross.ts` onShop · `B06_Section_UI_Page_Structures_Panel.ts` seen | `test_472_5_shop_owner` |
|
||||
| 정본 자리 = 값을 낳은 주인 — 노선 시설 = `pipe_points.json` · `structures.json` · 횡단 값 = 횡단 패치 | `B05_Profile_Api_Pipes_Draft.ts:30-37` · `B05_Profile_Structures_Router.py:386-405` · `B06_Section_Section_Store.ts:449` | — |
|
||||
| 관 자리 읽기 한 벌 = 지금 노선에 얹은 관 지점(측점 계획 · 관 지점 GET · 서버 상세 형상 얹기 · 화면) — 지문 어긋난 옛 저장분도 같은 자리 | `B06_Section_Engine_Attach.py` saved_pipes · `B05_Profile_Engine_Sections.py:210` | `test_472_d_pipe_route_attach` |
|
||||
| 관 자리 읽기 한 벌 = 지금 노선에 얹은 관 지점(측점 계획 · 관 지점 GET · 서버 상세 형상 얹기 · 카드 이름 · 세월교 노면 하강 · 물넘이포장 구간 · B07 관 글 · 화면) — 지문 어긋난 옛 저장분도 같은 자리 · 관 파일 누가거리를 그대로 읽지 않음 | `B05_Profile_Engine_Sections.py:249` route_pipe_points | `test_472_d_pipe_route_attach` · `test_472_d_route_pipe_readers` |
|
||||
|
||||
## 바꿀 때 할 일
|
||||
|
||||
|
||||
@@ -70,11 +70,14 @@ def test_상세_읽기_관_세트_자리_측점_계획과_같음(tmp_path: Path)
|
||||
assert owners == {351.0: 351.0}
|
||||
|
||||
|
||||
def test_노선_모름_저장분_그대로(tmp_path: Path) -> None:
|
||||
def test_노선_경로_안_줌_노선_파일_하나(tmp_path: Path) -> None:
|
||||
# 472 덧(관 파일 누가거리 남은 자리) — 경로 안 줌 = 노선 파일 하나(`ROUTE_DATA_FILE`) · 옛 단언
|
||||
# 「파일 누가거리 394」는 측점 계획과 갈리던 옛 동작이라 고침
|
||||
_project(tmp_path)
|
||||
sections = _sections()
|
||||
attach_saved_shapes(tmp_path, sections) # 노선 경로 없음 = 파일 누가거리(394 · 제 측점 없음)
|
||||
assert not any("culvert" in s for s in sections)
|
||||
attach_saved_shapes(tmp_path, sections)
|
||||
owners = {s["chainage_m"]: s["culvert"]["chainage_m"] for s in sections if "culvert" in s}
|
||||
assert owners == {351.0: 351.0}
|
||||
|
||||
|
||||
def test_노선_파일_없음_저장분_그대로(tmp_path: Path) -> None:
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
"""PLAN 472 덧 (요구 272) — 관 파일 누가거리를 그대로 읽던 남은 서버 자리 = 지금 노선 관 자리.
|
||||
|
||||
관 지점 정본의 노선 지문이 지금 노선과 어긋난 저장분(옛 노선 누가거리 · 좌표는 지금 노선) —
|
||||
측점 계획(`_load_pipe_points`) · 관 지점 GET · 화면 · 서버 상세 얹기(`attach_saved_shapes`)는 좌표로
|
||||
얹는데 세월교 노면 하강(`ford_surface_drops`) · 물넘이포장 구간(`ford_pavement_ranges` ·
|
||||
`tilt_ranges`) · 카드 이름(`relabel_pipe_stations`) · B07 관 글 재료(`load_note_sources`)는
|
||||
파일 누가거리로 읽어 [저장] 재계산 · 상세 값이 화면과 갈렸음.
|
||||
관 = 좌표 주인 · 파일 지문이 어긋나도 같은 값.
|
||||
|
||||
./venv/Scripts/python.exe -m pytest resources/tester/test_472_d_route_pipe_readers.py -q
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from B05_Profile.B05_Profile_Engine_Sections import relabel_pipe_stations # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Attach import attach_saved_shapes # noqa: E402
|
||||
from B06_Section.B06_Section_Engine_Tilt import tilt_ranges # noqa: E402
|
||||
from B06_Section.B06_Section_Router_Design_Ranges import ( # noqa: E402
|
||||
ford_drop_at,
|
||||
ford_pavement_ranges,
|
||||
ford_surface_drops,
|
||||
paved_at,
|
||||
pavement_ranges,
|
||||
)
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_CulvertNote import ( # noqa: E402
|
||||
load_note_sources,
|
||||
)
|
||||
|
||||
ROUTE = "B05_Profile/route/route_main.geojson"
|
||||
|
||||
# (옛 노선 누가거리, 지금 노선 x) — 지금 노선 = x 축 0 → 1000 · 지금 누가거리 = x
|
||||
PIPES = [
|
||||
(194.0, 151.0, "box_culvert", {}),
|
||||
(394.0, 351.0, "ford_bridge", {"ford_height_m": 0.5, "ford_width_m": 10}),
|
||||
(594.0, 551.0, "ford_pavement", {"ford_width_m": 10, "ford_slope_deg": 3}),
|
||||
(894.0, 751.0, "pipe", {"pipe_kind": "파형강관", "pipe_diameter_mm": "1000"}),
|
||||
]
|
||||
|
||||
|
||||
def _project(root: Path, stale: bool) -> Path:
|
||||
route = root / ROUTE
|
||||
route.parent.mkdir(parents=True)
|
||||
route.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {"type": "LineString", "coordinates": [[0, 0, 0], [1000, 0, 0]]},
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
edits = root / "B04_PreProcess" / "drainage" / "edits"
|
||||
edits.mkdir(parents=True)
|
||||
points = [
|
||||
{
|
||||
"id": f"p{int(x)}",
|
||||
"chainage_m": old if stale else x,
|
||||
"x": x,
|
||||
"y": 0.3,
|
||||
"facility": facility,
|
||||
"options": options,
|
||||
}
|
||||
for old, x, facility, options in PIPES
|
||||
]
|
||||
(edits / "pipe_points.json").write_text(
|
||||
json.dumps({"route_signature": "옛-노선", "points": points}), encoding="utf-8"
|
||||
)
|
||||
return root
|
||||
|
||||
|
||||
def _read(root: Path) -> dict:
|
||||
sections = [
|
||||
{"chainage_m": 151.0, "structure": "파형강관 D900"},
|
||||
{"chainage_m": 351.0, "center_x": 351.0, "center_y": 0.0},
|
||||
{"chainage_m": 551.0, "center_x": 551.0, "center_y": 0.0},
|
||||
{"chainage_m": 751.0, "center_x": 751.0, "center_y": 0.0},
|
||||
]
|
||||
relabel_pipe_stations(root, sections)
|
||||
attach_saved_shapes(root, sections) # 노선 경로 안 줌 = 노선 파일 하나
|
||||
pipes, _things = load_note_sources(root)
|
||||
drops = ford_surface_drops(root)
|
||||
return {
|
||||
"drops": drops,
|
||||
"ford_pavement": ford_pavement_ranges(root),
|
||||
"tilts": [(a, b) for a, b, _ in tilt_ranges(root)],
|
||||
"label_151": sections[0].get("structure"),
|
||||
"ford_at_351": sections[1].get("ford", {}).get("chainage_m"),
|
||||
"drop_351": ford_drop_at(351.0, drops),
|
||||
"paved_551": paved_at(551.0, pavement_ranges(root)),
|
||||
"note_pipes": [at for at, _spec, _options in pipes],
|
||||
}
|
||||
|
||||
|
||||
def test_지문_어긋난_관_파일_지금_노선_자리(tmp_path: Path) -> None:
|
||||
got = _read(_project(tmp_path, stale=True))
|
||||
assert got["drops"] == [(351.0, 0.5)]
|
||||
assert got["ford_pavement"] == [(546.0, 556.0)]
|
||||
assert got["tilts"] == [(546.0, 556.0)]
|
||||
assert got["label_151"] == "BOX암거"
|
||||
assert got["ford_at_351"] == 351.0
|
||||
assert got["drop_351"] == 0.5
|
||||
assert got["paved_551"] is True
|
||||
assert got["note_pipes"] == [751.0]
|
||||
|
||||
|
||||
def test_지문_어긋나도_같은_값(tmp_path: Path) -> None:
|
||||
stale = _read(_project(tmp_path / "옛", stale=True))
|
||||
fresh = _read(_project(tmp_path / "새", stale=False))
|
||||
assert stale == fresh
|
||||
|
||||
|
||||
def test_노선_파일_없음_저장분_그대로(tmp_path: Path) -> None:
|
||||
root = _project(tmp_path, stale=True)
|
||||
(root / ROUTE).unlink()
|
||||
assert ford_surface_drops(root) == [(394.0, 0.5)]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main([__file__, "-q"]))
|
||||
Reference in New Issue
Block a user