valetudo-map-parser 0.1.8__py3-none-any.whl → 0.1.9__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.
Files changed (30) hide show
  1. valetudo_map_parser/__init__.py +28 -13
  2. valetudo_map_parser/config/async_utils.py +93 -0
  3. valetudo_map_parser/config/auto_crop.py +312 -123
  4. valetudo_map_parser/config/color_utils.py +105 -0
  5. valetudo_map_parser/config/colors.py +662 -13
  6. valetudo_map_parser/config/drawable.py +613 -268
  7. valetudo_map_parser/config/drawable_elements.py +292 -0
  8. valetudo_map_parser/config/enhanced_drawable.py +324 -0
  9. valetudo_map_parser/config/optimized_element_map.py +406 -0
  10. valetudo_map_parser/config/rand256_parser.py +395 -0
  11. valetudo_map_parser/config/shared.py +94 -11
  12. valetudo_map_parser/config/types.py +105 -52
  13. valetudo_map_parser/config/utils.py +1025 -0
  14. valetudo_map_parser/hypfer_draw.py +464 -148
  15. valetudo_map_parser/hypfer_handler.py +366 -259
  16. valetudo_map_parser/hypfer_rooms_handler.py +599 -0
  17. valetudo_map_parser/map_data.py +56 -66
  18. valetudo_map_parser/rand256_handler.py +674 -0
  19. valetudo_map_parser/reimg_draw.py +68 -84
  20. valetudo_map_parser/rooms_handler.py +474 -0
  21. valetudo_map_parser-0.1.9.dist-info/METADATA +93 -0
  22. valetudo_map_parser-0.1.9.dist-info/RECORD +27 -0
  23. {valetudo_map_parser-0.1.8.dist-info → valetudo_map_parser-0.1.9.dist-info}/WHEEL +1 -1
  24. valetudo_map_parser/config/rand25_parser.py +0 -398
  25. valetudo_map_parser/images_utils.py +0 -398
  26. valetudo_map_parser/rand25_handler.py +0 -455
  27. valetudo_map_parser-0.1.8.dist-info/METADATA +0 -23
  28. valetudo_map_parser-0.1.8.dist-info/RECORD +0 -20
  29. {valetudo_map_parser-0.1.8.dist-info → valetudo_map_parser-0.1.9.dist-info}/LICENSE +0 -0
  30. {valetudo_map_parser-0.1.8.dist-info → valetudo_map_parser-0.1.9.dist-info}/NOTICE.txt +0 -0
@@ -10,47 +10,12 @@ from __future__ import annotations
10
10
 
11
11
  import numpy as np
12
12
 
13
- from .config.types import (
14
- Colors,
15
- ImageSize,
16
- JsonType,
17
- NumpyArray,
18
- )
13
+ from .config.types import ImageSize, JsonType
19
14
 
20
15
 
21
16
  class ImageData:
22
17
  """Class to handle the image data."""
23
18
 
24
- @staticmethod
25
- async def async_extract_color_coordinates(
26
- source_array: NumpyArray, search_for_colours_list: Colors
27
- ) -> list:
28
- """Search for specific colors in an image array and return their coordinates."""
29
- # Initialize an empty list to store color and coordinates tuples
30
- color_coordinates_list = []
31
-
32
- # Iterate over the search_for_colours_list
33
- for color_to_search in search_for_colours_list:
34
- # Initialize an empty list to store coordinates for the current color
35
- color_coordinates = []
36
-
37
- # Iterate over the image array
38
- for y in range(source_array.shape[0]):
39
- for x in range(source_array.shape[1]):
40
- # Extract the pixel color at the current coordinates
41
- pixel_color = source_array[y, x]
42
-
43
- # Check if the current pixel color matches the color_to_search
44
- if np.all(pixel_color == color_to_search):
45
- # Record the coordinates for the current color
46
- color_coordinates.append((x, y))
47
-
48
- # Append the color and its coordinates to the final list
49
- color_coordinates_list.append((color_to_search, color_coordinates))
50
-
51
- # Return the final list of color and coordinates tuples
52
- return color_coordinates_list
53
-
54
19
  @staticmethod
55
20
  def sublist(lst, n):
56
21
  """Sub lists of specific n number of elements"""
@@ -69,6 +34,30 @@ class ImageData:
69
34
  # list the specific Layers, Paths, Zones and Pints in the
70
35
  # Vacuums Json in parallel.
71
36
 
37
+ @staticmethod
38
+ def get_obstacles(entity_dict: dict) -> list:
39
+ """Get the obstacles positions from the entity data."""
40
+ try:
41
+ obstacle_data = entity_dict.get("obstacle")
42
+ except KeyError:
43
+ return []
44
+ obstacle_positions = []
45
+ if obstacle_data:
46
+ for obstacle in obstacle_data:
47
+ label = obstacle.get("metaData", {}).get("label")
48
+ points = obstacle.get("points", [])
49
+ image_id = obstacle.get("metaData", {}).get("id")
50
+
51
+ if label and points:
52
+ obstacle_pos = {
53
+ "label": label,
54
+ "points": {"x": points[0], "y": points[1]},
55
+ "id": image_id,
56
+ }
57
+ obstacle_positions.append(obstacle_pos)
58
+ return obstacle_positions
59
+ return []
60
+
72
61
  @staticmethod
73
62
  def find_layers(
74
63
  json_obj: JsonType, layer_dict: dict, active_list: list
@@ -209,10 +198,11 @@ class ImageData:
209
198
  max_y * pixel_size,
210
199
  )
211
200
 
212
- # Added below in order to support Valetudo Re.
213
- # This functions read directly the data from the json created
214
- # from the parser for Valetudo Re. They allow to use the
215
- # functions to draw the image without changes on the drawing class.
201
+
202
+ class RandImageData:
203
+ """This functions read directly the data from the json created
204
+ from the parser for Valetudo Re. They allow to use the
205
+ functions to draw the image without changes on the drawing class."""
216
206
 
217
207
  @staticmethod
218
208
  def from_rrm_to_compressed_pixels(
@@ -243,7 +233,7 @@ class ImageData:
243
233
  return compressed_pixels
244
234
 
245
235
  @staticmethod
246
- def calculate_max_x_y(coord_array):
236
+ def _calculate_max_x_y(coord_array):
247
237
  """Calculate the max and min x and y coordinates."""
248
238
  max_x = -float("inf")
249
239
  max_y = -float("inf")
@@ -297,7 +287,7 @@ class ImageData:
297
287
  except KeyError:
298
288
  return None
299
289
  predicted_path = ImageData.sublist_join(
300
- ImageData.rrm_valetudo_path_array(points), 2
290
+ RandImageData.rrm_valetudo_path_array(points), 2
301
291
  )
302
292
  return predicted_path
303
293
 
@@ -318,8 +308,17 @@ class ImageData:
318
308
  Return the calculated angle and original angle.
319
309
  """
320
310
  angle_c = round(json_data.get("robot_angle", 0))
321
- angle = (360 - angle_c + 80) if angle_c < 0 else (180 - angle_c - 80)
322
- return angle % 360, json_data.get("robot_angle", 0)
311
+ # Convert negative values: -10 -> 350, -180 -> 359, but keep positive: 24 -> 24
312
+ if angle_c < 0:
313
+ if angle_c == -180:
314
+ angle = 359 # -180 becomes 359 (avoiding 360)
315
+ else:
316
+ angle = 360 + angle_c # -10 -> 350, -90 -> 270
317
+ else:
318
+ angle = angle_c
319
+
320
+ angle = (angle + 90) % 360
321
+ return angle, json_data.get("robot_angle", 0)
323
322
 
324
323
  @staticmethod
325
324
  def get_rrm_goto_target(json_data: JsonType) -> list or None:
@@ -330,7 +329,7 @@ class ImageData:
330
329
  return None
331
330
 
332
331
  if path_data and path_data != []:
333
- path_data = ImageData.rrm_coordinates_to_valetudo(path_data)
332
+ path_data = RandImageData.rrm_coordinates_to_valetudo(path_data)
334
333
  return path_data
335
334
  return None
336
335
 
@@ -338,18 +337,18 @@ class ImageData:
338
337
  def get_rrm_currently_cleaned_zones(json_data: JsonType) -> dict:
339
338
  """Get the currently cleaned zones from the json."""
340
339
  re_zones = json_data.get("currently_cleaned_zones", [])
341
- formatted_zones = ImageData.rrm_valetudo_format_zone(re_zones)
340
+ formatted_zones = RandImageData._rrm_valetudo_format_zone(re_zones)
342
341
  return formatted_zones
343
342
 
344
343
  @staticmethod
345
344
  def get_rrm_forbidden_zones(json_data: JsonType) -> dict:
346
345
  """Get the forbidden zones from the json."""
347
346
  re_zones = json_data.get("forbidden_zones", [])
348
- formatted_zones = ImageData.rrm_valetudo_format_zone(re_zones)
347
+ formatted_zones = RandImageData._rrm_valetudo_format_zone(re_zones)
349
348
  return formatted_zones
350
349
 
351
350
  @staticmethod
352
- def rrm_valetudo_format_zone(coordinates: list) -> any:
351
+ def _rrm_valetudo_format_zone(coordinates: list) -> any:
353
352
  """Format the zones from RRM to Valetudo."""
354
353
  formatted_zones = []
355
354
  for zone_data in coordinates:
@@ -391,7 +390,7 @@ class ImageData:
391
390
  return formatted_zones
392
391
 
393
392
  @staticmethod
394
- def rrm_valetudo_lines(coordinates: list) -> list:
393
+ def _rrm_valetudo_lines(coordinates: list) -> list:
395
394
  """Format the lines from RRM to Valetudo."""
396
395
  formatted_lines = []
397
396
  for lines in coordinates:
@@ -406,7 +405,7 @@ class ImageData:
406
405
  tmp_data = json_data.get("virtual_walls", [])
407
406
  except KeyError:
408
407
  return None
409
- virtual_walls = ImageData.rrm_valetudo_lines(tmp_data)
408
+ virtual_walls = RandImageData._rrm_valetudo_lines(tmp_data)
410
409
  return virtual_walls
411
410
 
412
411
  @staticmethod
@@ -424,7 +423,7 @@ class ImageData:
424
423
  """Get the image size from the json."""
425
424
  if isinstance(json_data, tuple):
426
425
  return 0, 0
427
- image = ImageData.get_rrm_image(json_data)
426
+ image = RandImageData.get_rrm_image(json_data)
428
427
  if image == {}:
429
428
  return 0, 0
430
429
  dimensions = image.get("dimensions", {})
@@ -433,20 +432,20 @@ class ImageData:
433
432
  @staticmethod
434
433
  def get_rrm_image_position(json_data: JsonType) -> tuple:
435
434
  """Get the image position from the json."""
436
- image = ImageData.get_rrm_image(json_data)
435
+ image = RandImageData.get_rrm_image(json_data)
437
436
  position = image.get("position", {})
438
437
  return position.get("top", 0), position.get("left", 0)
439
438
 
440
439
  @staticmethod
441
440
  def get_rrm_floor(json_data: JsonType) -> list:
442
441
  """Get the floor data from the json."""
443
- img = ImageData.get_rrm_image(json_data)
442
+ img = RandImageData.get_rrm_image(json_data)
444
443
  return img.get("pixels", {}).get("floor", [])
445
444
 
446
445
  @staticmethod
447
446
  def get_rrm_walls(json_data: JsonType) -> list:
448
447
  """Get the walls data from the json."""
449
- img = ImageData.get_rrm_image(json_data)
448
+ img = RandImageData.get_rrm_image(json_data)
450
449
  return img.get("pixels", {}).get("walls", [])
451
450
 
452
451
  @staticmethod
@@ -460,7 +459,7 @@ class ImageData:
460
459
  ) -> tuple or list:
461
460
  """Get the segments data from the json."""
462
461
 
463
- img = ImageData.get_rrm_image(json_data)
462
+ img = RandImageData.get_rrm_image(json_data)
464
463
  seg_data = img.get("segments", {})
465
464
  seg_ids = seg_data.get("id")
466
465
  segments = []
@@ -469,7 +468,7 @@ class ImageData:
469
468
  for id_seg in seg_ids:
470
469
  tmp_data = seg_data.get("pixels_seg_" + str(id_seg))
471
470
  segments.append(
472
- ImageData.from_rrm_to_compressed_pixels(
471
+ RandImageData.from_rrm_to_compressed_pixels(
473
472
  tmp_data,
474
473
  image_width=size_x,
475
474
  image_height=size_y,
@@ -493,17 +492,8 @@ class ImageData:
493
492
  def get_rrm_segments_ids(json_data: JsonType) -> list or None:
494
493
  """Get the segments ids from the json."""
495
494
  try:
496
- img = ImageData.get_rrm_image(json_data)
495
+ img = RandImageData.get_rrm_image(json_data)
497
496
  seg_ids = img.get("segments", {}).get("id", [])
498
497
  except KeyError:
499
498
  return None
500
499
  return seg_ids
501
-
502
- @staticmethod
503
- def convert_negative_angle(angle: int) -> int:
504
- """Convert negative angle to positive."""
505
- angle_c = angle % 360 # Ensure angle is within 0-359
506
- if angle_c < 0:
507
- angle_c += 360 # Convert negative angle to positive
508
- angle = angle_c + 180 # add offset
509
- return angle