fix(B03/B04): PRJ 좌표계 판별을 문자열 매칭에서 WKT 정본+EPSG 라벨로 바꾼다

get_epsg_from_prj()가 WKT에 항상 있는 false_easting 때문에 EAST 분기가
무조건 걸려 모든 PRJ를 EPSG:5187로 판정했다(표준 WKT 6종 실측). 새 원청
자료의 5176(비표준 TOWGS84)·5179(AUTHORITY 없는 ESRI WKT)가 이 경로로
들어오면 최대 100km 어긋난다.

- common_util/common_util_crs.py 신설: 판별 사다리(pyproj DB 대조 →
  AUTHORITY 태그 → 투영 파라미터 지문)와 변환 입력 정규화. 수평 성분에
  TOWGS84가 박힌 PRJ는 EPSG로 갈아타지 않고 원문 WKT로 변환해 지역 보정을
  보존한다. 수직 성분의 bound(KNGeoid)는 2D 변환에 무관하므로 무시.
- B04 get_epsg_from_prj: 죽은 문자열 분기 제거, 유틸 위임. 시그니처 불변 —
  기존 COMPD_CS 프로젝트는 예전과 같은 EPSG:5187 문자열이 나온다.
- B03 _component_metadata: to_epsg 실패 시 사다리 라벨 보강,
  normalize_crs_metadata: BoundCRS 벗김(TOWGS84 PRJ 수평 탐색 실패 수정).

검증: tmp/tests/test_common_util_crs.py 13건 포함 스위트 29 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-31 16:27:13 +09:00
co-authored by Claude Opus 5
parent 46ac54257e
commit 0d90595a40
3 changed files with 196 additions and 18 deletions
+12 -1
View File
@@ -55,6 +55,12 @@ def _component_metadata(crs: CRS) -> dict[str, Any]:
"""CRS 구성 요소를 JSON 저장 가능한 메타데이터로 변환한다."""
authority = crs.to_authority()
epsg = crs.to_epsg()
if epsg is None and (crs.is_projected or crs.is_geographic):
# DB 대조 실패(비표준 TOWGS84·AUTHORITY 없는 ESRI WKT 등) — 파라미터
# 지문으로 라벨을 보강한다. 변환 정본은 여전히 원문 WKT다 (2026-08-31).
from common_util.common_util_crs import identify_epsg
epsg = identify_epsg(crs)
return {
"name": crs.name,
"type": crs.type_name,
@@ -77,7 +83,12 @@ def normalize_crs_metadata(crs: Any | None) -> dict[str, Any]:
}
parsed = crs if isinstance(crs, CRS) else CRS.from_user_input(crs)
components = parsed.sub_crs_list or [parsed]
# TOWGS84가 붙은 WKT는 BoundCRS로 감싸져 is_projected가 False가 된다 —
# 벗겨야 수평 성분 탐색과 EPSG 라벨이 동작한다 (2026-08-31).
from common_util.common_util_crs import strip_bound
flattened = strip_bound(parsed)
components = [strip_bound(item) for item in (flattened.sub_crs_list or [flattened])]
horizontal = next(
(item for item in components if item.is_projected or item.is_geographic),
None,