Spaces:
Build error
Build error
Upload 4 files
Browse files- backend/area.py +26 -0
- backend/coordinate_converter.py +31 -0
- backend/distance.py +36 -0
- backend/terrain.py +35 -0
backend/area.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, HTTPException
|
| 2 |
+
from pydantic import BaseModel
|
| 3 |
+
from typing import List
|
| 4 |
+
|
| 5 |
+
router = APIRouter()
|
| 6 |
+
|
| 7 |
+
class PolygonCoordinates(BaseModel):
|
| 8 |
+
coordinates: List[List[float]] # List of [longitude, latitude] pairs
|
| 9 |
+
|
| 10 |
+
@router.post("/api/calculate-area")
|
| 11 |
+
async def calculate_area(polygon: PolygonCoordinates):
|
| 12 |
+
"""Calculate the area of a polygon defined by a set of coordinates."""
|
| 13 |
+
if len(polygon.coordinates) < 3:
|
| 14 |
+
raise HTTPException(status_code=400, detail="At least three coordinates are required to form a polygon.")
|
| 15 |
+
|
| 16 |
+
# Using the Shoelace formula to calculate the area
|
| 17 |
+
area = 0.0
|
| 18 |
+
n = len(polygon.coordinates)
|
| 19 |
+
|
| 20 |
+
for i in range(n):
|
| 21 |
+
x1, y1 = polygon.coordinates[i]
|
| 22 |
+
x2, y2 = polygon.coordinates[(i + 1) % n] # Wrap around to the first point
|
| 23 |
+
area += x1 * y2 - x2 * y1
|
| 24 |
+
|
| 25 |
+
area = abs(area) / 2.0
|
| 26 |
+
return {"area": area}
|
backend/coordinate_converter.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, HTTPException
|
| 2 |
+
from pydantic import BaseModel
|
| 3 |
+
import pyproj
|
| 4 |
+
|
| 5 |
+
router = APIRouter()
|
| 6 |
+
|
| 7 |
+
class CoordinateConversionRequest(BaseModel):
|
| 8 |
+
latitude: float
|
| 9 |
+
longitude: float
|
| 10 |
+
source_crs: str
|
| 11 |
+
target_crs: str
|
| 12 |
+
|
| 13 |
+
class CoordinateConversionResponse(BaseModel):
|
| 14 |
+
original_coordinates: dict
|
| 15 |
+
converted_coordinates: dict
|
| 16 |
+
|
| 17 |
+
@router.post("/api/coordinate-convert", response_model=CoordinateConversionResponse)
|
| 18 |
+
async def convert_coordinates(request: CoordinateConversionRequest):
|
| 19 |
+
"""Convert coordinates between different CRS systems."""
|
| 20 |
+
try:
|
| 21 |
+
# Create transformer
|
| 22 |
+
transformer = pyproj.Transformer.from_crs(request.source_crs, request.target_crs, always_xy=True)
|
| 23 |
+
# Transform coordinates
|
| 24 |
+
lon, lat = transformer.transform(request.longitude, request.latitude)
|
| 25 |
+
|
| 26 |
+
return CoordinateConversionResponse(
|
| 27 |
+
original_coordinates={"latitude": request.latitude, "longitude": request.longitude, "crs": request.source_crs},
|
| 28 |
+
converted_coordinates={"latitude": lat, "longitude": lon, "crs": request.target_crs}
|
| 29 |
+
)
|
| 30 |
+
except Exception as e:
|
| 31 |
+
raise HTTPException(status_code=500, detail=str(e))
|
backend/distance.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, HTTPException
|
| 2 |
+
from pydantic import BaseModel
|
| 3 |
+
import math
|
| 4 |
+
|
| 5 |
+
router = APIRouter()
|
| 6 |
+
|
| 7 |
+
class DistanceRequest(BaseModel):
|
| 8 |
+
lat1: float
|
| 9 |
+
lon1: float
|
| 10 |
+
lat2: float
|
| 11 |
+
lon2: float
|
| 12 |
+
|
| 13 |
+
class DistanceResponse(BaseModel):
|
| 14 |
+
distance: float # Distance in kilometers
|
| 15 |
+
|
| 16 |
+
@router.post("/api/distance", response_model=DistanceResponse)
|
| 17 |
+
async def calculate_distance(request: DistanceRequest):
|
| 18 |
+
"""Calculate the distance between two coordinates using the Haversine formula."""
|
| 19 |
+
try:
|
| 20 |
+
# Haversine formula
|
| 21 |
+
R = 6371.0 # Earth radius in kilometers
|
| 22 |
+
lat1_rad = math.radians(request.lat1)
|
| 23 |
+
lon1_rad = math.radians(request.lon1)
|
| 24 |
+
lat2_rad = math.radians(request.lat2)
|
| 25 |
+
lon2_rad = math.radians(request.lon2)
|
| 26 |
+
|
| 27 |
+
dlat = lat2_rad - lat1_rad
|
| 28 |
+
dlon = lon2_rad - lon1_rad
|
| 29 |
+
|
| 30 |
+
a = math.sin(dlat / 2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2)**2
|
| 31 |
+
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
| 32 |
+
|
| 33 |
+
distance = R * c # Distance in kilometers
|
| 34 |
+
return DistanceResponse(distance=distance)
|
| 35 |
+
except Exception as e:
|
| 36 |
+
raise HTTPException(status_code=500, detail=str(e))
|
backend/terrain.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, HTTPException
|
| 2 |
+
import httpx
|
| 3 |
+
|
| 4 |
+
router = APIRouter()
|
| 5 |
+
|
| 6 |
+
# Route for extracting terrain data
|
| 7 |
+
@router.post("/api/terrain-data")
|
| 8 |
+
async def extract_terrain_data(latitude: float, longitude: float):
|
| 9 |
+
"""Extract terrain data such as slope or aspect from a given location"""
|
| 10 |
+
try:
|
| 11 |
+
# Example API call to a terrain data service (replace with actual service)
|
| 12 |
+
url = f"https://api.example.com/terrain?latitude={latitude}&longitude={longitude}"
|
| 13 |
+
|
| 14 |
+
async with httpx.AsyncClient() as client:
|
| 15 |
+
response = await client.get(url)
|
| 16 |
+
response.raise_for_status()
|
| 17 |
+
data = response.json()
|
| 18 |
+
|
| 19 |
+
# Extract relevant terrain data (e.g., slope, aspect)
|
| 20 |
+
slope = data.get("slope")
|
| 21 |
+
aspect = data.get("aspect")
|
| 22 |
+
|
| 23 |
+
if slope is None or aspect is None:
|
| 24 |
+
raise Exception("No terrain data found in API response")
|
| 25 |
+
|
| 26 |
+
return {
|
| 27 |
+
"latitude": latitude,
|
| 28 |
+
"longitude": longitude,
|
| 29 |
+
"slope": slope,
|
| 30 |
+
"aspect": aspect
|
| 31 |
+
}
|
| 32 |
+
except httpx.HTTPStatusError as e:
|
| 33 |
+
raise HTTPException(status_code=500, detail=f"Terrain API error: {str(e)}")
|
| 34 |
+
except Exception as e:
|
| 35 |
+
raise HTTPException(status_code=500, detail=str(e))
|