-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrenderer.py
More file actions
114 lines (96 loc) · 4.4 KB
/
renderer.py
File metadata and controls
114 lines (96 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import pygame
from constants import (
CELL_SIZE, GRID_SIZE, GRID_AREA_WIDTH, WINDOW_HEIGHT,
COLOR_BG, COLOR_GRID_LINE, COLOR_START, COLOR_END,
COLOR_OBSTACLE, COLOR_VISITED, COLOR_FRONTIER, COLOR_PATH,
COLOR_RRT_EDGE, COLOR_DYNAMIC_OBS,
)
class Renderer:
def __init__(self, surface: pygame.Surface, grid, cell_size: int):
self.surface = surface
self.grid = grid
self.cell_size = cell_size
def draw_grid_lines(self) -> None:
for r in range(GRID_SIZE + 1):
y = r * self.cell_size
pygame.draw.line(self.surface, COLOR_GRID_LINE,
(0, y), (GRID_AREA_WIDTH, y))
for c in range(GRID_SIZE + 1):
x = c * self.cell_size
pygame.draw.line(self.surface, COLOR_GRID_LINE,
(x, 0), (x, WINDOW_HEIGHT))
def draw_cell(self, row: int, col: int, color: tuple) -> None:
x = col * self.cell_size
y = row * self.cell_size
pygame.draw.rect(self.surface, color,
(x + 1, y + 1, self.cell_size - 1, self.cell_size - 1))
def draw_static_obstacles(self) -> None:
for (r, c) in self.grid.obstacles:
self.draw_cell(r, c, COLOR_OBSTACLE)
def draw_start_end(self) -> None:
if self.grid.start:
self.draw_cell(*self.grid.start, COLOR_START)
if self.grid.end:
self.draw_cell(*self.grid.end, COLOR_END)
def draw_visited_cells(self, visited: set) -> None:
for (r, c) in visited:
if (r, c) != self.grid.start and (r, c) != self.grid.end:
self.draw_cell(r, c, COLOR_VISITED)
def draw_frontier_cells(self, frontier: set) -> None:
for (r, c) in frontier:
if (r, c) != self.grid.start and (r, c) != self.grid.end:
self.draw_cell(r, c, COLOR_FRONTIER)
def draw_path_cells(self, path: list, color=None) -> None:
color = color or COLOR_PATH
for (r, c) in path:
if (r, c) != self.grid.start and (r, c) != self.grid.end:
self.draw_cell(r, c, color)
def draw_rrt_edges(self, edges: list) -> None:
for (n1, n2) in edges:
pygame.draw.line(self.surface, COLOR_RRT_EDGE,
(n1.x, n1.y), (n2.x, n2.y), 1)
def draw_rrt_path(self, path: list[tuple[float, float]], color=None) -> None:
if len(path) < 2:
return
color = color or COLOR_PATH
pygame.draw.lines(self.surface, color, False, path, 3)
def draw_dynamic_obstacles(self, obstacles: list) -> None:
for obs in obstacles:
pygame.draw.circle(self.surface, COLOR_DYNAMIC_OBS,
(int(obs.x), int(obs.y)), obs.radius)
pygame.draw.circle(self.surface, (255, 100, 100),
(int(obs.x), int(obs.y)), obs.radius, 2)
def draw_all(self, step_result, algorithm_type: str,
dynamic_obstacles: list, path_blocked: bool = False) -> None:
# Layer 1: grid lines
self.draw_grid_lines()
# Layer 2: static obstacles
self.draw_static_obstacles()
# Pick path color — flash between red and yellow when blocked
if path_blocked:
# Pulse red/orange based on frame time
tick = pygame.time.get_ticks()
if (tick // 300) % 2 == 0:
path_color = (255, 60, 60)
else:
path_color = (255, 140, 0)
else:
path_color = COLOR_PATH
# Layer 3: algorithm visualization
if step_result is not None:
if algorithm_type in ("RRT", "RRT*"):
if hasattr(step_result, 'tree_edges'):
self.draw_rrt_edges(step_result.tree_edges)
if step_result.path:
self.draw_rrt_path(step_result.path, path_color)
else:
if hasattr(step_result, 'visited') and step_result.visited:
self.draw_visited_cells(step_result.visited)
if hasattr(step_result, 'frontier') and step_result.frontier:
self.draw_frontier_cells(step_result.frontier)
if step_result.path:
self.draw_path_cells(step_result.path, path_color)
# Layer 4: start/end on top
self.draw_start_end()
# Layer 5: dynamic obstacles
self.draw_dynamic_obstacles(dynamic_obstacles)