merge(D 예정노선): dev 받기 — 604 영역 루틴(fetchLayer · areaTurn · load(have) · track) 과 605 올린 임도망 묶음(applyRoads · deleteRoad · pickRoad) 함께 살림 · 옛 haveTag · sheetLayer 뺌 (PLAN 605 · 요구 475 · 476)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-30 21:54:36 +09:00
co-authored by Claude Opus 5.5
9 changed files with 532 additions and 267 deletions
+43 -3
View File
@@ -290,12 +290,51 @@ async def _layer_root(project_id: UUID) -> tuple[Path, int, terrain.Box]:
return root, epsg, box
SHEET_CLIP_KIND = "plan_sheet"
SHEET_CLIP_VERSION = 1
def _clip_to_box(root: Path, source: Path, box: terrain.Box, epsg: int) -> Path:
"""받은 범위(경위도 외접 상자)로 자른 사본(475) — 열쇠 = 사본 지문 + 범위 · 실패 = 통째."""
from B04_PreProcess.B04_PreProcess_Engine_SheetClip import clip_collection
from common_util.common_util_derived_store import (
derived_dir,
derived_key,
file_stamp,
prune_derived,
)
try:
bounds = layers._lonlat_bounds(box, epsg)
rect = (bounds["min_lon"], bounds["min_lat"], bounds["max_lon"], bounds["max_lat"])
key = derived_key(
SHEET_CLIP_VERSION, source.name, file_stamp(source), [round(v, 1) for v in box]
)
target = derived_dir(root, SHEET_CLIP_KIND) / f"{key}.json"
if target.is_file():
return target
collection = json.loads(source.read_text(encoding="utf-8"))
text = json.dumps(
clip_collection(collection, rect), ensure_ascii=False, separators=(",", ":")
)
target.parent.mkdir(parents=True, exist_ok=True)
temporary = target.with_suffix(f".{uuid4().hex}.tmp")
temporary.write_text(text, encoding="utf-8")
temporary.replace(target)
prune_derived(root, SHEET_CLIP_KIND, keep=2 * len(layers.SHEET_LAYERS))
return target
except Exception as error: # 자르기 실패가 화면을 막으면 안 됨
logger.warning("도엽 겹 받은 범위 자름 실패 (%s): %s", source.name, error)
return source
@router.get("/{project_id}/plan/layers/sheet", response_model=None)
async def plan_layer_sheet(project_id: UUID, key: str, request: Request) -> Response:
"""도엽 겹 GeoJSON(하천중심선 · 도로중심선 …) — 없으면 지난 병합 도엽에서 풀어 냄."""
"""도엽 겹 GeoJSON(등고선 · 하천중심선 · 도로중심선 …) — 없으면 지난 병합 도엽에서 풀어 냄 ·
받은 범위로 자름(475 · 범위가 늘면 새 사본)."""
from B04_PreProcess.B04_PreProcess_Router_GIS import _display_copy
root, _, _ = await _layer_root(project_id)
root, epsg, box = await _layer_root(project_id)
try:
path = await asyncio.to_thread(layers.ensure_sheet_layer, root, key)
except KeyError as error:
@@ -303,7 +342,8 @@ async def plan_layer_sheet(project_id: UUID, key: str, request: Request) -> Resp
except FileNotFoundError as error:
raise HTTPException(status_code=404, detail=str(error)) from error
display = await asyncio.to_thread(_display_copy, path)
return cached_file_response(request, display, "application/geo+json")
clipped = await asyncio.to_thread(_clip_to_box, root, display, box, epsg)
return cached_file_response(request, clipped, "application/geo+json")
@router.get("/{project_id}/plan/layers/cadastral", response_model=None)