valetudo-map-parser 0.1.9b50__py3-none-any.whl → 0.1.9b52__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,11 @@ from typing import Optional, Tuple
14
14
  import numpy as np
15
15
 
16
16
  from .drawable import Drawable
17
- from .drawable_elements import DrawableElement, DrawingConfig
17
+ from .drawable_elements import (
18
+ DrawableElement,
19
+ DrawingConfig,
20
+ )
21
+ from .colors import ColorsManagement
18
22
 
19
23
 
20
24
  # Type aliases
@@ -32,97 +36,13 @@ class EnhancedDrawable(Drawable):
32
36
  super().__init__()
33
37
  self.drawing_config = drawing_config or DrawingConfig()
34
38
 
35
- @staticmethod
36
- def blend_colors(base_color: Color, overlay_color: Color) -> Color:
37
- """
38
- Blend two RGBA colors, considering alpha channels.
39
-
40
- Args:
41
- base_color: The base RGBA color
42
- overlay_color: The overlay RGBA color to blend on top
43
-
44
- Returns:
45
- The blended RGBA color
46
- """
47
- # Extract components
48
- r1, g1, b1, a1 = base_color
49
- r2, g2, b2, a2 = overlay_color
50
-
51
- # Convert alpha to 0-1 range
52
- a1 = a1 / 255.0
53
- a2 = a2 / 255.0
54
-
55
- # Calculate resulting alpha
56
- a_out = a1 + a2 * (1 - a1)
57
-
58
- # Avoid division by zero
59
- if a_out < 0.0001:
60
- return (0, 0, 0, 0)
61
-
62
- # Calculate blended RGB components
63
- r_out = (r1 * a1 + r2 * a2 * (1 - a1)) / a_out
64
- g_out = (g1 * a1 + g2 * a2 * (1 - a1)) / a_out
65
- b_out = (b1 * a1 + b2 * a2 * (1 - a1)) / a_out
66
-
67
- # Convert back to 0-255 range and return as tuple
68
- return (
69
- int(max(0, min(255, int(r_out)))),
70
- int(max(0, min(255, int(g_out)))),
71
- int(max(0, min(255, int(b_out)))),
72
- int(max(0, min(255, int(a_out * 255)))),
73
- )
74
-
75
- def blend_pixel(
76
- self,
77
- array: NumpyArray,
78
- x: int,
79
- y: int,
80
- color: Color,
81
- element: DrawableElement,
82
- element_map: NumpyArray,
83
- ) -> None:
84
- """
85
- Blend a pixel color with the existing color at the specified position.
86
- Also updates the element map if the new element has higher z-index.
87
-
88
- Args:
89
- array: The image array to modify
90
- x, y: Pixel coordinates
91
- color: RGBA color to blend
92
- element: The element being drawn
93
- element_map: The element map to update
94
- """
95
- # Check bounds
96
- if not (0 <= y < array.shape[0] and 0 <= x < array.shape[1]):
97
- return
98
-
99
- # Get current element at this position
100
- current_element = element_map[y, x]
101
-
102
- # Get z-indices for comparison
103
- current_z = (
104
- self.drawing_config.get_property(current_element, "z_index", 0)
105
- if current_element
106
- else 0
107
- )
108
- new_z = self.drawing_config.get_property(element, "z_index", 0)
109
-
110
- # Get current color at this position
111
- current_color = tuple(array[y, x])
112
-
113
- # Blend colors
114
- blended_color = self.blend_colors(current_color, color)
39
+ # Color blending methods have been moved to ColorsManagement class in colors.py
115
40
 
116
- # Update pixel color
117
- array[y, x] = blended_color
118
-
119
- # Update element map if new element has higher z-index
120
- if new_z >= current_z:
121
- element_map[y, x] = element
41
+ # Pixel blending methods have been moved to ColorsManagement class in colors.py
122
42
 
123
43
  async def draw_map(
124
44
  self, map_data: dict, base_array: Optional[NumpyArray] = None
125
- ) -> Tuple[NumpyArray, NumpyArray]:
45
+ ) -> NumpyArray:
126
46
  """
127
47
  Draw the map with selected elements.
128
48
 
@@ -131,7 +51,7 @@ class EnhancedDrawable(Drawable):
131
51
  base_array: Optional base array to draw on
132
52
 
133
53
  Returns:
134
- Tuple of (image_array, element_map)
54
+ The image array with all elements drawn
135
55
  """
136
56
  # Get map dimensions
137
57
  size_x = map_data.get("size", {}).get("x", 1024)
@@ -144,81 +64,48 @@ class EnhancedDrawable(Drawable):
144
64
  )
145
65
  base_array = await self.create_empty_image(size_x, size_y, background_color)
146
66
 
147
- # Create a 2D map for element identification
148
- element_map = np.zeros(
149
- (base_array.shape[0], base_array.shape[1]), dtype=np.int32
150
- )
151
-
152
67
  # Draw elements in order of z-index
153
68
  for element in self.drawing_config.get_drawing_order():
154
69
  if element == DrawableElement.FLOOR:
155
- base_array, element_map = await self._draw_floor(
156
- map_data, base_array, element_map
157
- )
70
+ base_array = await self._draw_floor(map_data, base_array)
158
71
  elif element == DrawableElement.WALL:
159
- base_array, element_map = await self._draw_walls(
160
- map_data, base_array, element_map
161
- )
72
+ base_array = await self._draw_walls(map_data, base_array)
162
73
  elif element == DrawableElement.ROBOT:
163
- base_array, element_map = await self._draw_robot(
164
- map_data, base_array, element_map
165
- )
74
+ base_array = await self._draw_robot(map_data, base_array)
166
75
  elif element == DrawableElement.CHARGER:
167
- base_array, element_map = await self._draw_charger(
168
- map_data, base_array, element_map
169
- )
76
+ base_array = await self._draw_charger(map_data, base_array)
170
77
  elif element == DrawableElement.VIRTUAL_WALL:
171
- base_array, element_map = await self._draw_virtual_walls(
172
- map_data, base_array, element_map
173
- )
78
+ base_array = await self._draw_virtual_walls(map_data, base_array)
174
79
  elif element == DrawableElement.RESTRICTED_AREA:
175
- base_array, element_map = await self._draw_restricted_areas(
176
- map_data, base_array, element_map
177
- )
80
+ base_array = await self._draw_restricted_areas(map_data, base_array)
178
81
  elif element == DrawableElement.NO_MOP_AREA:
179
- base_array, element_map = await self._draw_no_mop_areas(
180
- map_data, base_array, element_map
181
- )
82
+ base_array = await self._draw_no_mop_areas(map_data, base_array)
182
83
  elif element == DrawableElement.PATH:
183
- base_array, element_map = await self._draw_path(
184
- map_data, base_array, element_map
185
- )
84
+ base_array = await self._draw_path(map_data, base_array)
186
85
  elif element == DrawableElement.PREDICTED_PATH:
187
- base_array, element_map = await self._draw_predicted_path(
188
- map_data, base_array, element_map
189
- )
86
+ base_array = await self._draw_predicted_path(map_data, base_array)
190
87
  elif element == DrawableElement.GO_TO_TARGET:
191
- base_array, element_map = await self._draw_go_to_target(
192
- map_data, base_array, element_map
193
- )
88
+ base_array = await self._draw_go_to_target(map_data, base_array)
194
89
  elif DrawableElement.ROOM_1 <= element <= DrawableElement.ROOM_15:
195
90
  room_id = element - DrawableElement.ROOM_1 + 1
196
- base_array, element_map = await self._draw_room(
197
- map_data, room_id, base_array, element_map
198
- )
91
+ base_array = await self._draw_room(map_data, room_id, base_array)
199
92
 
200
- return base_array, element_map
93
+ return base_array
201
94
 
202
- async def _draw_floor(
203
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
204
- ) -> Tuple[NumpyArray, NumpyArray]:
95
+ async def _draw_floor(self, map_data: dict, array: NumpyArray) -> NumpyArray:
205
96
  """Draw the floor layer."""
206
97
  if not self.drawing_config.is_enabled(DrawableElement.FLOOR):
207
- return array, element_map
98
+ return array
208
99
 
209
100
  # Implementation depends on the map data format
210
101
  # This is a placeholder - actual implementation would use map_data to draw floor
211
- # For now, we'll just mark the entire map as floor in the element map
212
- element_map[:] = DrawableElement.FLOOR
213
102
 
214
- return array, element_map
103
+ return array
215
104
 
216
- async def _draw_walls(
217
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
218
- ) -> Tuple[NumpyArray, NumpyArray]:
105
+ async def _draw_walls(self, map_data: dict, array: NumpyArray) -> NumpyArray:
219
106
  """Draw the walls."""
220
107
  if not self.drawing_config.is_enabled(DrawableElement.WALL):
221
- return array, element_map
108
+ return array
222
109
 
223
110
  # Get wall color from drawing config
224
111
  wall_color = self.drawing_config.get_property(
@@ -240,17 +127,19 @@ class EnhancedDrawable(Drawable):
240
127
 
241
128
  # Draw wall pixels with color blending
242
129
  for x, y in wall_pixels:
243
- # Use blend_pixel to properly blend colors and update element map
244
- self.blend_pixel(array, x, y, wall_color, DrawableElement.WALL, element_map)
130
+ # Use sample_and_blend_color from ColorsManagement
131
+ blended_color = ColorsManagement.sample_and_blend_color(
132
+ array, x, y, wall_color
133
+ )
134
+ if 0 <= y < array.shape[0] and 0 <= x < array.shape[1]:
135
+ array[y, x] = blended_color
245
136
 
246
- return array, element_map
137
+ return array
247
138
 
248
- async def _draw_robot(
249
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
250
- ) -> Tuple[NumpyArray, NumpyArray]:
139
+ async def _draw_robot(self, map_data: dict, array: NumpyArray) -> NumpyArray:
251
140
  """Draw the robot."""
252
141
  if not self.drawing_config.is_enabled(DrawableElement.ROBOT):
253
- return array, element_map
142
+ return array
254
143
 
255
144
  # Get robot color from drawing config
256
145
  robot_color = self.drawing_config.get_property(
@@ -271,23 +160,18 @@ class EnhancedDrawable(Drawable):
271
160
  for dx in range(-radius, radius + 1):
272
161
  if dx * dx + dy * dy <= radius * radius:
273
162
  map_x, map_y = int(x + dx), int(y + dy)
274
- # Use blend_pixel to properly blend colors and update element map
275
- self.blend_pixel(
276
- array,
277
- map_x,
278
- map_y,
279
- robot_color,
280
- DrawableElement.ROBOT,
281
- element_map,
163
+ # Use sample_and_blend_color from ColorsManagement
164
+ blended_color = ColorsManagement.sample_and_blend_color(
165
+ array, map_x, map_y, robot_color
282
166
  )
283
- return array, element_map
167
+ if 0 <= map_y < array.shape[0] and 0 <= map_x < array.shape[1]:
168
+ array[map_y, map_x] = blended_color
169
+ return array
284
170
 
285
- async def _draw_charger(
286
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
287
- ) -> Tuple[NumpyArray, NumpyArray]:
171
+ async def _draw_charger(self, map_data: dict, array: NumpyArray) -> NumpyArray:
288
172
  """Draw the charger."""
289
173
  if not self.drawing_config.is_enabled(DrawableElement.CHARGER):
290
- return array, element_map
174
+ return array
291
175
 
292
176
  # Get charger color from drawing config
293
177
  charger_color = self.drawing_config.get_property(
@@ -297,14 +181,14 @@ class EnhancedDrawable(Drawable):
297
181
  # Implementation depends on the map data format
298
182
  # This would extract charger data from map_data and draw it
299
183
 
300
- return array, element_map
184
+ return array
301
185
 
302
186
  async def _draw_virtual_walls(
303
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
304
- ) -> Tuple[NumpyArray, NumpyArray]:
187
+ self, map_data: dict, array: NumpyArray
188
+ ) -> NumpyArray:
305
189
  """Draw virtual walls."""
306
190
  if not self.drawing_config.is_enabled(DrawableElement.VIRTUAL_WALL):
307
- return array, element_map
191
+ return array
308
192
 
309
193
  # Get virtual wall color from drawing config
310
194
  wall_color = self.drawing_config.get_property(
@@ -314,14 +198,14 @@ class EnhancedDrawable(Drawable):
314
198
  # Implementation depends on the map data format
315
199
  # This would extract virtual wall data from map_data and draw it
316
200
 
317
- return array, element_map
201
+ return array
318
202
 
319
203
  async def _draw_restricted_areas(
320
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
321
- ) -> Tuple[NumpyArray, NumpyArray]:
204
+ self, map_data: dict, array: NumpyArray
205
+ ) -> NumpyArray:
322
206
  """Draw restricted areas."""
323
207
  if not self.drawing_config.is_enabled(DrawableElement.RESTRICTED_AREA):
324
- return array, element_map
208
+ return array
325
209
 
326
210
  # Get restricted area color from drawing config
327
211
  area_color = self.drawing_config.get_property(
@@ -331,14 +215,12 @@ class EnhancedDrawable(Drawable):
331
215
  # Implementation depends on the map data format
332
216
  # This would extract restricted area data from map_data and draw it
333
217
 
334
- return array, element_map
218
+ return array
335
219
 
336
- async def _draw_no_mop_areas(
337
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
338
- ) -> Tuple[NumpyArray, NumpyArray]:
220
+ async def _draw_no_mop_areas(self, map_data: dict, array: NumpyArray) -> NumpyArray:
339
221
  """Draw no-mop areas."""
340
222
  if not self.drawing_config.is_enabled(DrawableElement.NO_MOP_AREA):
341
- return array, element_map
223
+ return array
342
224
 
343
225
  # Get no-mop area color from drawing config
344
226
  area_color = self.drawing_config.get_property(
@@ -348,14 +230,12 @@ class EnhancedDrawable(Drawable):
348
230
  # Implementation depends on the map data format
349
231
  # This would extract no-mop area data from map_data and draw it
350
232
 
351
- return array, element_map
233
+ return array
352
234
 
353
- async def _draw_path(
354
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
355
- ) -> Tuple[NumpyArray, NumpyArray]:
235
+ async def _draw_path(self, map_data: dict, array: NumpyArray) -> NumpyArray:
356
236
  """Draw the robot's path."""
357
237
  if not self.drawing_config.is_enabled(DrawableElement.PATH):
358
- return array, element_map
238
+ return array
359
239
 
360
240
  # Get path color from drawing config
361
241
  path_color = self.drawing_config.get_property(
@@ -365,14 +245,14 @@ class EnhancedDrawable(Drawable):
365
245
  # Implementation depends on the map data format
366
246
  # This would extract path data from map_data and draw it
367
247
 
368
- return array, element_map
248
+ return array
369
249
 
370
250
  async def _draw_predicted_path(
371
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
372
- ) -> Tuple[NumpyArray, NumpyArray]:
251
+ self, map_data: dict, array: NumpyArray
252
+ ) -> NumpyArray:
373
253
  """Draw the predicted path."""
374
254
  if not self.drawing_config.is_enabled(DrawableElement.PREDICTED_PATH):
375
- return array, element_map
255
+ return array
376
256
 
377
257
  # Get predicted path color from drawing config
378
258
  path_color = self.drawing_config.get_property(
@@ -382,14 +262,12 @@ class EnhancedDrawable(Drawable):
382
262
  # Implementation depends on the map data format
383
263
  # This would extract predicted path data from map_data and draw it
384
264
 
385
- return array, element_map
265
+ return array
386
266
 
387
- async def _draw_go_to_target(
388
- self, map_data: dict, array: NumpyArray, element_map: NumpyArray
389
- ) -> Tuple[NumpyArray, NumpyArray]:
267
+ async def _draw_go_to_target(self, map_data: dict, array: NumpyArray) -> NumpyArray:
390
268
  """Draw the go-to target."""
391
269
  if not self.drawing_config.is_enabled(DrawableElement.GO_TO_TARGET):
392
- return array, element_map
270
+ return array
393
271
 
394
272
  # Get go-to target color from drawing config
395
273
  target_color = self.drawing_config.get_property(
@@ -399,15 +277,15 @@ class EnhancedDrawable(Drawable):
399
277
  # Implementation depends on the map data format
400
278
  # This would extract go-to target data from map_data and draw it
401
279
 
402
- return array, element_map
280
+ return array
403
281
 
404
282
  async def _draw_room(
405
- self, map_data: dict, room_id: int, array: NumpyArray, element_map: NumpyArray
406
- ) -> Tuple[NumpyArray, NumpyArray]:
283
+ self, map_data: dict, room_id: int, array: NumpyArray
284
+ ) -> NumpyArray:
407
285
  """Draw a specific room."""
408
286
  element = getattr(DrawableElement, f"ROOM_{room_id}")
409
287
  if not self.drawing_config.is_enabled(element):
410
- return array, element_map
288
+ return array
411
289
 
412
290
  # Get room color from drawing config
413
291
  room_color = self.drawing_config.get_property(
@@ -436,7 +314,11 @@ class EnhancedDrawable(Drawable):
436
314
 
437
315
  # Draw room pixels with color blending
438
316
  for x, y in room_pixels:
439
- # Use blend_pixel to properly blend colors and update element map
440
- self.blend_pixel(array, x, y, room_color, element, element_map)
317
+ # Use sample_and_blend_color from ColorsManagement
318
+ blended_color = ColorsManagement.sample_and_blend_color(
319
+ array, x, y, room_color
320
+ )
321
+ if 0 <= y < array.shape[0] and 0 <= x < array.shape[1]:
322
+ array[y, x] = blended_color
441
323
 
442
- return array, element_map
324
+ return array
@@ -107,7 +107,6 @@ class CameraShared:
107
107
  self.trims = TrimsData.from_dict(DEFAULT_VALUES["trims_data"]) # Trims data
108
108
  self.skip_room_ids: List[str] = []
109
109
  self.device_info = None # Store the device_info
110
- self.element_map = None # Map of element codes
111
110
 
112
111
  def update_user_colors(self, user_colors):
113
112
  """Update the user colors."""
@@ -8,7 +8,7 @@ import json
8
8
  import logging
9
9
  import threading
10
10
  from dataclasses import asdict, dataclass
11
- from typing import Any, Dict, Optional, Tuple, Union
11
+ from typing import Any, Dict, Optional, Tuple, Union, TypedDict
12
12
 
13
13
  import numpy as np
14
14
  from PIL import Image
@@ -19,17 +19,12 @@ DEFAULT_ROOMS = 1
19
19
  LOGGER = logging.getLogger(__package__)
20
20
 
21
21
 
22
- Color = Union[Tuple[int, int, int], Tuple[int, int, int, int]]
23
- Colors = Dict[str, Color]
24
- CalibrationPoints = list[dict[str, Any]]
25
- RobotPosition = dict[str, int | float]
26
- ChargerPosition = dict[str, Any]
27
- RoomsProperties = dict[str, dict[str, int | list[tuple[Any, Any]]]]
28
- ImageSize = dict[str, int | list[int]]
29
- JsonType = Any # json.loads() return type is Any
30
- PilPNG = Image.Image
31
- NumpyArray = np.ndarray
32
- Point = Tuple[int, int]
22
+ class RoomProperty(TypedDict):
23
+ number: int
24
+ outline: list[tuple[int, int]]
25
+ name: str
26
+ x: int
27
+ y: int
33
28
 
34
29
 
35
30
  # pylint: disable=no-member
@@ -77,21 +72,9 @@ class TrimCropData:
77
72
 
78
73
 
79
74
  class RoomStore:
80
- """
81
- Singleton RoomStore per vacuum_id.
82
-
83
- This class stores room data (a dictionary) for each vacuum.
84
- Calling RoomStore(vacuum_id, rooms_data) creates a new instance for that vacuum_id if it doesn't exist,
85
- or returns the existing one (optionally updating the data if rooms_data is provided).
86
- """
87
-
88
75
  _instances: Dict[str, "RoomStore"] = {}
89
76
  _lock = threading.Lock()
90
77
 
91
- # Declare instance attributes for static analysis tools like Pylint
92
- vacuum_id: str
93
- vacuums_data: dict
94
-
95
78
  def __new__(cls, vacuum_id: str, rooms_data: Optional[dict] = None) -> "RoomStore":
96
79
  with cls._lock:
97
80
  if vacuum_id not in cls._instances:
@@ -100,25 +83,17 @@ class RoomStore:
100
83
  instance.vacuums_data = rooms_data or {}
101
84
  cls._instances[vacuum_id] = instance
102
85
  else:
103
- # Update the instance's data if new rooms_data is provided.
104
86
  if rooms_data is not None:
105
87
  cls._instances[vacuum_id].vacuums_data = rooms_data
106
88
  return cls._instances[vacuum_id]
107
89
 
108
90
  def get_rooms(self) -> dict:
109
- """Return the stored rooms data."""
110
91
  return self.vacuums_data
111
92
 
112
93
  def set_rooms(self, rooms_data: dict) -> None:
113
- """Update the stored rooms data."""
114
94
  self.vacuums_data = rooms_data
115
95
 
116
96
  def get_rooms_count(self) -> int:
117
- """
118
- Return the number of rooms stored for this vacuum.
119
- This is simply the number of keys in the vacuums_data dictionary.
120
- If no data is stored, return the default number of rooms.
121
- """
122
97
  if isinstance(self.vacuums_data, dict):
123
98
  count = len(self.vacuums_data)
124
99
  return count if count > 0 else DEFAULT_ROOMS
@@ -126,7 +101,6 @@ class RoomStore:
126
101
 
127
102
  @classmethod
128
103
  def get_all_instances(cls) -> Dict[str, "RoomStore"]:
129
- """Return all active RoomStore instances (useful for debugging)."""
130
104
  return cls._instances
131
105
 
132
106
 
@@ -220,6 +194,18 @@ class SnapshotStore:
220
194
  self.vacuum_json_data[vacuum_id] = json_data
221
195
 
222
196
 
197
+ Color = Union[Tuple[int, int, int], Tuple[int, int, int, int]]
198
+ Colors = Dict[str, Color]
199
+ CalibrationPoints = list[dict[str, Any]]
200
+ RobotPosition = dict[str, int | float]
201
+ ChargerPosition = dict[str, Any]
202
+ RoomsProperties = dict[str, RoomProperty]
203
+ ImageSize = dict[str, int | list[int]]
204
+ JsonType = Any # json.loads() return type is Any
205
+ PilPNG = Image.Image
206
+ NumpyArray = np.ndarray
207
+ Point = Tuple[int, int]
208
+
223
209
  CAMERA_STORAGE = "valetudo_camera"
224
210
  ATTR_ROTATE = "rotate_image"
225
211
  ATTR_CROP = "crop_image"
@@ -696,73 +696,6 @@ def blend_pixel(array, x, y, color, element, element_map=None, drawing_config=No
696
696
  array[y, x] = blended_color
697
697
 
698
698
 
699
- def get_element_at_position(element_map, x, y):
700
- """
701
- Get the element code at a specific position in the element map.
702
-
703
- Args:
704
- element_map: The element map array
705
- x: X coordinate
706
- y: Y coordinate
707
-
708
- Returns:
709
- Element code or None if out of bounds
710
- """
711
- if element_map is not None:
712
- if 0 <= y < element_map.shape[0] and 0 <= x < element_map.shape[1]:
713
- return element_map[y, x]
714
- return None
715
-
716
-
717
- def get_room_at_position(element_map, x, y, room_base=101):
718
- """
719
- Get the room ID at a specific position, or None if not a room.
720
-
721
- Args:
722
- element_map: The element map array
723
- x: X coordinate
724
- y: Y coordinate
725
- room_base: Base value for room elements (default: 101 for DrawableElement.ROOM_1)
726
-
727
- Returns:
728
- Room ID (1-15) or None if not a room
729
- """
730
- element = get_element_at_position(element_map, x, y)
731
- if element is not None and room_base <= element <= room_base + 14: # 15 rooms max
732
- return element - room_base + 1
733
- return None
734
-
735
-
736
- def update_element_map_with_robot(
737
- element_map, robot_position, robot_element=3, robot_radius=25
738
- ):
739
- """
740
- Update the element map with the robot position.
741
-
742
- Args:
743
- element_map: The element map to update
744
- robot_position: Tuple of (x, y) coordinates for the robot
745
- robot_element: Element code for the robot (default: 3 for DrawableElement.ROBOT)
746
- robot_radius: Radius of the robot in pixels
747
-
748
- Returns:
749
- None
750
- """
751
- if element_map is None or robot_position is None:
752
- return
753
-
754
- # Update element map for robot position
755
- for dy in range(-robot_radius, robot_radius + 1):
756
- for dx in range(-robot_radius, robot_radius + 1):
757
- if dx * dx + dy * dy <= robot_radius * robot_radius:
758
- rx, ry = (
759
- int(robot_position[0] + dx),
760
- int(robot_position[1] + dy),
761
- )
762
- if 0 <= ry < element_map.shape[0] and 0 <= rx < element_map.shape[1]:
763
- element_map[ry, rx] = robot_element
764
-
765
-
766
699
  def manage_drawable_elements(
767
700
  handler,
768
701
  action,