- 서버: 지오빅데이터(KIGAM) 수치지질도 1:50,000 — WFS 암상 면(깨진 한글 칸은 기호별 점 조회로 채움) · 받은 범위 ∪ 노선으로 자름 · 저장본 · 노선 따라 1 m 표본 구간 · 키는 서버만(.env GEOBIGDATA_API_KEY · 쿼리 key) - 그림 조각 대리에 geology(키 쿼리 이름 칸 key_param · 옛 겹 serviceKey 그대로) - 화면(D03 · B05): 「제한·재해」에 「암상 지질도」 — 그림 조각 + 갈래 색 면 · 「기호 · 암상」 글 · 범례 · 노선 구간 표(참고 — 토사 · 암 판정 아님) - 켠 밖 겹마다 범례 맨 아래 출처 줄(브이월드 · 국토지리정보원 · 산림청 · 환경부 · 생활안전지도 공공누리 · 한국지질자원연구원 CC BY-NC) - 범례 칸 높이 한도 · 밀기(낮은 화면) - 시험: test_760_1 새로 · test_634_2 · test_553_4 겹 차례 표에 geology 한 줄 더함(새 겹 · 낡은 표) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.7 KiB
Python
57 lines
2.7 KiB
Python
"""D 예정노선 받은 산림 · 환경 자료 조각 API (PLAN 622-1 · 요구 529).
|
|
|
|
- `GET /api/projects/{id}/plan/vt/{name}/{z}/{x}/{y}.pbf` — 벡터 조각(forest_road · forest_soil ·
|
|
eco_forest · 공용 창고 · `common_util_vector_tiles`)
|
|
- `GET …/plan/wmt/{name}/{z}/{x}/{y}.png` — 그림 조각 대리(ecology · landslide · geology 760-1 · 처음 받고 기억 ·
|
|
`common_util_wms_tiles`) · 빈 · 오류 조각 = 투명 PNG + `X-Tile-Empty` · 짧게 기억
|
|
권한 = 다른 plan 길과 같음(`main.py` 등록 때 회사 보호).
|
|
|
|
계산 자리 = ③ 서버 단독.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, HTTPException, Response
|
|
|
|
from common_util import common_util_vector_tiles as vector_tiles
|
|
from common_util import common_util_wms_tiles as wms_tiles
|
|
|
|
router = APIRouter(prefix="/api/projects", tags=["D03 Plan Tiles"])
|
|
|
|
KEEP = "private, max-age=86400"
|
|
SHORT = f"private, max-age={wms_tiles.SHORT_S}"
|
|
|
|
|
|
@router.get("/{project_id}/plan/vt/{name}/{z}/{x}/{y}.pbf", response_model=None)
|
|
async def plan_vector_tile(project_id: UUID, name: str, z: int, x: int, y: int) -> Response:
|
|
"""받은 산림 자료 벡터 조각 — 공용 창고 · 없으면 원자료에서 만듦 · 빈 조각 = 빈 MVT."""
|
|
if name not in vector_tiles.RULES:
|
|
raise HTTPException(status_code=404, detail=f"모르는 겹입니다 — {name}")
|
|
try:
|
|
tile = await asyncio.to_thread(vector_tiles.ensure_tile, name, z, x, y)
|
|
except KeyError as error:
|
|
raise HTTPException(status_code=400, detail="조각 번호가 범위를 벗어났습니다.") from error
|
|
return Response(
|
|
content=tile, media_type="application/x-protobuf", headers={"Cache-Control": KEEP}
|
|
)
|
|
|
|
|
|
@router.get("/{project_id}/plan/wmt/{name}/{z}/{x}/{y}.png", response_model=None)
|
|
async def plan_wms_tile(project_id: UUID, name: str, z: int, x: int, y: int) -> Response:
|
|
"""그림 조각 대리 — 처음 받고 기억 · 키 없음 = 404 + 까닭."""
|
|
if name not in wms_tiles.SOURCES:
|
|
raise HTTPException(status_code=404, detail=f"모르는 겹입니다 — {name}")
|
|
try:
|
|
png, status = await asyncio.to_thread(wms_tiles.ensure_tile, name, z, x, y)
|
|
except wms_tiles.MissingKeyError as error:
|
|
raise HTTPException(status_code=404, detail=str(error)) from error
|
|
except KeyError as error:
|
|
raise HTTPException(status_code=400, detail="조각 번호가 범위를 벗어났습니다.") from error
|
|
headers = {"Cache-Control": SHORT if status else KEEP}
|
|
if status:
|
|
headers["X-Tile-Empty"] = status
|
|
return Response(content=png, media_type="image/png", headers=headers)
|