maps4fs 1.5.9__py3-none-any.whl → 1.6.1__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:
@@ -294,7 +297,7 @@ class Background(Component):
294
297
  mesh.apply_transform(rotation_matrix_z)
295
298
 
296
299
  # if not include_zeros:
297
- z_scaling_factor = 1 / self.map.dem_settings.multiplier
300
+ z_scaling_factor = self.get_z_scaling_factor()
298
301
  self.logger.debug("Z scaling factor: %s", z_scaling_factor)
299
302
  mesh.apply_scale([1 / resize_factor, 1 / resize_factor, z_scaling_factor])
300
303
 
@@ -309,6 +312,29 @@ class Background(Component):
309
312
  mesh.apply_scale([0.5, 0.5, 0.5])
310
313
  self.mesh_to_stl(mesh)
311
314
 
315
+ def get_z_scaling_factor(self) -> float:
316
+ """Calculates the scaling factor for the Z axis based on the map settings.
317
+
318
+ Returns:
319
+ float -- The scaling factor for the Z axis.
320
+ """
321
+
322
+ scaling_factor = 1 / self.map.dem_settings.multiplier
323
+ self.logger.debug("Z scaling factor including DEM multiplier: %s", scaling_factor)
324
+
325
+ if self.map.shared_settings.height_scale_multiplier:
326
+ scaling_factor *= self.map.shared_settings.height_scale_multiplier
327
+ self.logger.debug(
328
+ "Z scaling factor including height scale multiplier: %s", scaling_factor
329
+ )
330
+ if self.map.shared_settings.mesh_z_scaling_factor:
331
+ scaling_factor *= 1 / self.map.shared_settings.mesh_z_scaling_factor
332
+ self.logger.debug(
333
+ "Z scaling factor including mesh z scaling factor: %s", scaling_factor
334
+ )
335
+
336
+ return scaling_factor
337
+
312
338
  def mesh_to_stl(self, mesh: trimesh.Trimesh) -> None:
313
339
  """Converts the mesh to an STL file and saves it in the previews directory.
314
340
  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
@@ -281,54 +283,15 @@ class DEM(Component):
281
283
  """
282
284
  return []
283
285
 
284
- def _get_scaling_factor(self, maximum_deviation: int) -> float:
285
- """Calculate scaling factor for DEM data normalization.
286
- NOTE: Needs reconsideration for the implementation.
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.
287
290
 
288
- Arguments:
289
- maximum_deviation (int): Maximum deviation in DEM data.
290
-
291
- Returns:
292
- float: Scaling factor for DEM data normalization.
293
- """
294
- ESTIMATED_MAXIMUM_DEVIATION = 1000 # pylint: disable=C0103
295
- scaling_factor = maximum_deviation / ESTIMATED_MAXIMUM_DEVIATION
296
- return scaling_factor if scaling_factor < 1 else 1
297
-
298
- def _normalize_dem(self, data: np.ndarray) -> np.ndarray:
299
- """Normalize DEM data to 16-bit unsigned integer using max height from settings.
300
- Arguments:
301
- data (np.ndarray): DEM data from SRTM file after cropping.
302
291
  Returns:
303
- np.ndarray: Normalized DEM data.
292
+ dict[Any, Any]: The information sequence for the component.
304
293
  """
305
- self.logger.debug("Starting DEM data normalization.")
306
- # Calculate the difference between the maximum and minimum values in the DEM data.
307
-
308
- max_height = data.max()
309
- min_height = data.min()
310
- max_dev = max_height - min_height
311
- self.logger.debug(
312
- "Maximum deviation: %s with maximum at %s and minimum at %s.",
313
- max_dev,
314
- max_height,
315
- min_height,
316
- )
317
-
318
- scaling_factor = self._get_scaling_factor(max_dev)
319
- adjusted_max_height = int(65535 * scaling_factor)
320
- self.logger.debug(
321
- "Maximum deviation: %s. Scaling factor: %s. Adjusted max height: %s.",
322
- max_dev,
323
- scaling_factor,
324
- adjusted_max_height,
325
- )
326
- normalized_data = (
327
- (data - data.min()) / (data.max() - data.min()) * adjusted_max_height
328
- ).astype("uint16")
329
- self.logger.debug(
330
- "DEM data was normalized to %s - %s.",
331
- normalized_data.min(),
332
- normalized_data.max(),
333
- )
334
- return normalized_data
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,18 +33,30 @@ class SRTM30Provider(DTMProvider):
24
33
  _author = "[iwatkot](https://github.com/iwatkot)"
25
34
 
26
35
  _instructions = (
27
- "ℹ️ Set the Multiplier value in the DEM Settings, when using this DTM provider. "
28
- "Otherwise, the dem file will contain values in meters exactly as on Earth "
29
- "and you probably won't see any terrain by eye. "
30
- "Note that the multiplier value may be big enough to make the terrain visible."
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"
31
49
  )
32
50
 
51
+ _settings = SRTM30ProviderSettings
52
+
33
53
  def __init__(self, *args, **kwargs):
34
54
  super().__init__(*args, **kwargs)
35
55
  self.hgt_directory = os.path.join(self._tile_directory, "hgt")
36
56
  self.gz_directory = os.path.join(self._tile_directory, "gz")
37
57
  os.makedirs(self.hgt_directory, exist_ok=True)
38
58
  os.makedirs(self.gz_directory, exist_ok=True)
59
+ self.data_info: dict[str, int | str | float] | None = None # type: ignore
39
60
 
40
61
  def get_tile_parameters(self, *args, **kwargs) -> dict[str, str]:
41
62
  """Returns latitude band and tile name for SRTM tile from coordinates.
@@ -82,4 +103,124 @@ class SRTM30Provider(DTMProvider):
82
103
  with open(decompressed_tile_path, "wb") as f_out:
83
104
  shutil.copyfileobj(f_in, f_out)
84
105
 
85
- 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)
@@ -305,8 +303,7 @@ class Texture(Component):
305
303
  useful_attributes = [
306
304
  "coordinates",
307
305
  "bbox",
308
- "map_height",
309
- "map_width",
306
+ "map_size",
310
307
  "rotation",
311
308
  "minimum_x",
312
309
  "minimum_y",
@@ -596,7 +593,7 @@ class Texture(Component):
596
593
  geometry_type = geometry.geom_type
597
594
  converter = self._converters(geometry_type)
598
595
  if not converter:
599
- self.logger.warning("Geometry type %s not supported.", geometry_type)
596
+ self.logger.debug("Geometry type %s not supported.", geometry_type)
600
597
  return None
601
598
  return converter(geometry, width)
602
599
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: maps4fs
3
- Version: 1.5.9
3
+ Version: 1.6.1
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=UQlYobpDuUaRM9Ke20-ZKhAYtMS-FC-ekYeaLhimhyQ,22374
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.1.dist-info/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
24
+ maps4fs-1.6.1.dist-info/METADATA,sha256=6LPuSkp0S7c0USSsUBF6n5MPuNMIuSA_J7IviBUHaKA,36231
25
+ maps4fs-1.6.1.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
26
+ maps4fs-1.6.1.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
27
+ maps4fs-1.6.1.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=vGz-gUg_JArqHO7qewdnSR7WiF7ciUzY-OSqOluUDWw,12304
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=sErusfv1AqQfP-veMrZ921Tz8DnGEhfB4ucggMmKrD4,31231
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=7uEb-Pde_uTG4D311mZ634QYkB5yvV8t2DfNfXuhYGY,3066
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.5.9.dist-info/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
24
- maps4fs-1.5.9.dist-info/METADATA,sha256=CEhXKo9Y6Nqmh7SL-_BV7XSHtD7eApd8-81Grfd-zp4,36231
25
- maps4fs-1.5.9.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
26
- maps4fs-1.5.9.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
27
- maps4fs-1.5.9.dist-info/RECORD,,