maps4fs 1.6.0__py3-none-any.whl → 1.6.2__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.
@@ -148,6 +148,9 @@ class Background(Component):
148
148
  "east": east,
149
149
  "west": west,
150
150
  }
151
+
152
+ dem_info_sequence = self.dem.info_sequence()
153
+ data["DEM"] = dem_info_sequence
151
154
  return data # type: ignore
152
155
 
153
156
  def qgis_sequence(self) -> None:
@@ -176,7 +179,7 @@ class Background(Component):
176
179
  self.logger.debug("Generating obj file in path: %s", save_path)
177
180
 
178
181
  dem_data = cv2.imread(self.dem.dem_path, cv2.IMREAD_UNCHANGED) # pylint: disable=no-member
179
- self.plane_from_np(dem_data, save_path) # type: ignore
182
+ self.plane_from_np(dem_data, save_path, create_preview=True) # type: ignore
180
183
 
181
184
  # pylint: disable=too-many-locals
182
185
  def cutout(self, dem_path: str, save_path: str | None = None) -> str:
@@ -229,6 +232,7 @@ class Background(Component):
229
232
  dem_data: np.ndarray,
230
233
  save_path: str,
231
234
  include_zeros: bool = True,
235
+ create_preview: bool = False,
232
236
  ) -> None:
233
237
  """Generates a 3D obj file based on DEM data.
234
238
 
@@ -236,6 +240,7 @@ class Background(Component):
236
240
  dem_data (np.ndarray) -- The DEM data as a numpy array.
237
241
  save_path (str) -- The path where the obj file will be saved.
238
242
  include_zeros (bool, optional) -- If True, the mesh will include the zero height values.
243
+ create_preview (bool, optional) -- If True, a simplified mesh will be saved as an STL.
239
244
  """
240
245
  resize_factor = 1 / self.map.background_settings.resize_factor
241
246
  dem_data = cv2.resize( # pylint: disable=no-member
@@ -275,7 +280,10 @@ class Background(Component):
275
280
  bottom_left = top_left + cols
276
281
  bottom_right = bottom_left + 1
277
282
 
278
- if ground in [z[i, j], z[i, j + 1], z[i + 1, j], z[i + 1, j + 1]]:
283
+ if (
284
+ ground in [z[i, j], z[i, j + 1], z[i + 1, j], z[i + 1, j + 1]]
285
+ and not include_zeros
286
+ ):
279
287
  skipped += 1
280
288
  continue
281
289
 
@@ -294,14 +302,14 @@ class Background(Component):
294
302
  mesh.apply_transform(rotation_matrix_z)
295
303
 
296
304
  # if not include_zeros:
297
- z_scaling_factor = 1 / self.map.dem_settings.multiplier
305
+ z_scaling_factor = self.get_z_scaling_factor()
298
306
  self.logger.debug("Z scaling factor: %s", z_scaling_factor)
299
307
  mesh.apply_scale([1 / resize_factor, 1 / resize_factor, z_scaling_factor])
300
308
 
301
309
  mesh.export(save_path)
302
310
  self.logger.debug("Obj file saved: %s", save_path)
303
311
 
304
- if include_zeros:
312
+ if create_preview:
305
313
  # Simplify the preview mesh to reduce the size of the file.
306
314
  mesh = mesh.simplify_quadric_decimation(face_count=len(mesh.faces) // 2**7)
307
315
 
@@ -309,6 +317,29 @@ class Background(Component):
309
317
  mesh.apply_scale([0.5, 0.5, 0.5])
310
318
  self.mesh_to_stl(mesh)
311
319
 
320
+ def get_z_scaling_factor(self) -> float:
321
+ """Calculates the scaling factor for the Z axis based on the map settings.
322
+
323
+ Returns:
324
+ float -- The scaling factor for the Z axis.
325
+ """
326
+
327
+ scaling_factor = 1 / self.map.dem_settings.multiplier
328
+ self.logger.debug("Z scaling factor including DEM multiplier: %s", scaling_factor)
329
+
330
+ if self.map.shared_settings.height_scale_multiplier:
331
+ scaling_factor *= self.map.shared_settings.height_scale_multiplier
332
+ self.logger.debug(
333
+ "Z scaling factor including height scale multiplier: %s", scaling_factor
334
+ )
335
+ if self.map.shared_settings.mesh_z_scaling_factor:
336
+ scaling_factor *= 1 / self.map.shared_settings.mesh_z_scaling_factor
337
+ self.logger.debug(
338
+ "Z scaling factor including mesh z scaling factor: %s", scaling_factor
339
+ )
340
+
341
+ return scaling_factor
342
+
312
343
  def mesh_to_stl(self, mesh: trimesh.Trimesh) -> None:
313
344
  """Converts the mesh to an STL file and saves it in the previews directory.
314
345
  Uses powerful simplification to reduce the size of the file since it will be used
@@ -58,7 +58,7 @@ class Component:
58
58
  self.logger = logger
59
59
  self.kwargs = kwargs
60
60
 
61
- self.logger.info(
61
+ self.logger.debug(
62
62
  "Component %s initialized. Map size: %s, map rotated size: %s", # type: ignore
63
63
  self.__class__.__name__,
64
64
  self.map_size,
maps4fs/generator/dem.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """This module contains DEM class for processing Digital Elevation Model data."""
2
2
 
3
3
  import os
4
+ from typing import Any
4
5
 
5
6
  import cv2
6
7
  import numpy as np
@@ -63,6 +64,7 @@ class DEM(Component):
63
64
  size=self.map_rotated_size,
64
65
  directory=self.temp_dir,
65
66
  logger=self.logger,
67
+ map=self.map,
66
68
  )
67
69
 
68
70
  @property
@@ -280,3 +282,16 @@ class DEM(Component):
280
282
  list: Empty list.
281
283
  """
282
284
  return []
285
+
286
+ def info_sequence(self) -> dict[Any, Any] | None: # type: ignore
287
+ """Returns the information sequence for the component. Must be implemented in the child
288
+ class. If the component does not have an information sequence, an empty dictionary must be
289
+ returned.
290
+
291
+ Returns:
292
+ dict[Any, Any]: The information sequence for the component.
293
+ """
294
+ provider_info_sequence = self.dtm_provider.info_sequence()
295
+ if provider_info_sequence is None:
296
+ return {}
297
+ return provider_info_sequence
@@ -5,7 +5,7 @@ and specific settings for downloading and processing the data."""
5
5
  from __future__ import annotations
6
6
 
7
7
  import os
8
- from typing import Type
8
+ from typing import TYPE_CHECKING, Type
9
9
 
10
10
  import numpy as np
11
11
  import osmnx as ox # type: ignore
@@ -15,6 +15,9 @@ from pydantic import BaseModel
15
15
 
16
16
  from maps4fs.logger import Logger
17
17
 
18
+ if TYPE_CHECKING:
19
+ from maps4fs.generator.map import Map
20
+
18
21
 
19
22
  class DTMProviderSettings(BaseModel):
20
23
  """Base class for DTM provider settings models."""
@@ -45,6 +48,7 @@ class DTMProvider:
45
48
  size: int,
46
49
  directory: str,
47
50
  logger: Logger,
51
+ map: Map | None = None, # pylint: disable=W0622
48
52
  ):
49
53
  self._coordinates = coordinates
50
54
  self._user_settings = user_settings
@@ -56,6 +60,27 @@ class DTMProvider:
56
60
  os.makedirs(self._tile_directory, exist_ok=True)
57
61
 
58
62
  self.logger = logger
63
+ self.map = map
64
+
65
+ self._data_info: dict[str, int | str | float] | None = None
66
+
67
+ @property
68
+ def data_info(self) -> dict[str, int | str | float] | None:
69
+ """Information about the DTM data.
70
+
71
+ Returns:
72
+ dict: Information about the DTM data.
73
+ """
74
+ return self._data_info
75
+
76
+ @data_info.setter
77
+ def data_info(self, value: dict[str, int | str | float] | None) -> None:
78
+ """Set information about the DTM data.
79
+
80
+ Arguments:
81
+ value (dict): Information about the DTM data.
82
+ """
83
+ self._data_info = value
59
84
 
60
85
  @property
61
86
  def coordinates(self) -> tuple[float, float]:
@@ -260,3 +285,13 @@ class DTMProvider:
260
285
  raise ValueError("No data in the tile.")
261
286
 
262
287
  return data
288
+
289
+ def info_sequence(self) -> dict[str, int | str | float] | None:
290
+ """Returns the information sequence for the component. Must be implemented in the child
291
+ class. If the component does not have an information sequence, an empty dictionary must be
292
+ returned.
293
+
294
+ Returns:
295
+ dict[str, int | str | float] | None: Information sequence for the component.
296
+ """
297
+ return self.data_info
@@ -1,5 +1,7 @@
1
1
  """This module contains provider of Shuttle Radar Topography Mission (SRTM) 30m data."""
2
2
 
3
+ # Author: https://github.com/iwatkot
4
+
3
5
  import gzip
4
6
  import math
5
7
  import os
@@ -7,7 +9,14 @@ import shutil
7
9
 
8
10
  import numpy as np
9
11
 
10
- from maps4fs.generator.dtm.dtm import DTMProvider
12
+ from maps4fs.generator.dtm.dtm import DTMProvider, DTMProviderSettings
13
+
14
+
15
+ class SRTM30ProviderSettings(DTMProviderSettings):
16
+ """Settings for SRTM 30m provider."""
17
+
18
+ easy_mode: bool = True
19
+ power_factor: int = 0
11
20
 
12
21
 
13
22
  class SRTM30Provider(DTMProvider):
@@ -24,19 +33,30 @@ class SRTM30Provider(DTMProvider):
24
33
  _author = "[iwatkot](https://github.com/iwatkot)"
25
34
 
26
35
  _instructions = (
27
- "ℹ️ If you're a rookie in the Giants Editor check the **Apply the default multiplier** "
28
- "checkbox. Otherwise, you can change the multiplier value in the DEM Settings. "
29
- "If you will not apply the default multiplier and not change the value in the DEM "
30
- "Settings, you'll have the DEM image with the original values as on Earth, which can "
31
- "not be seen by eye and will lead to completely flat terrain. "
36
+ "ℹ️ If you don't know how to work with DEM data, it is recommended to use the "
37
+ "**Easy mode** option. It will automatically change the values in the image, so the "
38
+ "terrain will be visible in the Giants Editor. If you're an experienced modder, it's "
39
+ "recommended to disable this option and work with the DEM data in a usual way. \n"
40
+ "ℹ️ If the terrain height difference in the real world is bigger than 255 meters, "
41
+ "the [Height scale](https://github.com/iwatkot/maps4fs/blob/main/docs/dem.md#height-scale)"
42
+ " parameter in the **map.i3d** file will be changed automatically. \n"
43
+ "⚡ If the **Easy mode** option is disabled, you will probably get completely flat "
44
+ "terrain, unless you adjust the DEM Multiplier Setting or the Height scale parameter in "
45
+ "the Giants Editor. \n"
46
+ "💡 You can use the **Power factor** setting to make the difference between heights "
47
+ "bigger. Be extremely careful with this setting, and use only low values, otherwise your "
48
+ "terrain may be completely broken. \n"
32
49
  )
33
50
 
51
+ _settings = SRTM30ProviderSettings
52
+
34
53
  def __init__(self, *args, **kwargs):
35
54
  super().__init__(*args, **kwargs)
36
55
  self.hgt_directory = os.path.join(self._tile_directory, "hgt")
37
56
  self.gz_directory = os.path.join(self._tile_directory, "gz")
38
57
  os.makedirs(self.hgt_directory, exist_ok=True)
39
58
  os.makedirs(self.gz_directory, exist_ok=True)
59
+ self.data_info: dict[str, int | str | float] | None = None # type: ignore
40
60
 
41
61
  def get_tile_parameters(self, *args, **kwargs) -> dict[str, str]:
42
62
  """Returns latitude band and tile name for SRTM tile from coordinates.
@@ -83,4 +103,124 @@ class SRTM30Provider(DTMProvider):
83
103
  with open(decompressed_tile_path, "wb") as f_out:
84
104
  shutil.copyfileobj(f_in, f_out)
85
105
 
86
- return self.extract_roi(decompressed_tile_path)
106
+ data = self.extract_roi(decompressed_tile_path)
107
+
108
+ self.data_info = {}
109
+ self.add_numpy_params(data, "original")
110
+
111
+ data = self.signed_to_unsigned(data)
112
+ self.add_numpy_params(data, "grounded")
113
+
114
+ original_deviation = int(self.data_info["original_deviation"])
115
+ in_game_maximum_height = 65535 // 255
116
+ if original_deviation > in_game_maximum_height:
117
+ suggested_height_scale_multiplier = (
118
+ original_deviation / in_game_maximum_height # type: ignore
119
+ )
120
+ suggested_height_scale_value = int(255 * suggested_height_scale_multiplier)
121
+ else:
122
+ suggested_height_scale_multiplier = 1
123
+ suggested_height_scale_value = 255
124
+
125
+ self.data_info["suggested_height_scale_multiplier"] = suggested_height_scale_multiplier
126
+ self.data_info["suggested_height_scale_value"] = suggested_height_scale_value
127
+
128
+ self.map.shared_settings.height_scale_multiplier = ( # type: ignore
129
+ suggested_height_scale_multiplier
130
+ )
131
+ self.map.shared_settings.height_scale_value = suggested_height_scale_value # type: ignore
132
+
133
+ if self.user_settings.easy_mode: # type: ignore
134
+ try:
135
+ data = self.normalize_dem(data)
136
+ self.add_numpy_params(data, "normalized")
137
+
138
+ normalized_deviation = self.data_info["normalized_deviation"]
139
+ z_scaling_factor = normalized_deviation / original_deviation # type: ignore
140
+ self.data_info["z_scaling_factor"] = z_scaling_factor
141
+
142
+ self.map.shared_settings.mesh_z_scaling_factor = z_scaling_factor # type: ignore
143
+ self.map.shared_settings.change_height_scale = True # type: ignore
144
+
145
+ except Exception as e: # pylint: disable=W0718
146
+ self.logger.error(
147
+ "Failed to normalize DEM data. Error: %s. Using original data.", e
148
+ )
149
+
150
+ return data
151
+
152
+ def add_numpy_params(
153
+ self,
154
+ data: np.ndarray,
155
+ prefix: str,
156
+ ) -> None:
157
+ """Add numpy array parameters to the data_info dictionary.
158
+
159
+ Arguments:
160
+ data (np.ndarray): Numpy array of the tile.
161
+ prefix (str): Prefix for the parameters.
162
+ """
163
+ self.data_info[f"{prefix}_minimum_height"] = int(data.min()) # type: ignore
164
+ self.data_info[f"{prefix}_maximum_height"] = int(data.max()) # type: ignore
165
+ self.data_info[f"{prefix}_deviation"] = int(data.max() - data.min()) # type: ignore
166
+ self.data_info[f"{prefix}_unique_values"] = int(np.unique(data).size) # type: ignore
167
+
168
+ def signed_to_unsigned(self, data: np.ndarray, add_one: bool = True) -> np.ndarray:
169
+ """Convert signed 16-bit integer to unsigned 16-bit integer.
170
+
171
+ Arguments:
172
+ data (np.ndarray): DEM data from SRTM file after cropping.
173
+
174
+ Returns:
175
+ np.ndarray: Unsigned DEM data.
176
+ """
177
+ data = data - data.min()
178
+ if add_one:
179
+ data = data + 1
180
+ return data.astype(np.uint16)
181
+
182
+ def normalize_dem(self, data: np.ndarray) -> np.ndarray:
183
+ """Normalize DEM data to 16-bit unsigned integer using max height from settings.
184
+
185
+ Arguments:
186
+ data (np.ndarray): DEM data from SRTM file after cropping.
187
+
188
+ Returns:
189
+ np.ndarray: Normalized DEM data.
190
+ """
191
+ maximum_height = int(data.max())
192
+ minimum_height = int(data.min())
193
+ deviation = maximum_height - minimum_height
194
+ self.logger.debug(
195
+ "Maximum height: %s. Minimum height: %s. Deviation: %s.",
196
+ maximum_height,
197
+ minimum_height,
198
+ deviation,
199
+ )
200
+ self.logger.debug("Number of unique values in original DEM data: %s.", np.unique(data).size)
201
+
202
+ adjusted_maximum_height = maximum_height * 255
203
+ adjusted_maximum_height = min(adjusted_maximum_height, 65535)
204
+ scaling_factor = adjusted_maximum_height / maximum_height
205
+ self.logger.debug(
206
+ "Adjusted maximum height: %s. Scaling factor: %s.",
207
+ adjusted_maximum_height,
208
+ scaling_factor,
209
+ )
210
+
211
+ if self.user_settings.power_factor: # type: ignore
212
+ power_factor = 1 + self.user_settings.power_factor / 10 # type: ignore
213
+ self.logger.debug(
214
+ "Applying power factor: %s to the DEM data.",
215
+ power_factor,
216
+ )
217
+ data = np.power(data, power_factor).astype(np.uint16)
218
+
219
+ normalized_data = np.round(data * scaling_factor).astype(np.uint16)
220
+ self.logger.debug(
221
+ "Normalized data maximum height: %s. Minimum height: %s. Number of unique values: %s.",
222
+ normalized_data.max(),
223
+ normalized_data.min(),
224
+ np.unique(normalized_data).size,
225
+ )
226
+ return normalized_data
maps4fs/generator/i3d.py CHANGED
@@ -14,7 +14,6 @@ import numpy as np
14
14
  from maps4fs.generator.component import Component
15
15
  from maps4fs.generator.texture import Texture
16
16
 
17
- DEFAULT_HEIGHT_SCALE = 2000
18
17
  DISPLACEMENT_LAYER_SIZE_FOR_BIG_MAPS = 32768
19
18
  DEFAULT_MAX_LOD_DISTANCE = 10000
20
19
  DEFAULT_MAX_LOD_OCCLUDER_DISTANCE = 10000
@@ -81,6 +80,20 @@ class I3d(Component):
81
80
 
82
81
  root = tree.getroot()
83
82
  for map_elem in root.iter("Scene"):
83
+ for terrain_elem in map_elem.iter("TerrainTransformGroup"):
84
+ if self.map.shared_settings.change_height_scale:
85
+ suggested_height_scale = self.map.shared_settings.height_scale_value
86
+ if suggested_height_scale is not None and suggested_height_scale > 255:
87
+ new_height_scale = int(
88
+ self.map.shared_settings.height_scale_value # type: ignore
89
+ )
90
+ terrain_elem.set("heightScale", str(new_height_scale))
91
+ self.logger.info(
92
+ "heightScale attribute set to %s in TerrainTransformGroup element.",
93
+ new_height_scale,
94
+ )
95
+
96
+ self.logger.debug("TerrainTransformGroup element updated in I3D file.")
84
97
  sun_elem = map_elem.find(".//Light[@name='sun']")
85
98
 
86
99
  if sun_elem is not None:
@@ -97,10 +110,6 @@ class I3d(Component):
97
110
  )
98
111
 
99
112
  if self.map_size > 4096:
100
- terrain_elem = root.find(".//TerrainTransformGroup")
101
- if terrain_elem is None:
102
- self.logger.warning("TerrainTransformGroup element not found in I3D file.")
103
- return
104
113
  displacement_layer = terrain_elem.find(".//DisplacementLayer") # pylint: disable=W0631
105
114
 
106
115
  if displacement_layer is not None:
maps4fs/generator/map.py CHANGED
@@ -16,6 +16,7 @@ from maps4fs.generator.settings import (
16
16
  GRLESettings,
17
17
  I3DSettings,
18
18
  SatelliteSettings,
19
+ SharedSettings,
19
20
  SplineSettings,
20
21
  TextureSettings,
21
22
  )
@@ -123,6 +124,8 @@ class Map:
123
124
  with open(save_path, "w", encoding="utf-8") as file:
124
125
  json.dump(settings_json, file, indent=4)
125
126
 
127
+ self.shared_settings = SharedSettings()
128
+
126
129
  self.texture_custom_schema = kwargs.get("texture_custom_schema", None)
127
130
  if self.texture_custom_schema:
128
131
  save_path = os.path.join(self.map_directory, "texture_custom_schema.json")
@@ -245,7 +248,7 @@ class Map:
245
248
  str: Path to the archive.
246
249
  """
247
250
  archive_path = shutil.make_archive(archive_path, "zip", self.map_directory)
248
- self.logger.info("Map packed to %s.zip", archive_path)
251
+ self.logger.debug("Map packed to %s.zip", archive_path)
249
252
  if remove_source:
250
253
  try:
251
254
  shutil.rmtree(self.map_directory)
@@ -34,7 +34,7 @@ class Satellite(Component):
34
34
  """Downloads the satellite images for the map."""
35
35
  self.image_paths = [] # pylint: disable=W0201
36
36
  if not self.map.satellite_settings.download_images:
37
- self.logger.info("Satellite images download is disabled.")
37
+ self.logger.debug("Satellite images download is disabled.")
38
38
  return
39
39
 
40
40
  margin = self.map.satellite_settings.satellite_margin
@@ -4,7 +4,20 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any
6
6
 
7
- from pydantic import BaseModel
7
+ from pydantic import BaseModel, ConfigDict
8
+
9
+
10
+ class SharedSettings(BaseModel):
11
+ """Represents the shared settings for all components."""
12
+
13
+ mesh_z_scaling_factor: float | None = None
14
+ height_scale_multiplier: float | None = None
15
+ height_scale_value: float | None = None
16
+ change_height_scale: bool = False
17
+
18
+ model_config = ConfigDict(
19
+ frozen=False,
20
+ )
8
21
 
9
22
 
10
23
  class SettingsModel(BaseModel):
@@ -187,7 +187,7 @@ class Texture(Component):
187
187
  custom_schema = self.kwargs.get("texture_custom_schema")
188
188
  if custom_schema:
189
189
  layers_schema = custom_schema # type: ignore
190
- self.logger.info("Custom schema loaded with %s layers.", len(layers_schema))
190
+ self.logger.debug("Custom schema loaded with %s layers.", len(layers_schema))
191
191
  else:
192
192
  if not os.path.isfile(self.game.texture_schema):
193
193
  raise FileNotFoundError(
@@ -202,15 +202,13 @@ class Texture(Component):
202
202
 
203
203
  try:
204
204
  self.layers = [self.Layer.from_json(layer) for layer in layers_schema] # type: ignore
205
- self.logger.info("Loaded %s layers.", len(self.layers))
205
+ self.logger.debug("Loaded %s layers.", len(self.layers))
206
206
  except Exception as e: # pylint: disable=W0703
207
207
  raise ValueError(f"Error loading texture layers: {e}") from e
208
208
 
209
209
  base_layer = self.get_base_layer()
210
210
  if base_layer:
211
211
  self.logger.debug("Base layer found: %s.", base_layer.name)
212
- else:
213
- self.logger.warning("No base layer found.")
214
212
 
215
213
  self._weights_dir = self.game.weights_dir_path(self.map_directory)
216
214
  self.logger.debug("Weights directory: %s.", self._weights_dir)
@@ -595,7 +593,7 @@ class Texture(Component):
595
593
  geometry_type = geometry.geom_type
596
594
  converter = self._converters(geometry_type)
597
595
  if not converter:
598
- self.logger.warning("Geometry type %s not supported.", geometry_type)
596
+ self.logger.debug("Geometry type %s not supported.", geometry_type)
599
597
  return None
600
598
  return converter(geometry, width)
601
599
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: maps4fs
3
- Version: 1.6.0
3
+ Version: 1.6.2
4
4
  Summary: Generate map templates for Farming Simulator from real places.
5
5
  Author-email: iwatkot <iwatkot@gmail.com>
6
6
  License: MIT License
@@ -0,0 +1,27 @@
1
+ maps4fs/__init__.py,sha256=WbT36EzJ_74GN0RUUrLIYECdSdtRiZaxKl17KUt7pjA,492
2
+ maps4fs/logger.py,sha256=B-NEYpMjPAAqlV4VpfTi6nbBFnEABVtQOaYe6nMpidg,1489
3
+ maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
4
+ maps4fs/generator/background.py,sha256=dpvhhkDUJtOt_pobIOuDp6DV8Z1HJfLyP8pzkIkk-G8,22615
5
+ maps4fs/generator/component.py,sha256=GrTI7803gOQFhqocdjFG-wh0HOkC6HWoyKr8pR2Xp28,20409
6
+ maps4fs/generator/config.py,sha256=0QmK052B8bxyHVhg3jzCORLfOBMMmqVfhhbqXKf6OMk,4383
7
+ maps4fs/generator/dem.py,sha256=20gx0dzX0LyO6ipvDitst-BwGfcKogFqgQf9Q2qMH5U,10933
8
+ maps4fs/generator/game.py,sha256=QHgVnyGYvEnfwGZ84-u-dpbCRr3UeVVqBbrwr5WG8dE,7992
9
+ maps4fs/generator/grle.py,sha256=u8ZwSs313PIOkH_0B_O2tVTaZ-eYNkc30eKGtBxWzTM,17846
10
+ maps4fs/generator/i3d.py,sha256=rjOm_vlh9dofmNpYJd9P2U9S7VxZ6r3e-JDJxnMQFD8,24943
11
+ maps4fs/generator/map.py,sha256=8CYUs7NNVoQBvABqtoKtnbj280JuvseNORDCsebkQ_c,9357
12
+ maps4fs/generator/qgis.py,sha256=Es8hLuqN_KH8lDfnJE6He2rWYbAKJ3RGPn-o87S6CPI,6116
13
+ maps4fs/generator/satellite.py,sha256=_7RcuNmR1mjxEJWMDsjnzKUIqWxnGUn50XtjB7HmSPg,3661
14
+ maps4fs/generator/settings.py,sha256=1ORjaa55sDIiwVZ0G7TIHEBSDLt7c8xAWgp4QcsInUM,4817
15
+ maps4fs/generator/texture.py,sha256=dtMpNkmJalaV5IOuv6vhVQHmjbfaWZGYZSSfhs2_m8U,31134
16
+ maps4fs/generator/dtm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ maps4fs/generator/dtm/dtm.py,sha256=azy-RWsc5PgenKDtgG0lrddMwWEw1hYzdng9V8zphMk,9167
18
+ maps4fs/generator/dtm/srtm.py,sha256=2-pX6bWrJX6gr8IM7ueX6mm_PW7_UQ58MtdzDHae2OQ,9030
19
+ maps4fs/generator/dtm/usgs.py,sha256=U0kDog1UAa1lWiK4Pe3nnhXnnplOS4HZde1yqYqCiDw,13123
20
+ maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
21
+ maps4fs/toolbox/background.py,sha256=9BXWNqs_n3HgqDiPztWylgYk_QM4YgBpe6_ZNQAWtSc,2154
22
+ maps4fs/toolbox/dem.py,sha256=z9IPFNmYbjiigb3t02ZenI3Mo8odd19c5MZbjDEovTo,3525
23
+ maps4fs-1.6.2.dist-info/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
24
+ maps4fs-1.6.2.dist-info/METADATA,sha256=d-BfbnZWHPF705S_hRl6q9u9GtL3wzonab3J-dFjzjk,36231
25
+ maps4fs-1.6.2.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
26
+ maps4fs-1.6.2.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
27
+ maps4fs-1.6.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.7.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,27 +0,0 @@
1
- maps4fs/__init__.py,sha256=WbT36EzJ_74GN0RUUrLIYECdSdtRiZaxKl17KUt7pjA,492
2
- maps4fs/logger.py,sha256=B-NEYpMjPAAqlV4VpfTi6nbBFnEABVtQOaYe6nMpidg,1489
3
- maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
4
- maps4fs/generator/background.py,sha256=moTsEJM-hZgHQQiBjFVTWBKgPMqxup-58EErh4bq_dE,21342
5
- maps4fs/generator/component.py,sha256=RtXruvT4Fxfr7_xo9Bi-i3IIWcPd5QQOSpYJ_cNC49o,20408
6
- maps4fs/generator/config.py,sha256=0QmK052B8bxyHVhg3jzCORLfOBMMmqVfhhbqXKf6OMk,4383
7
- maps4fs/generator/dem.py,sha256=gXmHRckXf9-3fNwEhZ8jk89oMn6eElghIQ1kUa0rcuk,10328
8
- maps4fs/generator/game.py,sha256=QHgVnyGYvEnfwGZ84-u-dpbCRr3UeVVqBbrwr5WG8dE,7992
9
- maps4fs/generator/grle.py,sha256=u8ZwSs313PIOkH_0B_O2tVTaZ-eYNkc30eKGtBxWzTM,17846
10
- maps4fs/generator/i3d.py,sha256=FLVlj0g90IXRuaRARD1HTnufsLpuaa5kHKdiME-LUZY,24329
11
- maps4fs/generator/map.py,sha256=-iUFGqe11Df-oUrxhcnJzRZ0o6NZKRQ_blTq1h1Wezg,9287
12
- maps4fs/generator/qgis.py,sha256=Es8hLuqN_KH8lDfnJE6He2rWYbAKJ3RGPn-o87S6CPI,6116
13
- maps4fs/generator/satellite.py,sha256=Qnb6XxmXKnHdHKVMb9mJ3vDGtGkDHCOv_81hrrXdx3k,3660
14
- maps4fs/generator/settings.py,sha256=NWuK76ICr8gURQnzePat4JH9w-iACbQEKQebqu51gBE,4470
15
- maps4fs/generator/texture.py,sha256=7Z6Ci7urMvqk3-Jp9K2AKH2KlD1smEQS2qoc8Qzn8Uw,31204
16
- maps4fs/generator/dtm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- maps4fs/generator/dtm/dtm.py,sha256=THQ3RWVL9ut7A4omS8hEog-oQSSwYV0JcDMe0Iiw4fY,8009
18
- maps4fs/generator/dtm/srtm.py,sha256=x78VjI4onXxPx5CLrzpwEgFOA_E9f9zhouPdKC2YnBE,3190
19
- maps4fs/generator/dtm/usgs.py,sha256=U0kDog1UAa1lWiK4Pe3nnhXnnplOS4HZde1yqYqCiDw,13123
20
- maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
21
- maps4fs/toolbox/background.py,sha256=9BXWNqs_n3HgqDiPztWylgYk_QM4YgBpe6_ZNQAWtSc,2154
22
- maps4fs/toolbox/dem.py,sha256=z9IPFNmYbjiigb3t02ZenI3Mo8odd19c5MZbjDEovTo,3525
23
- maps4fs-1.6.0.dist-info/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
24
- maps4fs-1.6.0.dist-info/METADATA,sha256=36OOMtK0RoswMn9iyTDeJFuNeIVlhcmrDknK4Xe8HE4,36231
25
- maps4fs-1.6.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
26
- maps4fs-1.6.0.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
27
- maps4fs-1.6.0.dist-info/RECORD,,