import os from fastapi import APIRouter, HTTPException, Query from fastapi.responses import FileResponse from typing import Optional from app.core.config import settings from app.services.terrain_service import terrain_service from app.services.los_service import los_service router = APIRouter() @router.get("/elevation") async def get_elevation( lat: float = Query(..., ge=-90, le=90, description="Latitude"), lon: float = Query(..., ge=-180, le=180, description="Longitude") ): """Get elevation at a specific point""" elevation = await terrain_service.get_elevation(lat, lon) return { "lat": lat, "lon": lon, "elevation": elevation, "unit": "meters" } @router.get("/profile") async def get_elevation_profile( lat1: float = Query(..., description="Start latitude"), lon1: float = Query(..., description="Start longitude"), lat2: float = Query(..., description="End latitude"), lon2: float = Query(..., description="End longitude"), points: int = Query(100, ge=10, le=500, description="Number of sample points") ): """Get elevation profile between two points""" profile = await terrain_service.get_elevation_profile(lat1, lon1, lat2, lon2, points) return { "start": {"lat": lat1, "lon": lon1}, "end": {"lat": lat2, "lon": lon2}, "num_points": len(profile), "profile": profile } @router.get("/los") async def check_line_of_sight( tx_lat: float = Query(..., description="Transmitter latitude"), tx_lon: float = Query(..., description="Transmitter longitude"), tx_height: float = Query(..., ge=0, description="Transmitter height above ground (m)"), rx_lat: float = Query(..., description="Receiver latitude"), rx_lon: float = Query(..., description="Receiver longitude"), rx_height: float = Query(1.5, ge=0, description="Receiver height above ground (m)") ): """Check line-of-sight between transmitter and receiver""" result = await los_service.check_line_of_sight( tx_lat, tx_lon, tx_height, rx_lat, rx_lon, rx_height ) return result @router.get("/fresnel") async def check_fresnel_clearance( tx_lat: float = Query(..., description="Transmitter latitude"), tx_lon: float = Query(..., description="Transmitter longitude"), tx_height: float = Query(..., ge=0, description="Transmitter height (m)"), rx_lat: float = Query(..., description="Receiver latitude"), rx_lon: float = Query(..., description="Receiver longitude"), rx_height: float = Query(1.5, ge=0, description="Receiver height (m)"), frequency: float = Query(..., ge=100, le=6000, description="Frequency (MHz)") ): """Calculate Fresnel zone clearance""" result = await los_service.calculate_fresnel_clearance( tx_lat, tx_lon, tx_height, rx_lat, rx_lon, rx_height, frequency ) return result @router.get("/tiles") async def list_cached_tiles(): """List cached SRTM tiles""" tiles = list(terrain_service.cache_dir.glob("*.hgt")) return { "cache_dir": str(terrain_service.cache_dir), "tiles": [t.stem for t in tiles], "count": len(tiles) } @router.get("/file/{region}") async def get_terrain_file(region: str): """Serve raw SRTM terrain .hgt files (legacy compatibility).""" terrain_path = os.path.join(settings.TERRAIN_DATA_DIR, f"{region}.hgt") if os.path.exists(terrain_path): return FileResponse(terrain_path) raise HTTPException(status_code=404, detail=f"Region '{region}' not found")