chat_back/app/coords/router.py
urec56 83e99edfa9
All checks were successful
/ build (push) Successful in 7m57s
/ deploy (push) Successful in 5m7s
Добавил обработку координат для жижи
2025-07-27 22:43:22 +03:00

89 lines
2.2 KiB
Python

from fastapi import APIRouter, status, UploadFile, HTTPException
from fastapi.responses import StreamingResponse
from io import BytesIO, StringIO
import simplekml
import gpxpy
import re
router = APIRouter(prefix="/coords", tags=["Координаты для жижи"])
@router.post(
"/map.kmz",
status_code=status.HTTP_200_OK,
)
async def create_chat(track_name: str, file: UploadFile):
try:
file = await file.read()
file = StringIO(file.decode("utf-8"))
kml = generate_kml(file, track_name)
kml.seek(0)
return StreamingResponse(
content=kml,
media_type="application/vnd.google-earth.kmz",
headers={"Content-Disposition": "attachment; filename=generated.kmz"}
)
except:
raise HTTPException(status_code=409, detail="Ты передал какую-то хуйню")
def generate_kml(file: StringIO, track_name: str):
buffer = BytesIO()
waypoints = []
kml = simplekml.Kml()
points = []
for line in file.readlines():
coords = line.split(":")
coord = coords[0].strip()
current_label = int(coords[1].strip())
lat, lon = parse_dms_string(coord)
name = f"Опора №{current_label}"
wpt = gpxpy.gpx.GPXWaypoint(latitude=lat, longitude=lon, name=name)
waypoints.append(wpt)
points.append((lon,lat))
linestring = kml.newlinestring(name=track_name)
linestring.coords = points
linestring.style.linestyle.width = 3
linestring.style.linestyle.color = simplekml.Color.red
for wpt in waypoints:
lat = wpt.latitude
lon = wpt.longitude
name = wpt.name
pnt = kml.newpoint(name=name, coords=[(lon, lat)]) # KML ожидает (lon, lat)
pnt.style.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png'
kml.savekmz(buffer)
return buffer
def parse_dms_string(dms_str):
pattern = r"(\d{1,3})°(\d{1,2})'(\d{1,2})\"([NSEW])"
matches = re.findall(pattern, dms_str)
if len(matches) != 2:
raise ValueError("Ожидалось две координаты в формате DMS")
def to_decimal(d, m, s, direction):
decimal = int(d) + int(m) / 60 + int(s) / 3600
if direction in ['S', 'W']:
decimal = -decimal
return decimal
lat = to_decimal(*matches[0])
lon = to_decimal(*matches[1])
return round(lat, 6), round(lon, 6)