82 lines
3.2 KiB
Python
82 lines
3.2 KiB
Python
"""Visualization API - GeoJSON endpoints for 3D Earth display"""
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
import httpx
|
|
|
|
router = APIRouter()
|
|
|
|
CABLE_DATA_URL = "https://services.arcgis.com/6DIQcwlPy8knb6sg/arcgis/rest/services/SubmarineCables/FeatureServer/2/query?where=1%3D1&outFields=*&returnGeometry=true&f=geojson"
|
|
LANDING_POINT_CSV_URL = "https://data.apps.fao.org/catalog/dataset/1b75ff21-92f2-4b96-9b7b-98e8aa65ad5d/resource/b6071077-d1d4-4e97-aa00-42e902847c87/download/landing-point-geo.csv"
|
|
|
|
|
|
@router.get("/geo/cables")
|
|
async def get_cables_geojson():
|
|
"""获取海底电缆 GeoJSON 数据 (LineString)"""
|
|
try:
|
|
async with httpx.AsyncClient(timeout=60.0) as client:
|
|
response = await client.get(CABLE_DATA_URL)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except httpx.HTTPError as e:
|
|
raise HTTPException(status_code=502, detail=f"Failed to fetch cable data: {str(e)}")
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Internal error: {str(e)}")
|
|
|
|
|
|
@router.get("/geo/landing-points")
|
|
async def get_landing_points_geojson():
|
|
"""获取登陆点 GeoJSON 数据 (Point)"""
|
|
try:
|
|
async with httpx.AsyncClient(timeout=60.0) as client:
|
|
response = await client.get(LANDING_POINT_CSV_URL)
|
|
response.raise_for_status()
|
|
|
|
lines = response.text.strip().split("\n")
|
|
if not lines:
|
|
raise HTTPException(status_code=500, detail="Empty CSV data")
|
|
|
|
features = []
|
|
for line in lines[1:]:
|
|
if not line.strip():
|
|
continue
|
|
parts = line.split(",")
|
|
if len(parts) >= 4:
|
|
try:
|
|
lon = float(parts[0])
|
|
lat = float(parts[1])
|
|
feature_id = parts[2]
|
|
name = parts[3].strip('"')
|
|
is_tbd = parts[4].strip() == "true" if len(parts) > 4 else False
|
|
|
|
features.append(
|
|
{
|
|
"type": "Feature",
|
|
"geometry": {"type": "Point", "coordinates": [lon, lat]},
|
|
"properties": {"id": feature_id, "name": name, "is_tbd": is_tbd},
|
|
}
|
|
)
|
|
except (ValueError, IndexError):
|
|
continue
|
|
|
|
return {"type": "FeatureCollection", "features": features}
|
|
except httpx.HTTPError as e:
|
|
raise HTTPException(status_code=502, detail=f"Failed to fetch landing point data: {str(e)}")
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Internal error: {str(e)}")
|
|
|
|
|
|
@router.get("/geo/all")
|
|
async def get_all_geojson():
|
|
"""获取所有可视化数据 (电缆 + 登陆点)"""
|
|
cables = await get_cables_geojson()
|
|
points = await get_landing_points_geojson()
|
|
|
|
return {
|
|
"cables": cables,
|
|
"landing_points": points,
|
|
"stats": {
|
|
"cable_count": len(cables.get("features", [])) if cables else 0,
|
|
"landing_point_count": len(points.get("features", [])) if points else 0,
|
|
},
|
|
}
|