maps4fs 0.9.7__py3-none-any.whl → 0.9.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- maps4fs/generator/dem.py +18 -0
- maps4fs/toolbox/__init__.py +1 -0
- maps4fs/toolbox/dem.py +112 -0
- {maps4fs-0.9.7.dist-info → maps4fs-0.9.9.dist-info}/METADATA +19 -7
- {maps4fs-0.9.7.dist-info → maps4fs-0.9.9.dist-info}/RECORD +8 -6
- {maps4fs-0.9.7.dist-info → maps4fs-0.9.9.dist-info}/LICENSE.md +0 -0
- {maps4fs-0.9.7.dist-info → maps4fs-0.9.9.dist-info}/WHEEL +0 -0
- {maps4fs-0.9.7.dist-info → maps4fs-0.9.9.dist-info}/top_level.txt +0 -0
maps4fs/generator/dem.py
CHANGED
@@ -79,6 +79,22 @@ class DEM(Component):
|
|
79
79
|
)
|
80
80
|
return dem_width, dem_height
|
81
81
|
|
82
|
+
def to_ground(self, data: np.ndarray) -> np.ndarray:
|
83
|
+
"""Receives the signed 16-bit integer array and converts it to the ground level.
|
84
|
+
If the min value is negative, it will become zero value and the rest of the values
|
85
|
+
will be shifted accordingly.
|
86
|
+
"""
|
87
|
+
# For examlem, min value was -50, it will become 0 and for all values we'll +50.
|
88
|
+
|
89
|
+
if data.min() < 0:
|
90
|
+
self.logger.debug("Array contains negative values, will be shifted to the ground.")
|
91
|
+
data = data + abs(data.min())
|
92
|
+
|
93
|
+
self.logger.debug(
|
94
|
+
"Array was shifted to the ground. Min: %s, max: %s.", data.min(), data.max()
|
95
|
+
)
|
96
|
+
return data
|
97
|
+
|
82
98
|
# pylint: disable=no-member
|
83
99
|
def process(self) -> None:
|
84
100
|
"""Reads SRTM file, crops it to map size, normalizes and blurs it,
|
@@ -119,6 +135,8 @@ class DEM(Component):
|
|
119
135
|
data.max(),
|
120
136
|
)
|
121
137
|
|
138
|
+
data = self.to_ground(data)
|
139
|
+
|
122
140
|
resampled_data = cv2.resize(
|
123
141
|
data, dem_output_resolution, interpolation=cv2.INTER_LINEAR
|
124
142
|
).astype("uint16")
|
@@ -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.
|
3
|
+
Version: 0.9.9
|
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
|
@@ -31,7 +31,8 @@ Requires-Dist: tifffile
|
|
31
31
|
<a href="#Quick-Start">Quick Start</a> •
|
32
32
|
<a href="#Overview">Overview</a> •
|
33
33
|
<a href="#How-To-Run">How-To-Run</a> •
|
34
|
-
<a href="
|
34
|
+
<a href="docs/FAQ.md">FAQ</a> •
|
35
|
+
<a href="#Modder-Toolbox">Modder Toolbox</a><br>
|
35
36
|
<a href="#Supported-objects">Supported objects</a> •
|
36
37
|
<a href="#Generation-info">Generation info</a> •
|
37
38
|
<a href="#Texture-schema">Texture schema</a> •
|
@@ -65,6 +66,7 @@ Requires-Dist: tifffile
|
|
65
66
|
🚜 Supports Farming Simulator 22 and 25<br>
|
66
67
|
🔷 Generates *.obj files for background terrain based on the real-world height map<br>
|
67
68
|
📄 Generates scripts to download high-resolution satellite images from [QGIS](https://qgis.org/download/) in one click<br>
|
69
|
+
🧰 Modder Toolbox to help you with various of tasks 🆕<br>
|
68
70
|
|
69
71
|
<p align="center">
|
70
72
|
<img src="https://github.com/user-attachments/assets/cf8f5752-9c69-4018-bead-290f59ba6976"><br>
|
@@ -196,6 +198,16 @@ for active_component in map.generate():
|
|
196
198
|
|
197
199
|
The map will be saved in the `map_directory` directory.
|
198
200
|
|
201
|
+
## Modder Toolbox
|
202
|
+
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>
|
203
|
+
|
204
|
+

|
205
|
+
|
206
|
+
### Tool categories
|
207
|
+
Tools are divided into categories, which are listed below.
|
208
|
+
#### Textures and DEM
|
209
|
+
- **GeoTIFF windowing** - allows you to upload your GeoTIFF file and select the region of interest to extract it from the image.
|
210
|
+
|
199
211
|
## Supported objects
|
200
212
|
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
213
|
- "building": True
|
@@ -374,9 +386,9 @@ If you're willing to create a background terrain, you will need: Blender, the Bl
|
|
374
386
|
|
375
387
|
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
388
|
|
377
|
-
1. [Download high-resolution satellite images](
|
378
|
-
2. [Prepare the i3d files](
|
379
|
-
3. [Import the i3d files to Giants Editor](
|
389
|
+
1. [Download high-resolution satellite images](docs/download_satellite_images.md).
|
390
|
+
2. [Prepare the i3d files](docs/create_background_terrain.md).
|
391
|
+
3. [Import the i3d files to Giants Editor](docs/import_to_giants_editor.md).
|
380
392
|
|
381
393
|
## Overview image
|
382
394
|
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 +428,7 @@ You can also apply some advanced settings to the map generation process. Note th
|
|
416
428
|
|
417
429
|
Here's the list of the advanced settings:
|
418
430
|
|
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.
|
431
|
+
- 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
432
|
|
421
433
|
- 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
434
|
|
@@ -434,5 +446,5 @@ To create a basic map, you only need the Giants Editor. But if you want to creat
|
|
434
446
|
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
447
|
|
436
448
|
## Bugs and feature requests
|
437
|
-
➡️ Please, before creating an issue or asking some questions, check the [FAQ](
|
449
|
+
➡️ Please, before creating an issue or asking some questions, check the [FAQ](docs/FAQ.md) section.<br>
|
438
450
|
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,7 +4,7 @@ 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=
|
7
|
+
maps4fs/generator/dem.py,sha256=rBqVeWiLEpY89EIpfnSENOYsNYxsJcV_Y2UuBalE104,16438
|
8
8
|
maps4fs/generator/game.py,sha256=94HjPNOyy6XSSOnBp-uxrkBglKyC-X3ULIrrucfdlKw,6825
|
9
9
|
maps4fs/generator/i3d.py,sha256=UuQiQRusPQ2f6PvGKxJ_UZeXsx3uG15efmy8Ysnm3F8,3597
|
10
10
|
maps4fs/generator/map.py,sha256=v8OOLmhAkgqq64tQgEDbV6DmbgOVm3NXJBDDy0nJf60,4226
|
@@ -12,8 +12,10 @@ maps4fs/generator/path_steps.py,sha256=yeN6hmOD8O2LMozUf4HcQMIy8WJ5sHF5pGQT_s2Ff
|
|
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
|
16
|
-
maps4fs
|
17
|
-
maps4fs-0.9.
|
18
|
-
maps4fs-0.9.
|
19
|
-
maps4fs-0.9.
|
15
|
+
maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
|
16
|
+
maps4fs/toolbox/dem.py,sha256=53KVZ6IKIlK642eYFSRDAC8l2HL9IEUpQNYkkTC56uU,3510
|
17
|
+
maps4fs-0.9.9.dist-info/LICENSE.md,sha256=-JY0v7p3dwXze61EbYiK7YEJ2aKrjaFZ8y2xYEOrmRY,1068
|
18
|
+
maps4fs-0.9.9.dist-info/METADATA,sha256=rWT-sSS7QfXGArOqjWMLdCxSRm0bkGd0uMZwJegayZc,25170
|
19
|
+
maps4fs-0.9.9.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
20
|
+
maps4fs-0.9.9.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
|
21
|
+
maps4fs-0.9.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|