Parsovani GPX
This commit is contained in:
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
from typing import List, Tuple, Dict
|
||||
|
||||
import aiohttp
|
||||
|
||||
|
||||
class ElevationAPI:
|
||||
ELEVATION_ENDPOINT = "https://api.open-elevation.com/api/v1/lookup"
|
||||
|
||||
def get_request(self, points: List[Dict[str, float]]):
|
||||
return {"locations": [{"latitude": point['lat'], "longitude": point['lng']} for point in points]}
|
||||
|
||||
async def call_api(self, points: List[Dict[str, float]]):
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(self.ELEVATION_ENDPOINT, json=self.get_request(points)) as resp:
|
||||
resp.raise_for_status()
|
||||
return await resp.json()
|
||||
|
||||
async def get_elevation_for_points(self, points: List[Dict[str, float]]) -> List[dict]:
|
||||
response = await self.call_api(points)
|
||||
|
||||
return [{
|
||||
"lat": loc['latitude'],
|
||||
"lng": loc['longitude'],
|
||||
"elevation": loc['elevation']
|
||||
} for loc in response['results']]
|
||||
Vendored
+93
@@ -0,0 +1,93 @@
|
||||
from datetime import datetime
|
||||
from typing import List, Dict
|
||||
|
||||
from aiocache import cached
|
||||
from lxml import etree
|
||||
from lxml.etree import _ElementTree
|
||||
|
||||
|
||||
class GPXParser:
|
||||
def __init__(self, file: str):
|
||||
self.file = file
|
||||
self.gpx = etree.parse(self.file)
|
||||
self.namespace = None
|
||||
self.precision_digits = 6
|
||||
self.set_namespace()
|
||||
|
||||
def set_namespace(self):
|
||||
namespace = self.gpx.getroot().nsmap.get(None)
|
||||
self.namespace = {'gpx': namespace}
|
||||
|
||||
def run_xpath(self, path: str):
|
||||
return self.gpx.xpath(path, namespaces=self.namespace)
|
||||
|
||||
@cached()
|
||||
async def get_times(self):
|
||||
nodes = self.run_xpath("//gpx:time")
|
||||
return [datetime.fromisoformat(node.text).astimezone() for node in nodes]
|
||||
|
||||
@cached()
|
||||
async def get_coordinates(self) -> List[Dict[str, float]]:
|
||||
nodes = self.run_xpath("//gpx:trkpt")
|
||||
return [{"lat": float(node.attrib["lat"]), "lng": float(node.attrib['lon'])} for node in nodes]
|
||||
|
||||
@cached()
|
||||
async def get_speed(self) -> List[int]:
|
||||
nodes = self.run_xpath("//gpx:speed")
|
||||
return [int(node.text) for node in nodes]
|
||||
|
||||
@cached()
|
||||
async def get_magnetic_variation(self) -> List[int]:
|
||||
nodes = self.run_xpath("//gpx:magvar")
|
||||
return [int(node.text) for node in nodes]
|
||||
|
||||
@cached()
|
||||
async def get_altitude(self) -> List[float]:
|
||||
nodes = self.run_xpath("//gpx:ele")
|
||||
return [float(node.text) for node in nodes]
|
||||
|
||||
@cached()
|
||||
async def get_terrain_elevation(self) -> List[float]:
|
||||
nodes = self.run_xpath("//gpx:terrain_elevation")
|
||||
return [float(node.text) for node in nodes]
|
||||
|
||||
@cached()
|
||||
async def get_max_speed(self):
|
||||
return max(await self.get_speed())
|
||||
|
||||
@cached()
|
||||
async def get_avg_speed(self):
|
||||
speeds = await self.get_speed()
|
||||
return round(sum(speeds) / len(speeds), 2)
|
||||
|
||||
@cached()
|
||||
async def get_max_altitude(self):
|
||||
return max(await self.get_altitude())
|
||||
|
||||
@cached()
|
||||
async def get_avg_altitude(self):
|
||||
altitudes = await self.get_altitude()
|
||||
return round(sum(altitudes) / len(altitudes), 2)
|
||||
|
||||
def add_terrain_elevation(self, points_with_elevation: List[Dict[str, float]]):
|
||||
track_points = self.run_xpath("//gpx:trkpt")
|
||||
# TODO: open elevation API umi jen presnost na 6 desetinnych mist!
|
||||
track_points_index = {(float(n.attrib['lat']), float(n.attrib['lon'])): n for n in track_points}
|
||||
|
||||
for point_with_elevation in points_with_elevation:
|
||||
lat = point_with_elevation['lat']
|
||||
lng = point_with_elevation['lng']
|
||||
elevation = point_with_elevation['elevation']
|
||||
target_node = track_points_index.get((lat, lng))
|
||||
|
||||
if target_node is None:
|
||||
continue
|
||||
|
||||
extensions = target_node.find("./extensions", self.gpx.getroot().nsmap)
|
||||
extensions.append(etree.XML(f"<terrain_elevation>{elevation}</terrain_elevation>"))
|
||||
|
||||
return self.gpx
|
||||
|
||||
def write(self, tree: _ElementTree, output: str):
|
||||
print(f"ZAPISUJI DO {output}")
|
||||
tree.write(output)
|
||||
Reference in New Issue
Block a user