refactor(공통): 작업 좌표계 폴백을 창구 하나로 통합 + 트림 실패 진단
같은 폴백 사다리가 네 곳에 서로 다른 모양으로 흩어져 있었고, 그중 배수유역 라우터 `_route_center_lonlat` 은 노선 CSV 의 `crs_epsg` **라벨**을 그대로 변환에 썼다(라벨과 실좌표계가 다른 사례 실측 — 2026-09-01 용화 라벨 5179 / 실제 5176). `common_util_crs.resolve_project_crs()` 신설 — 사다리는 ① 노선 crs_input ② 파일 라벨 (원본 좌표를 읽는 자리만) ③ 지형 PRJ(작업 좌표계 정본) ④ DB epsg ⑤ EPSG:5186. 작업 좌표계는 **지형 PRJ 우선으로 확정**(2026-09-03 사용자 결정 — 서피스 격자가 모델좌표의 주인이라 현행 유지). `project_epsg_from_prj()` 도 이 창구로 위임. 더해 지표면 트림이 노선을 통째로 지울 때 노선·지표면 bbox 를 함께 로그에 남긴다 — "겹치지 않습니다" 만으로는 좌표계 문제인지 측량 범위 문제인지 갈리지 않았다. 검증 — `tmp/tests/test_project_crs_resolution.py` 5건 신설(사다리 4·진단 1), 전체 375 passed·17 skipped, ruff format 무변경. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -209,3 +209,51 @@ def crs_input_from_prj(prj_text: str) -> str | None:
|
||||
else:
|
||||
logger.warning("PRJ 좌표계의 EPSG 라벨을 찾지 못함 — 파일 WKT로 변환: %s", crs.name)
|
||||
return text
|
||||
|
||||
|
||||
def project_prj_crs(project_root: Path) -> str | None:
|
||||
"""프로젝트 **작업 좌표계** — 지형 PRJ 원문. PRJ가 없으면 None.
|
||||
|
||||
작업 좌표계는 지형 PRJ 로 확정(2026-09-03 사용자 결정, 종전 동작 유지). 서피스 격자가
|
||||
모델좌표의 주인이고 노선은 `load_design_route()` 가 이 좌표계로 옮겨 오기 때문이다.
|
||||
노선 shapefile 은 다른 좌표계로 들어온다(실측 2026-08-31 — 노선 UTM-K / 지형 동부원점).
|
||||
|
||||
기본값을 섞지 않는다 — 사다리(`resolve_project_crs`)가 다음 근거로 내려갈 수 있어야 한다.
|
||||
"""
|
||||
prj_path = find_project_prj(project_root)
|
||||
if prj_path is None:
|
||||
return None
|
||||
from B04_PreProcess.B04_PreProcess_Engine_VWorld import get_epsg_from_prj
|
||||
|
||||
return get_epsg_from_prj(prj_path.read_text(encoding="utf-8", errors="ignore"))
|
||||
|
||||
|
||||
def resolve_project_crs(
|
||||
project_root: Path,
|
||||
*,
|
||||
route_crs_input: str | None = None,
|
||||
file_label_epsg: int | None = None,
|
||||
db_epsg: int | None = None,
|
||||
) -> str:
|
||||
"""작업 좌표계를 정하는 **단일 창구** — pyproj 입력 문자열(`EPSG:n` 또는 WKT 원문).
|
||||
|
||||
사다리(위가 이김):
|
||||
① `load_design_route()` 가 돌려준 노선 `crs_input` — 이미 작업 좌표계로 맞춰 둔 값
|
||||
② `file_label_epsg` — **원본 파일 좌표를 그대로 해석할 때만** 넘긴다(노선 CSV 의
|
||||
`crs_epsg` 열). 그 자리에서는 파일이 스스로 밝힌 좌표계가 유일한 근거다.
|
||||
③ 지형 PRJ(`project_prj_crs`) — 작업 좌표계 정본
|
||||
④ DB `surface_models.crs_epsg`
|
||||
⑤ 중부원점 `EPSG:5186` — 최후 폴백
|
||||
|
||||
**변환이 끝난 좌표를 다룰 때는 ②를 넘기지 않는다.** 그 라벨은 실좌표계와 다른 사례가
|
||||
실측됐다(2026-09-01 용화 — 라벨 5179 / 실제 5176). 이 창구를 두기 전에는 같은 사다리가
|
||||
네 곳에 서로 다른 모양으로 흩어져 있었다.
|
||||
"""
|
||||
if route_crs_input:
|
||||
return route_crs_input
|
||||
if file_label_epsg:
|
||||
return f"EPSG:{file_label_epsg}"
|
||||
prj_crs = project_prj_crs(project_root)
|
||||
if prj_crs:
|
||||
return prj_crs
|
||||
return f"EPSG:{db_epsg or 5186}"
|
||||
|
||||
Reference in New Issue
Block a user