maps4fs 0.9.7__py3-none-any.whl → 0.9.92__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.
maps4fs/generator/dem.py CHANGED
@@ -9,6 +9,7 @@ import cv2
9
9
  import numpy as np
10
10
  import rasterio # type: ignore
11
11
  import requests
12
+ from pympler import asizeof # type: ignore
12
13
 
13
14
  from maps4fs.generator.component import Component
14
15
 
@@ -79,6 +80,22 @@ class DEM(Component):
79
80
  )
80
81
  return dem_width, dem_height
81
82
 
83
+ def to_ground(self, data: np.ndarray) -> np.ndarray:
84
+ """Receives the signed 16-bit integer array and converts it to the ground level.
85
+ If the min value is negative, it will become zero value and the rest of the values
86
+ will be shifted accordingly.
87
+ """
88
+ # For examlem, min value was -50, it will become 0 and for all values we'll +50.
89
+
90
+ if data.min() < 0:
91
+ self.logger.debug("Array contains negative values, will be shifted to the ground.")
92
+ data = data + abs(data.min())
93
+
94
+ self.logger.debug(
95
+ "Array was shifted to the ground. Min: %s, max: %s.", data.min(), data.max()
96
+ )
97
+ return data
98
+
82
99
  # pylint: disable=no-member
83
100
  def process(self) -> None:
84
101
  """Reads SRTM file, crops it to map size, normalizes and blurs it,
@@ -119,10 +136,15 @@ class DEM(Component):
119
136
  data.max(),
120
137
  )
121
138
 
139
+ data = self.to_ground(data)
140
+
122
141
  resampled_data = cv2.resize(
123
142
  data, dem_output_resolution, interpolation=cv2.INTER_LINEAR
124
143
  ).astype("uint16")
125
144
 
145
+ size_of_resampled_data = asizeof.asizeof(resampled_data) / 1024 / 1024
146
+ self.logger.debug("Size of resampled data: %s MB.", size_of_resampled_data)
147
+
126
148
  self.logger.debug(
127
149
  "Maximum value in resampled data: %s, minimum value: %s.",
128
150
  resampled_data.max(),
@@ -135,6 +157,17 @@ class DEM(Component):
135
157
  else:
136
158
  self.logger.debug("Auto processing is disabled, DEM data will not be normalized.")
137
159
  resampled_data = resampled_data * self.multiplier
160
+
161
+ self.logger.debug(
162
+ "DEM data was multiplied by %s. Min: %s, max: %s.",
163
+ self.multiplier,
164
+ resampled_data.min(),
165
+ resampled_data.max(),
166
+ )
167
+
168
+ size_of_resampled_data = asizeof.asizeof(resampled_data) / 1024 / 1024
169
+ self.logger.debug("Size of resampled data: %s MB.", size_of_resampled_data)
170
+
138
171
  # Clip values to 16-bit unsigned integer range.
139
172
  resampled_data = np.clip(resampled_data, 0, 65535)
140
173
  resampled_data = resampled_data.astype("uint16")
maps4fs/generator/map.py CHANGED
@@ -116,15 +116,19 @@ class Map:
116
116
  )
117
117
  return previews
118
118
 
119
- def pack(self, archive_name: str) -> str:
119
+ def pack(self, archive_path: str, remove_source: bool = True) -> str:
120
120
  """Pack map directory to zip archive.
121
121
 
122
122
  Args:
123
- archive_name (str): Name of the archive.
123
+ archive_path (str): Path to the archive.
124
+ remove_source (bool, optional): Remove source directory after packing.
124
125
 
125
126
  Returns:
126
127
  str: Path to the archive.
127
128
  """
128
- archive_path = shutil.make_archive(archive_name, "zip", self.map_directory)
129
- self.logger.info("Map packed to %s.zip", archive_name)
129
+ archive_path = shutil.make_archive(archive_path, "zip", self.map_directory)
130
+ self.logger.info("Map packed to %s.zip", archive_path)
131
+ if remove_source:
132
+ shutil.rmtree(self.map_directory)
133
+ self.logger.info("Map directory removed: %s", self.map_directory)
130
134
  return archive_path
@@ -0,0 +1 @@
1
+ # pylint: disable=missing-module-docstring
maps4fs/toolbox/dem.py ADDED
@@ -0,0 +1,112 @@
1
+ """This module contains functions for working with Digital Elevation Models (DEMs)."""
2
+
3
+ import os
4
+
5
+ import rasterio # type: ignore
6
+ from pyproj import Transformer
7
+ from rasterio.io import DatasetReader # type: ignore
8
+ from rasterio.windows import from_bounds # type: ignore
9
+
10
+
11
+ def read_geo_tiff(file_path: str) -> DatasetReader:
12
+ """Read a GeoTIFF file and return the DatasetReader object.
13
+
14
+ Args:
15
+ file_path (str): The path to the GeoTIFF file.
16
+
17
+ Raises:
18
+ FileNotFoundError: If the file is not found.
19
+ RuntimeError: If there is an error reading the file.
20
+
21
+ Returns:
22
+ DatasetReader: The DatasetReader object for the GeoTIFF file.
23
+ """
24
+ if not os.path.isfile(file_path):
25
+ raise FileNotFoundError(f"File not found: {file_path}")
26
+
27
+ try:
28
+ src = rasterio.open(file_path)
29
+ except Exception as e:
30
+ raise RuntimeError(f"Error reading file: {file_path}") from e
31
+
32
+ if not src.bounds or not src.crs:
33
+ raise RuntimeError(
34
+ f"Can not read bounds or CRS from file: {file_path}. "
35
+ f"Bounds: {src.bounds}, CRS: {src.crs}"
36
+ )
37
+
38
+ return src
39
+
40
+
41
+ def get_geo_tiff_bbox(
42
+ src: DatasetReader, dst_crs: str | None = "EPSG:4326"
43
+ ) -> tuple[float, float, float, float]:
44
+ """Return the bounding box of a GeoTIFF file in the destination CRS.
45
+
46
+ Args:
47
+ src (DatasetReader): The DatasetReader object for the GeoTIFF file.
48
+ dst_crs (str, optional): The destination CRS. Defaults to "EPSG:4326".
49
+
50
+ Returns:
51
+ tuple[float, float, float, float]: The bounding box in the destination CRS
52
+ as (north, south, east, west).
53
+ """
54
+ left, bottom, right, top = src.bounds
55
+
56
+ transformer = Transformer.from_crs(src.crs, dst_crs, always_xy=True)
57
+
58
+ east, north = transformer.transform(left, top)
59
+ west, south = transformer.transform(right, bottom)
60
+
61
+ return north, south, east, west
62
+
63
+
64
+ # pylint: disable=R0914
65
+ def extract_roi(file_path: str, bbox: tuple[float, float, float, float]) -> str:
66
+ """Extract a region of interest (ROI) from a GeoTIFF file and save it as a new file.
67
+
68
+ Args:
69
+ file_path (str): The path to the GeoTIFF file.
70
+ bbox (tuple[float, float, float, float]): The bounding box of the region of interest
71
+ as (north, south, east, west).
72
+
73
+ Raises:
74
+ RuntimeError: If there is no data in the selected region.
75
+
76
+ Returns:
77
+ str: The path to the new GeoTIFF file containing the extracted ROI.
78
+ """
79
+ with rasterio.open(file_path) as src:
80
+ transformer = Transformer.from_crs("EPSG:4326", src.crs, always_xy=True)
81
+ north, south, east, west = bbox
82
+
83
+ left, bottom = transformer.transform(west, south)
84
+ right, top = transformer.transform(east, north)
85
+
86
+ window = from_bounds(left, bottom, right, top, src.transform)
87
+ data = src.read(window=window)
88
+
89
+ if not data.size > 0:
90
+ raise RuntimeError("No data in the selected region.")
91
+
92
+ base_name = os.path.basename(file_path).split(".")[0]
93
+ dir_name = os.path.dirname(file_path)
94
+
95
+ output_name = f"{base_name}_{north}_{south}_{east}_{west}.tif"
96
+
97
+ output_path = os.path.join(dir_name, output_name)
98
+
99
+ with rasterio.open(
100
+ output_path,
101
+ "w",
102
+ driver="GTiff",
103
+ height=data.shape[1],
104
+ width=data.shape[2],
105
+ count=data.shape[0],
106
+ dtype=data.dtype,
107
+ crs=src.crs,
108
+ transform=src.window_transform(window),
109
+ ) as dst:
110
+ dst.write(data)
111
+
112
+ return output_path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: maps4fs
3
- Version: 0.9.7
3
+ Version: 0.9.92
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
@@ -21,6 +21,7 @@ Requires-Dist: geopy
21
21
  Requires-Dist: trimesh
22
22
  Requires-Dist: imageio
23
23
  Requires-Dist: tifffile
24
+ Requires-Dist: pympler
24
25
 
25
26
  <div align="center" markdown>
26
27
  <a href="https://discord.gg/Sj5QKKyE42">
@@ -31,7 +32,8 @@ Requires-Dist: tifffile
31
32
  <a href="#Quick-Start">Quick Start</a> •
32
33
  <a href="#Overview">Overview</a> •
33
34
  <a href="#How-To-Run">How-To-Run</a> •
34
- <a href="tutorials/FAQ.md">FAQ</a><br>
35
+ <a href="docs/FAQ.md">FAQ</a>
36
+ <a href="#Modder-Toolbox">Modder Toolbox</a><br>
35
37
  <a href="#Supported-objects">Supported objects</a> •
36
38
  <a href="#Generation-info">Generation info</a> •
37
39
  <a href="#Texture-schema">Texture schema</a> •
@@ -65,6 +67,7 @@ Requires-Dist: tifffile
65
67
  🚜 Supports Farming Simulator 22 and 25<br>
66
68
  🔷 Generates *.obj files for background terrain based on the real-world height map<br>
67
69
  📄 Generates scripts to download high-resolution satellite images from [QGIS](https://qgis.org/download/) in one click<br>
70
+ 🧰 Modder Toolbox to help you with various of tasks 🆕<br>
68
71
 
69
72
  <p align="center">
70
73
  <img src="https://github.com/user-attachments/assets/cf8f5752-9c69-4018-bead-290f59ba6976"><br>
@@ -196,6 +199,16 @@ for active_component in map.generate():
196
199
 
197
200
  The map will be saved in the `map_directory` directory.
198
201
 
202
+ ## Modder Toolbox
203
+ The tool now has a Modder Toolbox, which is a set of tools to help you with various tasks. You can open the toolbox by switching to the `🧰 Modder Toolbox` tab in the StreamLit app.<br>
204
+
205
+ ![Modder Toolbox](https://github.com/user-attachments/assets/18f169e9-1a5b-474c-b488-6becfffadcea)
206
+
207
+ ### Tool categories
208
+ Tools are divided into categories, which are listed below.
209
+ #### Textures and DEM
210
+ - **GeoTIFF windowing** - allows you to upload your GeoTIFF file and select the region of interest to extract it from the image.
211
+
199
212
  ## Supported objects
200
213
  The project is based on the [OpenStreetMap](https://www.openstreetmap.org/) data. So, refer to [this page](https://wiki.openstreetmap.org/wiki/Map_Features) to understand the list below.
201
214
  - "building": True
@@ -374,9 +387,9 @@ If you're willing to create a background terrain, you will need: Blender, the Bl
374
387
 
375
388
  If you're afraid of this task, please don't be. It's really simple and I've prepaired detailed step-by-step instructions for you, you'll find them in the separate README files. Here are the steps you need to follow:
376
389
 
377
- 1. [Download high-resolution satellite images](tutorials/README_satellite_images.md).
378
- 2. [Prepare the i3d files](tutorials/README_i3d.md).
379
- 3. [Import the i3d files to Giants Editor](tutorials/README_giants_editor.md).
390
+ 1. [Download high-resolution satellite images](docs/download_satellite_images.md).
391
+ 2. [Prepare the i3d files](docs/create_background_terrain.md).
392
+ 3. [Import the i3d files to Giants Editor](docs/import_to_giants_editor.md).
380
393
 
381
394
  ## Overview image
382
395
  The overview image is an image that is used as in-game map. No matter what the size of the map, this file is always `4096x4096 pixels`, while the region of your map is `2048x2048 pixels` in center of this file. The rest of the image is just here for nice view, but you still may add satellite pictures to this region.<br>
@@ -416,7 +429,7 @@ You can also apply some advanced settings to the map generation process. Note th
416
429
 
417
430
  Here's the list of the advanced settings:
418
431
 
419
- - DEM multiplier: the height of the map is multiplied by this value. So the DEM map is just a 16-bit grayscale image, which means that the maximum avaiable value there is 65535, while the actual difference between the deepest and the highest point on Earth is about 20 km. So, by default this value is set to 3. Just note that this setting mostly does not matter, because you can always adjust it in the Giants Editor, learn more about the [heightScale](https://www.farming-simulator.org/19/terrain-heightscale.php) parameter on the [PMC Farming Simulator](https://www.farming-simulator.org/) website.
432
+ - DEM multiplier: the height of the map is multiplied by this value. So the DEM map is just a 16-bit grayscale image, which means that the maximum avaiable value there is 65535, while the actual difference between the deepest and the highest point on Earth is about 20 km. Just note that this setting mostly does not matter, because you can always adjust it in the Giants Editor, learn more about the DEM file and the heightScale paramter in [docs](docs/dem.md). By default, it's set to 1.
420
433
 
421
434
  - DEM Blur radius: the radius of the Gaussian blur filter applied to the DEM map. By default, it's set to 21. This filter just makes the DEM map smoother, so the height transitions will be more natural. You can set it to 1 to disable the filter, but it will result as a Minecraft-like map.
422
435
 
@@ -434,5 +447,5 @@ To create a basic map, you only need the Giants Editor. But if you want to creat
434
447
  6. [AnyConv](https://anyconv.com/png-to-dds-converter/) - the online tool to convert the PNG images to the DDS format. You'll need this format for the textures, icons, overview and preview images.
435
448
 
436
449
  ## Bugs and feature requests
437
- ➡️ Please, before creating an issue or asking some questions, check the [FAQ](tutorials/FAQ.md) section.<br>
450
+ ➡️ Please, before creating an issue or asking some questions, check the [FAQ](docs/FAQ.md) section.<br>
438
451
  If you find a bug or have an idea for a new feature, please create an issue [here](https://github.com/iwatkot/maps4fs/issues) or contact me directly on [Telegram](https://t.me/iwatkot) or on Discord: `iwatkot`.
@@ -4,16 +4,18 @@ maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk
4
4
  maps4fs/generator/background.py,sha256=AP-Z3F-4I9achvA9xsaXAAoA6IHtmPLxb1RkUsVYdbg,14036
5
5
  maps4fs/generator/component.py,sha256=ZEDjChPnvqAsgnBu2f2YBOlwGOlfax4VaAYBcJerLIQ,10684
6
6
  maps4fs/generator/config.py,sha256=ZO5BWDU-S3p0-ndKDSFa8Oin3YcYy0iH8B4lqEA_07Q,4275
7
- maps4fs/generator/dem.py,sha256=XLpzjJMPZCxjrF-AhwTeEb-OQoCHEtYdK0b8z3Gb-is,15712
7
+ maps4fs/generator/dem.py,sha256=7UnIUnXbN3OVMSHKgrFcyzWYCMgk6vIg1-ehrNn4ek8,17042
8
8
  maps4fs/generator/game.py,sha256=94HjPNOyy6XSSOnBp-uxrkBglKyC-X3ULIrrucfdlKw,6825
9
9
  maps4fs/generator/i3d.py,sha256=UuQiQRusPQ2f6PvGKxJ_UZeXsx3uG15efmy8Ysnm3F8,3597
10
- maps4fs/generator/map.py,sha256=v8OOLmhAkgqq64tQgEDbV6DmbgOVm3NXJBDDy0nJf60,4226
10
+ maps4fs/generator/map.py,sha256=_LQe54KLfS_4M462UiiNSqKyUroqnQ8inwXZIZDP9a0,4487
11
11
  maps4fs/generator/path_steps.py,sha256=yeN6hmOD8O2LMozUf4HcQMIy8WJ5sHF5pGQT_s2FfOw,3147
12
12
  maps4fs/generator/qgis.py,sha256=R5Iv3ovyLXkhAL5Oy41u3ZLNOSEbc1byLetzPootO7o,6091
13
13
  maps4fs/generator/texture.py,sha256=CwaXZfAG4e3D3YR7yVR2MC677EHpbUWTboCS3G6jkhk,17723
14
14
  maps4fs/generator/tile.py,sha256=3vmfjQiPiiUZKPuIo5tg2rOKkgcP1NRVkMGK-Vo10-A,2138
15
- maps4fs-0.9.7.dist-info/LICENSE.md,sha256=-JY0v7p3dwXze61EbYiK7YEJ2aKrjaFZ8y2xYEOrmRY,1068
16
- maps4fs-0.9.7.dist-info/METADATA,sha256=dhMICyAhvj7SiKMKyK_-ewOb07j38R574o9SMezErYE,24635
17
- maps4fs-0.9.7.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
18
- maps4fs-0.9.7.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
19
- maps4fs-0.9.7.dist-info/RECORD,,
15
+ maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
16
+ maps4fs/toolbox/dem.py,sha256=53KVZ6IKIlK642eYFSRDAC8l2HL9IEUpQNYkkTC56uU,3510
17
+ maps4fs-0.9.92.dist-info/LICENSE.md,sha256=-JY0v7p3dwXze61EbYiK7YEJ2aKrjaFZ8y2xYEOrmRY,1068
18
+ maps4fs-0.9.92.dist-info/METADATA,sha256=wQTqG8ZcfeJYv4IYn9vIor9WtK36JnxPFAbjzTV-Tqw,25194
19
+ maps4fs-0.9.92.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
20
+ maps4fs-0.9.92.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
21
+ maps4fs-0.9.92.dist-info/RECORD,,