feat(529-3): D02 지점 정본 API · 경위도 ↔ TM 점 변환

- common_util_crs: 경도로 TM 띠(5185 · 5186 · 5187) · lonlat_to_tm · tm_to_lonlat
- D02_PlanBase_Router: GET · PUT /api/projects/{id}/plan/points — 잇기(직전 종점 = 다음 시점) · 범위 밖 · 빈 연도 거절 · 산림청만 고침 · 바뀐 연도만 분석 노선 비움
- 지킴 시험 test_529_3_plan_points

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 19:46:43 +09:00
co-authored by Claude Opus 5.5
parent 02bb502ad9
commit 76a399026c
4 changed files with 384 additions and 1 deletions
+27 -1
View File
@@ -10,9 +10,10 @@ from __future__ import annotations
import logging
import re
from functools import lru_cache
from pathlib import Path
from pyproj import CRS
from pyproj import CRS, Transformer
logger = logging.getLogger(__name__)
@@ -257,3 +258,28 @@ def resolve_project_crs(
if prj_crs:
return prj_crs
return f"EPSG:{db_epsg or 5186}"
# --- 점 변환(경위도 ↔ Korea 2000 TM · 요구 345 · PLAN 529-3) ---
def tm_epsg_for_lon(lon: float) -> int:
"""경도로 TM 띠 — 126° 앞 서부 5185 · 128° 앞 중부 5186 · 그 밖 동부 5187(동해 5188 안 씀)."""
return 5185 if lon < 126.0 else 5186 if lon < 128.0 else 5187
@lru_cache(maxsize=16)
def _transformer(source: int, target: int) -> Transformer:
return Transformer.from_crs(source, target, always_xy=True)
def lonlat_to_tm(lon: float, lat: float, epsg: int) -> tuple[float, float]:
"""WGS84 경위도 → TM (x 동, y 북) m."""
x, y = _transformer(4326, epsg).transform(lon, lat)
return float(x), float(y)
def tm_to_lonlat(x: float, y: float, epsg: int) -> tuple[float, float]:
"""TM (x, y) m → WGS84 (경도, 위도)."""
lon, lat = _transformer(epsg, 4326).transform(x, y)
return float(lon), float(lat)