Revise geometry API for CSV
Browse files
app.py
CHANGED
|
@@ -17,7 +17,7 @@ import requests
|
|
| 17 |
import kml2geojson
|
| 18 |
import folium
|
| 19 |
import xml.etree.ElementTree as ET
|
| 20 |
-
from fastapi import FastAPI, HTTPException
|
| 21 |
from urllib.parse import unquote
|
| 22 |
from pydantic import BaseModel, HttpUrl
|
| 23 |
|
|
@@ -381,7 +381,7 @@ def process_and_display(file_obj, url_str, buffer_m, progress=gr.Progress()):
|
|
| 381 |
return m._repr_html_(), None, stats_df, dem_html, slope_html, geometry_json, buffer_geometry_json
|
| 382 |
|
| 383 |
|
| 384 |
-
@app.get("/api/
|
| 385 |
def calculate_geometry_metrics(file_url: str):
|
| 386 |
"""
|
| 387 |
Accepts a URL to a KML/GeoJSON file, calculates the area and
|
|
@@ -422,6 +422,63 @@ def calculate_geometry_metrics(file_url: str):
|
|
| 422 |
# Handle any other unexpected errors with a 500 Internal Server Error
|
| 423 |
print(f"An unexpected error occurred in /api/geometry: {e}")
|
| 424 |
raise HTTPException(status_code=500, detail="An unexpected server error occurred.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 425 |
|
| 426 |
def calculate_indices(
|
| 427 |
geometry_json, buffer_geometry_json, veg_indices, evi_vars, date_range,
|
|
|
|
| 17 |
import kml2geojson
|
| 18 |
import folium
|
| 19 |
import xml.etree.ElementTree as ET
|
| 20 |
+
from fastapi import FastAPI, HTTPException, Response
|
| 21 |
from urllib.parse import unquote
|
| 22 |
from pydantic import BaseModel, HttpUrl
|
| 23 |
|
|
|
|
| 381 |
return m._repr_html_(), None, stats_df, dem_html, slope_html, geometry_json, buffer_geometry_json
|
| 382 |
|
| 383 |
|
| 384 |
+
@app.get("/api/geometry1")
|
| 385 |
def calculate_geometry_metrics(file_url: str):
|
| 386 |
"""
|
| 387 |
Accepts a URL to a KML/GeoJSON file, calculates the area and
|
|
|
|
| 422 |
# Handle any other unexpected errors with a 500 Internal Server Error
|
| 423 |
print(f"An unexpected error occurred in /api/geometry: {e}")
|
| 424 |
raise HTTPException(status_code=500, detail="An unexpected server error occurred.")
|
| 425 |
+
|
| 426 |
+
@app.get("/api/geometry")
|
| 427 |
+
def calculate_geometry_metrics(file_url: str):
|
| 428 |
+
"""
|
| 429 |
+
Accepts a URL to a KML/GeoJSON file, calculates the area and
|
| 430 |
+
perimeter of the first valid polygon, and returns the results
|
| 431 |
+
in a CSV format compatible with Google Sheets' IMPORTDATA.
|
| 432 |
+
"""
|
| 433 |
+
try:
|
| 434 |
+
decoded_url = unquote(file_url)
|
| 435 |
+
input_gdf = get_gdf_from_url(decoded_url)
|
| 436 |
+
|
| 437 |
+
if input_gdf is None or input_gdf.empty:
|
| 438 |
+
raise ValueError("Could not read geometry from the provided URL.")
|
| 439 |
+
|
| 440 |
+
input_gdf = preprocess_gdf(input_gdf)
|
| 441 |
+
geometry_gdf = next((input_gdf.iloc[[i]] for i in range(len(input_gdf)) if is_valid_polygon(input_gdf.iloc[[i]])), None)
|
| 442 |
+
|
| 443 |
+
if geometry_gdf is None:
|
| 444 |
+
raise ValueError("No valid polygon found in the provided file.")
|
| 445 |
+
|
| 446 |
+
projected_gdf = to_best_crs(geometry_gdf)
|
| 447 |
+
|
| 448 |
+
# Calculate area (in hectares) and perimeter (in meters)
|
| 449 |
+
area_hectares = projected_gdf.area.item() / 10000
|
| 450 |
+
perimeter_meters = projected_gdf.length.item()
|
| 451 |
+
|
| 452 |
+
# reproject to WGS84 (EPSG:4326) for centroid
|
| 453 |
+
centroid_gdf = projected_gdf.to_crs(epsg=4326)
|
| 454 |
+
centroid_point = centroid_gdf.centroid.item()
|
| 455 |
+
|
| 456 |
+
# --- CSV Formatting ---
|
| 457 |
+
# 1. Define the header row
|
| 458 |
+
header = "area_hectares,perimeter_meters,latitude,longitude"
|
| 459 |
+
|
| 460 |
+
# 2. Define the data row, rounding the values
|
| 461 |
+
data_row = (
|
| 462 |
+
f"{round(area_hectares, 4)},"
|
| 463 |
+
f"{round(perimeter_meters, 4)},"
|
| 464 |
+
f"{round(centroid_point.y, 4)},"
|
| 465 |
+
f"{round(centroid_point.x, 4)}"
|
| 466 |
+
)
|
| 467 |
+
|
| 468 |
+
# 3. Combine header and data with a newline character
|
| 469 |
+
csv_output = f"{header}\n{data_row}"
|
| 470 |
+
|
| 471 |
+
# 4. Return the CSV string with the correct media type
|
| 472 |
+
return Response(content=csv_output, media_type="text/csv")
|
| 473 |
+
|
| 474 |
+
except ValueError as e:
|
| 475 |
+
# Handle specific errors with a 400 Bad Request
|
| 476 |
+
raise HTTPException(status_code=400, detail=str(e))
|
| 477 |
+
except Exception as e:
|
| 478 |
+
# Handle any other unexpected errors with a 500
|
| 479 |
+
print(f"An unexpected error occurred in /api/geometry: {e}")
|
| 480 |
+
raise HTTPException(status_code=500, detail="An unexpected server error occurred.")
|
| 481 |
+
|
| 482 |
|
| 483 |
def calculate_indices(
|
| 484 |
geometry_json, buffer_geometry_json, veg_indices, evi_vars, date_range,
|