@mytec: iter2.4 ready for testing
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import os
|
||||
import asyncio
|
||||
import math
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from fastapi.responses import FileResponse
|
||||
@@ -11,6 +13,46 @@ from app.services.los_service import los_service
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
def _build_elevation_grid(min_lat, max_lat, min_lon, max_lon, resolution):
|
||||
"""Build a 2D elevation grid. Runs in thread executor (CPU-bound)."""
|
||||
import numpy as np
|
||||
|
||||
rows = min(resolution, 200)
|
||||
cols = min(resolution, 200)
|
||||
|
||||
lats = np.linspace(max_lat, min_lat, rows) # north to south
|
||||
lons = np.linspace(min_lon, max_lon, cols)
|
||||
|
||||
grid = []
|
||||
min_elev = float('inf')
|
||||
max_elev = float('-inf')
|
||||
|
||||
for lat in lats:
|
||||
row = []
|
||||
for lon in lons:
|
||||
elev = terrain_service.get_elevation_sync(float(lat), float(lon))
|
||||
row.append(elev)
|
||||
if elev < min_elev:
|
||||
min_elev = elev
|
||||
if elev > max_elev:
|
||||
max_elev = elev
|
||||
grid.append(row)
|
||||
|
||||
return {
|
||||
"grid": grid,
|
||||
"rows": rows,
|
||||
"cols": cols,
|
||||
"min_elevation": min_elev if min_elev != float('inf') else 0,
|
||||
"max_elevation": max_elev if max_elev != float('-inf') else 0,
|
||||
"bbox": {
|
||||
"min_lat": min_lat,
|
||||
"max_lat": max_lat,
|
||||
"min_lon": min_lon,
|
||||
"max_lon": max_lon,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@router.get("/elevation")
|
||||
async def get_elevation(
|
||||
lat: float = Query(..., ge=-90, le=90, description="Latitude"),
|
||||
@@ -26,6 +68,42 @@ async def get_elevation(
|
||||
}
|
||||
|
||||
|
||||
@router.get("/elevation-grid")
|
||||
async def get_elevation_grid(
|
||||
min_lat: float = Query(..., ge=-90, le=90, description="South boundary"),
|
||||
max_lat: float = Query(..., ge=-90, le=90, description="North boundary"),
|
||||
min_lon: float = Query(..., ge=-180, le=180, description="West boundary"),
|
||||
max_lon: float = Query(..., ge=-180, le=180, description="East boundary"),
|
||||
resolution: int = Query(100, ge=10, le=200, description="Grid size (rows/cols)"),
|
||||
):
|
||||
"""Get elevation grid for a bounding box. Returns a 2D array for terrain visualization."""
|
||||
if max_lat <= min_lat or max_lon <= min_lon:
|
||||
raise HTTPException(400, "Invalid bbox: max must be greater than min")
|
||||
if (max_lat - min_lat) > 2.0 or (max_lon - min_lon) > 2.0:
|
||||
raise HTTPException(400, "Bbox too large (max 2 degrees per axis)")
|
||||
|
||||
# Ensure terrain tiles are loaded for this area
|
||||
await terrain_service.ensure_tiles_for_bbox(min_lat, min_lon, max_lat, max_lon)
|
||||
|
||||
# Pre-load all tiles that cover the bbox
|
||||
lat_start = int(math.floor(min_lat))
|
||||
lat_end = int(math.floor(max_lat))
|
||||
lon_start = int(math.floor(min_lon))
|
||||
lon_end = int(math.floor(max_lon))
|
||||
for lat_i in range(lat_start, lat_end + 1):
|
||||
for lon_i in range(lon_start, lon_end + 1):
|
||||
tile_name = terrain_service.get_tile_name(lat_i + 0.5, lon_i + 0.5)
|
||||
terrain_service._load_tile(tile_name)
|
||||
|
||||
# Build grid in thread executor (CPU-bound sync calls)
|
||||
loop = asyncio.get_event_loop()
|
||||
result = await loop.run_in_executor(
|
||||
None, _build_elevation_grid,
|
||||
min_lat, max_lat, min_lon, max_lon, resolution,
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/profile")
|
||||
async def get_elevation_profile(
|
||||
lat1: float = Query(..., description="Start latitude"),
|
||||
@@ -87,9 +165,9 @@ async def check_fresnel_clearance(
|
||||
@router.get("/tiles")
|
||||
async def list_cached_tiles():
|
||||
"""List cached SRTM tiles"""
|
||||
tiles = list(terrain_service.cache_dir.glob("*.hgt"))
|
||||
tiles = list(terrain_service.terrain_path.glob("*.hgt"))
|
||||
return {
|
||||
"cache_dir": str(terrain_service.cache_dir),
|
||||
"cache_dir": str(terrain_service.terrain_path),
|
||||
"tiles": [t.stem for t in tiles],
|
||||
"count": len(tiles)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user