2024-04-16 17:05:52 +00:00
|
|
|
from typing import Optional
|
|
|
|
|
2024-04-15 20:27:07 +00:00
|
|
|
import pygame
|
|
|
|
|
2024-04-16 16:42:01 +00:00
|
|
|
from gps_loader import GPSLoader
|
2024-04-15 20:27:07 +00:00
|
|
|
from map_display import MapDisplay
|
|
|
|
from path import Path
|
2024-04-16 16:42:01 +00:00
|
|
|
from units import Unit
|
2024-04-15 21:14:18 +00:00
|
|
|
from vec import Vec2
|
2024-04-15 20:27:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
class SpeedMapDisplay(MapDisplay):
|
|
|
|
def __init__(self,
|
|
|
|
surf: pygame.Surface,
|
|
|
|
min_lon: float,
|
|
|
|
max_lon: float,
|
2024-04-15 21:14:18 +00:00
|
|
|
min_lat: float,
|
|
|
|
max_lat: float,
|
2024-04-15 21:26:41 +00:00
|
|
|
cities: list[tuple[Vec2, str, str]],
|
2024-04-15 20:27:07 +00:00
|
|
|
min_speed_col: tuple[int, int, int],
|
|
|
|
max_speed_col: tuple[int, int, int],
|
|
|
|
segment_threshold: float):
|
2024-04-15 21:26:41 +00:00
|
|
|
super().__init__(surf, min_lon, max_lon, min_lat, max_lat, cities)
|
2024-04-15 20:27:07 +00:00
|
|
|
self.min_speed_col: tuple[int, int, int] = min_speed_col
|
|
|
|
self.max_speed_col: tuple[int, int, int] = max_speed_col
|
|
|
|
self.segment_threshold: float = segment_threshold
|
|
|
|
|
2024-04-16 17:05:52 +00:00
|
|
|
self._path: Optional[Path] = None
|
|
|
|
|
2024-04-15 20:27:07 +00:00
|
|
|
def draw_path(self, path: Path) -> None:
|
|
|
|
min_speed = min(path.extra_data)
|
|
|
|
max_speed = max(path.extra_data)
|
|
|
|
|
|
|
|
colors = list(map(lambda s: self.interpolate_color(s, min_speed, max_speed), path.extra_data))
|
|
|
|
|
|
|
|
self.draw_colored_path(path, colors)
|
|
|
|
|
2024-04-15 21:14:18 +00:00
|
|
|
in_segment = False
|
|
|
|
start_i = 0
|
|
|
|
for i, speed in enumerate(path.extra_data):
|
|
|
|
if speed >= self.segment_threshold:
|
|
|
|
if not in_segment:
|
|
|
|
in_segment = True
|
|
|
|
start_i = i
|
|
|
|
|
|
|
|
elif in_segment:
|
|
|
|
in_segment = False
|
|
|
|
self.draw_segment(path, start_i, i)
|
|
|
|
|
2024-04-15 20:27:07 +00:00
|
|
|
def interpolate_color(self, speed: float, min_speed: float, max_speed: float) -> tuple[int, int, int]:
|
|
|
|
r_span = self.max_speed_col[0] - self.min_speed_col[0]
|
|
|
|
g_span = self.max_speed_col[1] - self.min_speed_col[1]
|
|
|
|
b_span = self.max_speed_col[2] - self.min_speed_col[2]
|
|
|
|
|
|
|
|
f = (speed - min_speed) / (max_speed - min_speed)
|
|
|
|
r = int(r_span * f + self.min_speed_col[0])
|
|
|
|
g = int(g_span * f + self.min_speed_col[1])
|
|
|
|
b = int(b_span * f + self.min_speed_col[2])
|
|
|
|
|
|
|
|
return r, g, b
|
2024-04-16 16:42:01 +00:00
|
|
|
|
2024-04-16 17:05:52 +00:00
|
|
|
def render(self) -> None:
|
|
|
|
self.surf.fill((0, 0, 0))
|
|
|
|
self.draw_cities()
|
|
|
|
|
|
|
|
if self._path is not None:
|
|
|
|
self.draw_path(self._path)
|
|
|
|
|
|
|
|
def set_path(self, path: Path) -> None:
|
|
|
|
self._path = path
|
|
|
|
|
2024-04-16 16:42:01 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
name = "data_28-03"
|
|
|
|
cities = [
|
|
|
|
(Vec2(7.359119, 46.227302), "Sion", "above"),
|
|
|
|
(Vec2(7.079001, 46.105981), "Martigny", "below"),
|
|
|
|
(Vec2(7.001849, 46.216559), "Saint-Maurice", "right")
|
|
|
|
]
|
|
|
|
|
|
|
|
data = GPSLoader.load_data(f"{name}.csv")
|
|
|
|
speeds = list(map(lambda s: s.convert(Unit.KM_H).value, data["speeds"]))
|
|
|
|
path = Path(data["points"], speeds)
|
|
|
|
|
|
|
|
pygame.init()
|
|
|
|
|
|
|
|
win = pygame.display.set_mode([600, 600])
|
|
|
|
display = SpeedMapDisplay(
|
|
|
|
win,
|
|
|
|
6.971094, 7.430611,
|
|
|
|
46.076312, 46.253036,
|
|
|
|
cities,
|
|
|
|
(255, 0, 0), (0, 255, 0), 155)
|
|
|
|
|
2024-04-16 17:05:52 +00:00
|
|
|
display.set_path(path)
|
|
|
|
|
|
|
|
display.mainloop()
|