backend: initial commit
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
"""GPS track simplification using the Ramer-Douglas-Peucker algorithm."""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from rdp import rdp
|
||||
|
||||
from bincio.extract.models import DataPoint
|
||||
|
||||
|
||||
def simplify_track(
|
||||
points: list[DataPoint],
|
||||
epsilon: float = 0.0001,
|
||||
) -> list[DataPoint]:
|
||||
"""Return a simplified subset of points using RDP.
|
||||
|
||||
epsilon is in degrees (~11m at equator for 0.0001).
|
||||
Points without GPS coordinates are dropped.
|
||||
"""
|
||||
gps_pts = [(p, p.lat, p.lon) for p in points if p.lat is not None and p.lon is not None]
|
||||
if len(gps_pts) < 2:
|
||||
return [p for p, _, _ in gps_pts]
|
||||
|
||||
coords = [[lon, lat] for _, lat, lon in gps_pts]
|
||||
mask = rdp(coords, epsilon=epsilon, return_mask=True)
|
||||
return [p for (p, _, _), keep in zip(gps_pts, mask) if keep]
|
||||
|
||||
|
||||
def build_geojson(
|
||||
points: list[DataPoint],
|
||||
activity_id: str,
|
||||
epsilon: float = 0.0001,
|
||||
original_count: Optional[int] = None,
|
||||
) -> dict:
|
||||
"""Build a GeoJSON Feature for the simplified track."""
|
||||
simplified = simplify_track(points, epsilon=epsilon)
|
||||
|
||||
coordinates = [
|
||||
[p.lon, p.lat, p.elevation_m] if p.elevation_m is not None else [p.lon, p.lat]
|
||||
for p in simplified
|
||||
if p.lon is not None and p.lat is not None
|
||||
]
|
||||
|
||||
# Parallel speed array for gradient coloring
|
||||
speeds = [round(p.speed_kmh, 2) if p.speed_kmh is not None else None for p in simplified]
|
||||
|
||||
return {
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": coordinates,
|
||||
},
|
||||
"properties": {
|
||||
"id": activity_id,
|
||||
"speeds": speeds,
|
||||
"simplification": "rdp",
|
||||
"rdp_epsilon": epsilon,
|
||||
"point_count_original": original_count or len(points),
|
||||
"point_count_simplified": len(coordinates),
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user