valetudo-map-parser 0.1.2__py3-none-any.whl → 0.1.4__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.
- valetudo_map_parser/__init__.py +32 -0
- valetudo_map_parser/config/__init__.py +1 -0
- valetudo_map_parser/config/auto_crop.py +288 -0
- valetudo_map_parser/config/colors.py +178 -0
- valetudo_map_parser/config/drawable.py +561 -0
- valetudo_map_parser/config/shared.py +249 -0
- valetudo_map_parser/config/types.py +590 -0
- valetudo_map_parser/hypfer_draw.py +422 -0
- valetudo_map_parser/hypfer_handler.py +418 -0
- valetudo_map_parser/images_utils.py +398 -0
- valetudo_map_parser/map_data.py +510 -0
- valetudo_map_parser/py.typed +0 -0
- {valetudo_map_parser-0.1.2.dist-info → valetudo_map_parser-0.1.4.dist-info}/METADATA +2 -2
- valetudo_map_parser-0.1.4.dist-info/RECORD +17 -0
- __init__.py +0 -18
- valetudo_map_parser-0.1.2.dist-info/RECORD +0 -6
- {valetudo_map_parser-0.1.2.dist-info → valetudo_map_parser-0.1.4.dist-info}/LICENSE +0 -0
- {valetudo_map_parser-0.1.2.dist-info → valetudo_map_parser-0.1.4.dist-info}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.2.dist-info → valetudo_map_parser-0.1.4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,510 @@
|
|
1
|
+
"""
|
2
|
+
Collections of Json and List routines
|
3
|
+
ImageData is part of the Image_Handler
|
4
|
+
used functions to search data in the json
|
5
|
+
provided for the creation of the new camera frame
|
6
|
+
Version: v2024.08.0
|
7
|
+
"""
|
8
|
+
|
9
|
+
from __future__ import annotations
|
10
|
+
|
11
|
+
from typing import Any
|
12
|
+
import numpy as np
|
13
|
+
|
14
|
+
from .config.types import (
|
15
|
+
Colors,
|
16
|
+
ImageSize,
|
17
|
+
JsonType,
|
18
|
+
NumpyArray,
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
class ImageData:
|
23
|
+
"""Class to handle the image data."""
|
24
|
+
|
25
|
+
@staticmethod
|
26
|
+
async def async_extract_color_coordinates(
|
27
|
+
source_array: NumpyArray, search_for_colours_list: Colors
|
28
|
+
) -> list:
|
29
|
+
"""Search for specific colors in an image array and return their coordinates."""
|
30
|
+
# Initialize an empty list to store color and coordinates tuples
|
31
|
+
color_coordinates_list = []
|
32
|
+
|
33
|
+
# Iterate over the search_for_colours_list
|
34
|
+
for color_to_search in search_for_colours_list:
|
35
|
+
# Initialize an empty list to store coordinates for the current color
|
36
|
+
color_coordinates = []
|
37
|
+
|
38
|
+
# Iterate over the image array
|
39
|
+
for y in range(source_array.shape[0]):
|
40
|
+
for x in range(source_array.shape[1]):
|
41
|
+
# Extract the pixel color at the current coordinates
|
42
|
+
pixel_color = source_array[y, x]
|
43
|
+
|
44
|
+
# Check if the current pixel color matches the color_to_search
|
45
|
+
if np.all(pixel_color == color_to_search):
|
46
|
+
# Record the coordinates for the current color
|
47
|
+
color_coordinates.append((x, y))
|
48
|
+
|
49
|
+
# Append the color and its coordinates to the final list
|
50
|
+
color_coordinates_list.append((color_to_search, color_coordinates))
|
51
|
+
|
52
|
+
# Return the final list of color and coordinates tuples
|
53
|
+
return color_coordinates_list
|
54
|
+
|
55
|
+
@staticmethod
|
56
|
+
def sublist(lst, n):
|
57
|
+
"""Sub lists of specific n number of elements"""
|
58
|
+
return [lst[i : i + n] for i in range(0, len(lst), n)]
|
59
|
+
|
60
|
+
@staticmethod
|
61
|
+
def sublist_join(lst, n):
|
62
|
+
"""Join the lists in a unique list of n elements"""
|
63
|
+
arr = np.array(lst)
|
64
|
+
num_windows = len(lst) - n + 1
|
65
|
+
result = [arr[i : i + n].tolist() for i in range(num_windows)]
|
66
|
+
return result
|
67
|
+
|
68
|
+
# The below functions are basically the same ech one
|
69
|
+
# of them is allowing filtering and putting together in a
|
70
|
+
# list the specific Layers, Paths, Zones and Pints in the
|
71
|
+
# Vacuums Json in parallel.
|
72
|
+
|
73
|
+
@staticmethod
|
74
|
+
def find_layers(
|
75
|
+
json_obj: JsonType, layer_dict: dict, active_list: list
|
76
|
+
) -> tuple[dict, list]:
|
77
|
+
"""Find the layers in the json object."""
|
78
|
+
layer_dict = {} if layer_dict is None else layer_dict
|
79
|
+
active_list = [] if active_list is None else active_list
|
80
|
+
if isinstance(json_obj, dict):
|
81
|
+
if "__class" in json_obj and json_obj["__class"] == "MapLayer":
|
82
|
+
layer_type = json_obj.get("type")
|
83
|
+
active_type = json_obj.get("metaData")
|
84
|
+
if layer_type:
|
85
|
+
if layer_type not in layer_dict:
|
86
|
+
layer_dict[layer_type] = []
|
87
|
+
layer_dict[layer_type].append(json_obj.get("compressedPixels", []))
|
88
|
+
if layer_type == "segment":
|
89
|
+
active_list.append(int(active_type["active"]))
|
90
|
+
|
91
|
+
for value in json_obj.items():
|
92
|
+
ImageData.find_layers(value, layer_dict, active_list)
|
93
|
+
elif isinstance(json_obj, list):
|
94
|
+
for item in json_obj:
|
95
|
+
ImageData.find_layers(item, layer_dict, active_list)
|
96
|
+
return layer_dict, active_list
|
97
|
+
|
98
|
+
@staticmethod
|
99
|
+
def find_points_entities(json_obj: JsonType, entity_dict: dict = None) -> dict:
|
100
|
+
"""Find the points entities in the json object."""
|
101
|
+
if entity_dict is None:
|
102
|
+
entity_dict = {}
|
103
|
+
if isinstance(json_obj, dict):
|
104
|
+
if json_obj.get("__class") == "PointMapEntity":
|
105
|
+
entity_type = json_obj.get("type")
|
106
|
+
if entity_type:
|
107
|
+
entity_dict.setdefault(entity_type, []).append(json_obj)
|
108
|
+
for value in json_obj.values():
|
109
|
+
ImageData.find_points_entities(value, entity_dict)
|
110
|
+
elif isinstance(json_obj, list):
|
111
|
+
for item in json_obj:
|
112
|
+
ImageData.find_points_entities(item, entity_dict)
|
113
|
+
return entity_dict
|
114
|
+
|
115
|
+
@staticmethod
|
116
|
+
def find_paths_entities(json_obj: JsonType, entity_dict: dict = None) -> dict:
|
117
|
+
"""Find the paths entities in the json object."""
|
118
|
+
|
119
|
+
if entity_dict is None:
|
120
|
+
entity_dict = {}
|
121
|
+
if isinstance(json_obj, dict):
|
122
|
+
if json_obj.get("__class") == "PathMapEntity":
|
123
|
+
entity_type = json_obj.get("type")
|
124
|
+
if entity_type:
|
125
|
+
entity_dict.setdefault(entity_type, []).append(json_obj)
|
126
|
+
for value in json_obj.values():
|
127
|
+
ImageData.find_paths_entities(value, entity_dict)
|
128
|
+
elif isinstance(json_obj, list):
|
129
|
+
for item in json_obj:
|
130
|
+
ImageData.find_paths_entities(item, entity_dict)
|
131
|
+
return entity_dict
|
132
|
+
|
133
|
+
@staticmethod
|
134
|
+
def find_zone_entities(json_obj: JsonType, entity_dict: dict = None) -> dict:
|
135
|
+
"""Find the zone entities in the json object."""
|
136
|
+
if entity_dict is None:
|
137
|
+
entity_dict = {}
|
138
|
+
if isinstance(json_obj, dict):
|
139
|
+
if json_obj.get("__class") == "PolygonMapEntity":
|
140
|
+
entity_type = json_obj.get("type")
|
141
|
+
if entity_type:
|
142
|
+
entity_dict.setdefault(entity_type, []).append(json_obj)
|
143
|
+
for value in json_obj.values():
|
144
|
+
ImageData.find_zone_entities(value, entity_dict)
|
145
|
+
elif isinstance(json_obj, list):
|
146
|
+
for item in json_obj:
|
147
|
+
ImageData.find_zone_entities(item, entity_dict)
|
148
|
+
return entity_dict
|
149
|
+
|
150
|
+
@staticmethod
|
151
|
+
def find_virtual_walls(json_obj: JsonType) -> list:
|
152
|
+
"""Find the virtual walls in the json object."""
|
153
|
+
virtual_walls = []
|
154
|
+
|
155
|
+
def find_virtual_walls_recursive(obj):
|
156
|
+
"""Find the virtual walls in the json object recursively."""
|
157
|
+
if isinstance(obj, dict):
|
158
|
+
if obj.get("__class") == "LineMapEntity":
|
159
|
+
entity_type = obj.get("type")
|
160
|
+
if entity_type == "virtual_wall":
|
161
|
+
virtual_walls.append(obj["points"])
|
162
|
+
for value in obj.values():
|
163
|
+
find_virtual_walls_recursive(value)
|
164
|
+
elif isinstance(obj, list):
|
165
|
+
for item in obj:
|
166
|
+
find_virtual_walls_recursive(item)
|
167
|
+
|
168
|
+
find_virtual_walls_recursive(json_obj)
|
169
|
+
return virtual_walls
|
170
|
+
|
171
|
+
@staticmethod
|
172
|
+
async def async_get_rooms_coordinates(
|
173
|
+
pixels: list, pixel_size: int = 5, rand: bool = False
|
174
|
+
) -> tuple:
|
175
|
+
"""
|
176
|
+
Extract the room coordinates from the vacuum pixels data.
|
177
|
+
piexels: dict: The pixels data format [[x,y,z], [x1,y1,z1], [xn,yn,zn]].
|
178
|
+
pixel_size: int: The size of the pixel in mm (optional).
|
179
|
+
rand: bool: Return the coordinates in a rand256 format (optional).
|
180
|
+
"""
|
181
|
+
# Initialize variables to store max and min coordinates
|
182
|
+
max_x, max_y = pixels[0][0], pixels[0][1]
|
183
|
+
min_x, min_y = pixels[0][0], pixels[0][1]
|
184
|
+
# Iterate through the data list to find max and min coordinates
|
185
|
+
for entry in pixels:
|
186
|
+
if rand:
|
187
|
+
x, y, _ = entry # Extract x and y coordinates
|
188
|
+
max_x = max(max_x, x) # Update max x coordinate
|
189
|
+
max_y = max(max_y, y) # Update max y coordinate
|
190
|
+
min_x = min(min_x, x) # Update min x coordinate
|
191
|
+
min_y = min(min_y, y) # Update min y coordinate
|
192
|
+
else:
|
193
|
+
x, y, z = entry # Extract x and y coordinates
|
194
|
+
max_x = max(max_x, x + z) # Update max x coordinate
|
195
|
+
max_y = max(max_y, y + pixel_size) # Update max y coordinate
|
196
|
+
min_x = min(min_x, x) # Update min x coordinate
|
197
|
+
min_y = min(min_y, y) # Update min y coordinate
|
198
|
+
if rand:
|
199
|
+
return (
|
200
|
+
(((max_x * pixel_size) * 10), ((max_y * pixel_size) * 10)),
|
201
|
+
(
|
202
|
+
((min_x * pixel_size) * 10),
|
203
|
+
((min_y * pixel_size) * 10),
|
204
|
+
),
|
205
|
+
)
|
206
|
+
return (
|
207
|
+
min_x * pixel_size,
|
208
|
+
min_y * pixel_size,
|
209
|
+
max_x * pixel_size,
|
210
|
+
max_y * pixel_size,
|
211
|
+
)
|
212
|
+
|
213
|
+
# Added below in order to support Valetudo Re.
|
214
|
+
# This functions read directly the data from the json created
|
215
|
+
# from the parser for Valetudo Re. They allow to use the
|
216
|
+
# functions to draw the image without changes on the drawing class.
|
217
|
+
|
218
|
+
@staticmethod
|
219
|
+
def from_rrm_to_compressed_pixels(
|
220
|
+
pixel_data: list,
|
221
|
+
image_width: int = 0,
|
222
|
+
image_height: int = 0,
|
223
|
+
image_top: int = 0,
|
224
|
+
image_left: int = 0,
|
225
|
+
) -> list:
|
226
|
+
"""Convert the pixel data to compressed pixels."""
|
227
|
+
compressed_pixels = []
|
228
|
+
|
229
|
+
tot_pixels = 0
|
230
|
+
current_x, current_y, count = None, None, 0 # pylint: disable=unused-variable
|
231
|
+
for index in pixel_data:
|
232
|
+
x = (index % image_width) + image_left
|
233
|
+
y = ((image_height - 1) - (index // image_width)) + image_top
|
234
|
+
|
235
|
+
if current_x == x and current_y == y:
|
236
|
+
count += 1
|
237
|
+
else:
|
238
|
+
if current_x is not None:
|
239
|
+
compressed_pixels.append([current_x, current_y, count])
|
240
|
+
current_x, current_y, count = x, y, 1
|
241
|
+
tot_pixels += 1
|
242
|
+
if current_x is not None:
|
243
|
+
compressed_pixels.append([current_x, current_y, count])
|
244
|
+
return compressed_pixels
|
245
|
+
|
246
|
+
@staticmethod
|
247
|
+
def calculate_max_x_y(coord_array):
|
248
|
+
"""Calculate the max and min x and y coordinates."""
|
249
|
+
max_x = -float("inf")
|
250
|
+
max_y = -float("inf")
|
251
|
+
|
252
|
+
for x, y, _ in coord_array:
|
253
|
+
max_x = max(max_x, x)
|
254
|
+
max_y = max(max_y, y)
|
255
|
+
|
256
|
+
return (max_x * 6), (max_y * 6)
|
257
|
+
|
258
|
+
@staticmethod
|
259
|
+
def rrm_coordinates_to_valetudo(points):
|
260
|
+
"""Transform the coordinates from RRM to Valetudo."""
|
261
|
+
transformed_points = []
|
262
|
+
dimension_mm = 50 * 1024
|
263
|
+
for i, p in enumerate(points):
|
264
|
+
if i % 2 == 0:
|
265
|
+
transformed_points.append(round(p / 10))
|
266
|
+
else:
|
267
|
+
transformed_points.append(round((dimension_mm - p) / 10))
|
268
|
+
return transformed_points
|
269
|
+
|
270
|
+
@staticmethod
|
271
|
+
def rrm_valetudo_path_array(points):
|
272
|
+
"""Transform the path coordinates from RRM to Valetudo."""
|
273
|
+
transformed_points = []
|
274
|
+
for point in points:
|
275
|
+
transformed_x = round(point[0] / 10)
|
276
|
+
transformed_y = round(point[1] / 10)
|
277
|
+
transformed_points.extend([[transformed_x, transformed_y]])
|
278
|
+
return transformed_points
|
279
|
+
|
280
|
+
@staticmethod
|
281
|
+
def get_rrm_image(json_data: JsonType) -> JsonType:
|
282
|
+
"""Get the image data from the json."""
|
283
|
+
if isinstance(json_data, tuple):
|
284
|
+
return {}
|
285
|
+
return json_data.get("image", {})
|
286
|
+
|
287
|
+
@staticmethod
|
288
|
+
def get_rrm_path(json_data: JsonType) -> JsonType:
|
289
|
+
"""Get the path data from the json."""
|
290
|
+
return json_data.get("path", {})
|
291
|
+
|
292
|
+
@staticmethod
|
293
|
+
def get_rrm_goto_predicted_path(json_data: JsonType) -> list or None:
|
294
|
+
"""Get the predicted path data from the json."""
|
295
|
+
try:
|
296
|
+
predicted_path = json_data.get("goto_predicted_path", {})
|
297
|
+
points = predicted_path["points"]
|
298
|
+
except KeyError:
|
299
|
+
return None
|
300
|
+
predicted_path = ImageData.sublist_join(
|
301
|
+
ImageData.rrm_valetudo_path_array(points), 2
|
302
|
+
)
|
303
|
+
return predicted_path
|
304
|
+
|
305
|
+
@staticmethod
|
306
|
+
def get_rrm_charger_position(json_data: JsonType) -> JsonType:
|
307
|
+
"""Get the charger position from the json."""
|
308
|
+
return json_data.get("charger", {})
|
309
|
+
|
310
|
+
@staticmethod
|
311
|
+
def get_rrm_robot_position(json_data: JsonType) -> JsonType:
|
312
|
+
"""Get the robot position from the json."""
|
313
|
+
return json_data.get("robot", {})
|
314
|
+
|
315
|
+
@staticmethod
|
316
|
+
def get_rrm_robot_angle(json_data: JsonType) -> tuple:
|
317
|
+
"""
|
318
|
+
Get the robot angle from the json.
|
319
|
+
Return the calculated angle and original angle.
|
320
|
+
"""
|
321
|
+
angle_c = round(json_data.get("robot_angle", 0))
|
322
|
+
angle = (360 - angle_c + 80) if angle_c < 0 else (180 - angle_c - 80)
|
323
|
+
return angle % 360, json_data.get("robot_angle", 0)
|
324
|
+
|
325
|
+
@staticmethod
|
326
|
+
def get_rrm_goto_target(json_data: JsonType) -> list or None:
|
327
|
+
"""Get the goto target from the json."""
|
328
|
+
try:
|
329
|
+
path_data = json_data.get("goto_target", {})
|
330
|
+
except KeyError:
|
331
|
+
return None
|
332
|
+
|
333
|
+
if path_data and path_data != []:
|
334
|
+
path_data = ImageData.rrm_coordinates_to_valetudo(path_data)
|
335
|
+
return path_data
|
336
|
+
return None
|
337
|
+
|
338
|
+
@staticmethod
|
339
|
+
def get_rrm_currently_cleaned_zones(json_data: JsonType) -> dict:
|
340
|
+
"""Get the currently cleaned zones from the json."""
|
341
|
+
re_zones = json_data.get("currently_cleaned_zones", [])
|
342
|
+
formatted_zones = ImageData.rrm_valetudo_format_zone(re_zones)
|
343
|
+
return formatted_zones
|
344
|
+
|
345
|
+
@staticmethod
|
346
|
+
def get_rrm_forbidden_zones(json_data: JsonType) -> dict:
|
347
|
+
"""Get the forbidden zones from the json."""
|
348
|
+
re_zones = json_data.get("forbidden_zones", [])
|
349
|
+
formatted_zones = ImageData.rrm_valetudo_format_zone(re_zones)
|
350
|
+
return formatted_zones
|
351
|
+
|
352
|
+
@staticmethod
|
353
|
+
def rrm_valetudo_format_zone(coordinates: list) -> any:
|
354
|
+
"""Format the zones from RRM to Valetudo."""
|
355
|
+
formatted_zones = []
|
356
|
+
for zone_data in coordinates:
|
357
|
+
if len(zone_data) == 4: # This is a zone_clean (4 coordinates)
|
358
|
+
formatted_zone = {
|
359
|
+
"__class": "PolygonMapEntity",
|
360
|
+
"metaData": {},
|
361
|
+
"points": [
|
362
|
+
zone_data[0] // 10,
|
363
|
+
zone_data[1] // 10,
|
364
|
+
zone_data[2] // 10,
|
365
|
+
zone_data[1] // 10,
|
366
|
+
zone_data[2] // 10,
|
367
|
+
zone_data[3] // 10,
|
368
|
+
zone_data[0] // 10,
|
369
|
+
zone_data[3] // 10,
|
370
|
+
],
|
371
|
+
"type": "zone_clean",
|
372
|
+
}
|
373
|
+
formatted_zones.append(formatted_zone)
|
374
|
+
elif len(zone_data) == 8: # This is a no_go_area (8 coordinates)
|
375
|
+
formatted_zone = {
|
376
|
+
"__class": "PolygonMapEntity",
|
377
|
+
"metaData": {},
|
378
|
+
"points": [
|
379
|
+
zone_data[0] // 10,
|
380
|
+
zone_data[1] // 10,
|
381
|
+
zone_data[2] // 10,
|
382
|
+
zone_data[3] // 10,
|
383
|
+
zone_data[4] // 10,
|
384
|
+
zone_data[5] // 10,
|
385
|
+
zone_data[6] // 10,
|
386
|
+
zone_data[7] // 10,
|
387
|
+
],
|
388
|
+
"type": "no_go_area",
|
389
|
+
}
|
390
|
+
formatted_zones.append(formatted_zone)
|
391
|
+
|
392
|
+
return formatted_zones
|
393
|
+
|
394
|
+
@staticmethod
|
395
|
+
def rrm_valetudo_lines(coordinates: list) -> list:
|
396
|
+
"""Format the lines from RRM to Valetudo."""
|
397
|
+
formatted_lines = []
|
398
|
+
for lines in coordinates:
|
399
|
+
line = [lines[0] // 10, lines[1] // 10, lines[2] // 10, lines[3] // 10]
|
400
|
+
formatted_lines.append(line)
|
401
|
+
return formatted_lines
|
402
|
+
|
403
|
+
@staticmethod
|
404
|
+
def get_rrm_virtual_walls(json_data: JsonType) -> list or None:
|
405
|
+
"""Get the virtual walls from the json."""
|
406
|
+
try:
|
407
|
+
tmp_data = json_data.get("virtual_walls", [])
|
408
|
+
except KeyError:
|
409
|
+
return None
|
410
|
+
virtual_walls = ImageData.rrm_valetudo_lines(tmp_data)
|
411
|
+
return virtual_walls
|
412
|
+
|
413
|
+
@staticmethod
|
414
|
+
def get_rrm_currently_cleaned_blocks(json_data: JsonType) -> list:
|
415
|
+
"""Get the currently cleaned blocks from the json."""
|
416
|
+
return json_data.get("currently_cleaned_blocks", [])
|
417
|
+
|
418
|
+
@staticmethod
|
419
|
+
def get_rrm_forbidden_mop_zones(json_data: JsonType) -> list:
|
420
|
+
"""Get the forbidden mop zones from the json."""
|
421
|
+
return json_data.get("forbidden_mop_zones", [])
|
422
|
+
|
423
|
+
@staticmethod
|
424
|
+
def get_rrm_image_size(json_data: JsonType) -> ImageSize:
|
425
|
+
"""Get the image size from the json."""
|
426
|
+
if isinstance(json_data, tuple):
|
427
|
+
return 0, 0
|
428
|
+
image = ImageData.get_rrm_image(json_data)
|
429
|
+
if image == {}:
|
430
|
+
return 0, 0
|
431
|
+
dimensions = image.get("dimensions", {})
|
432
|
+
return dimensions.get("width", 0), dimensions.get("height", 0)
|
433
|
+
|
434
|
+
@staticmethod
|
435
|
+
def get_rrm_image_position(json_data: JsonType) -> tuple:
|
436
|
+
"""Get the image position from the json."""
|
437
|
+
image = ImageData.get_rrm_image(json_data)
|
438
|
+
position = image.get("position", {})
|
439
|
+
return position.get("top", 0), position.get("left", 0)
|
440
|
+
|
441
|
+
@staticmethod
|
442
|
+
def get_rrm_floor(json_data: JsonType) -> list:
|
443
|
+
"""Get the floor data from the json."""
|
444
|
+
img = ImageData.get_rrm_image(json_data)
|
445
|
+
return img.get("pixels", {}).get("floor", [])
|
446
|
+
|
447
|
+
@staticmethod
|
448
|
+
def get_rrm_walls(json_data: JsonType) -> list:
|
449
|
+
"""Get the walls data from the json."""
|
450
|
+
img = ImageData.get_rrm_image(json_data)
|
451
|
+
return img.get("pixels", {}).get("walls", [])
|
452
|
+
|
453
|
+
@staticmethod
|
454
|
+
async def async_get_rrm_segments(
|
455
|
+
json_data: JsonType,
|
456
|
+
size_x: int,
|
457
|
+
size_y: int,
|
458
|
+
pos_top: int,
|
459
|
+
pos_left: int,
|
460
|
+
out_lines: bool = False,
|
461
|
+
) -> tuple or list:
|
462
|
+
"""Get the segments data from the json."""
|
463
|
+
|
464
|
+
img = ImageData.get_rrm_image(json_data)
|
465
|
+
seg_data = img.get("segments", {})
|
466
|
+
seg_ids = seg_data.get("id")
|
467
|
+
segments = []
|
468
|
+
outlines = []
|
469
|
+
count_seg = 0
|
470
|
+
for id_seg in seg_ids:
|
471
|
+
tmp_data = seg_data.get("pixels_seg_" + str(id_seg))
|
472
|
+
segments.append(
|
473
|
+
ImageData.from_rrm_to_compressed_pixels(
|
474
|
+
tmp_data,
|
475
|
+
image_width=size_x,
|
476
|
+
image_height=size_y,
|
477
|
+
image_top=pos_top,
|
478
|
+
image_left=pos_left,
|
479
|
+
)
|
480
|
+
)
|
481
|
+
if out_lines:
|
482
|
+
room_coords = await ImageData.async_get_rooms_coordinates(
|
483
|
+
pixels=segments[count_seg], rand=True
|
484
|
+
)
|
485
|
+
outlines.append(room_coords)
|
486
|
+
count_seg += 1
|
487
|
+
if count_seg > 0:
|
488
|
+
if out_lines:
|
489
|
+
return segments, outlines
|
490
|
+
return segments
|
491
|
+
return []
|
492
|
+
|
493
|
+
@staticmethod
|
494
|
+
def get_rrm_segments_ids(json_data: JsonType) -> list or None:
|
495
|
+
"""Get the segments ids from the json."""
|
496
|
+
try:
|
497
|
+
img = ImageData.get_rrm_image(json_data)
|
498
|
+
seg_ids = img.get("segments", {}).get("id", [])
|
499
|
+
except KeyError:
|
500
|
+
return None
|
501
|
+
return seg_ids
|
502
|
+
|
503
|
+
@staticmethod
|
504
|
+
def convert_negative_angle(angle: int) -> int:
|
505
|
+
"""Convert negative angle to positive."""
|
506
|
+
angle_c = angle % 360 # Ensure angle is within 0-359
|
507
|
+
if angle_c < 0:
|
508
|
+
angle_c += 360 # Convert negative angle to positive
|
509
|
+
angle = angle_c + 180 # add offset
|
510
|
+
return angle
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: valetudo-map-parser
|
3
|
-
Version: 0.1.
|
4
|
-
Summary: A Python library to parse Valetudo map data returning a PIL Image object
|
3
|
+
Version: 0.1.4
|
4
|
+
Summary: A Python library to parse Valetudo map data returning a PIL Image object.
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: Sandro Cantarella
|
7
7
|
Author-email: gsca075@gmail.com
|
@@ -0,0 +1,17 @@
|
|
1
|
+
valetudo_map_parser/__init__.py,sha256=SYv1w4Zf6ADLJ6yC6W8vhzQ96DicDRSP3yuf6ijmlxc,683
|
2
|
+
valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
|
3
|
+
valetudo_map_parser/config/auto_crop.py,sha256=eTzMVhaeP7SP2-65jefE4toAigkZM6XUoARsSB5JwH8,10927
|
4
|
+
valetudo_map_parser/config/colors.py,sha256=HlgROKagpV7FP9LTU1IvhTKTYjnlBw1ZDMKHVJSct8M,6514
|
5
|
+
valetudo_map_parser/config/drawable.py,sha256=8Fp4yqyFbsGvNyCEynYCTpiohRZk_plUSSOyHpECvj8,20356
|
6
|
+
valetudo_map_parser/config/shared.py,sha256=8xYBUfKY-tiPhXaT5ttIasnCWL3_RLawIZeTValQC64,9462
|
7
|
+
valetudo_map_parser/config/types.py,sha256=bVSEDE0ihrc01jG4fZ1_hUVtoj6hdkbqShytZ6wJwJY,16163
|
8
|
+
valetudo_map_parser/hypfer_draw.py,sha256=R8JVrqPPavhj8exCDJKk1QsXgsB12cjy4AIgFffyQec,15773
|
9
|
+
valetudo_map_parser/hypfer_handler.py,sha256=PCdfzLpGZD0zXvVufFWadPc-xDqbtsnArfPW0PWViU4,18469
|
10
|
+
valetudo_map_parser/images_utils.py,sha256=Ls5OnXXcojBTuUagj3_N4tY3nOe9aot7gl5hrPCXKss,15262
|
11
|
+
valetudo_map_parser/map_data.py,sha256=-6etLFZXZikFEUeR2YhPLgXu7dv3YRY2e-u5Mx9ogqw,19498
|
12
|
+
valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
valetudo_map_parser-0.1.4.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
14
|
+
valetudo_map_parser-0.1.4.dist-info/METADATA,sha256=qsrU3YyxUwjsKvqo6IReZAneO_6KIAVHVvdVDLYlTMA,1026
|
15
|
+
valetudo_map_parser-0.1.4.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
16
|
+
valetudo_map_parser-0.1.4.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
17
|
+
valetudo_map_parser-0.1.4.dist-info/RECORD,,
|
__init__.py
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
"""Valetudo Map Parser."""
|
2
|
-
from SCR.valetudo_map_parser.hypfer_handler import HypferMapImageHandler
|
3
|
-
from SCR.valetudo_map_parser.config.shared import CameraShared, CameraSharedManager
|
4
|
-
|
5
|
-
__all__ = [
|
6
|
-
"HypferMapImageHandler",
|
7
|
-
"CameraShared",
|
8
|
-
"CameraSharedManager",
|
9
|
-
"ColorsManagment",
|
10
|
-
"SnapshotStore",
|
11
|
-
"UserLanguageStore",
|
12
|
-
"UserLanguageStore",
|
13
|
-
"SnapshotStore",
|
14
|
-
"RoomStore",
|
15
|
-
"RoomsProperties",
|
16
|
-
"TrimCropData",
|
17
|
-
"CameraModes",
|
18
|
-
]
|
@@ -1,6 +0,0 @@
|
|
1
|
-
__init__.py,sha256=a9BnpCeG7Ewj34CgO6wjM0RfEyCDURSCHO0gvWbPK_0,469
|
2
|
-
valetudo_map_parser-0.1.2.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
3
|
-
valetudo_map_parser-0.1.2.dist-info/METADATA,sha256=zs5So0xm53-aW0zVrv9a9mg10ii3esC6O6tU4_CHoqQ,1025
|
4
|
-
valetudo_map_parser-0.1.2.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
5
|
-
valetudo_map_parser-0.1.2.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
6
|
-
valetudo_map_parser-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|