maps4fs 1.8.172__py3-none-any.whl → 1.8.173__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/component/background.py +9 -11
- maps4fs/generator/component/base/component_mesh.py +128 -11
- maps4fs/generator/settings.py +1 -1
- {maps4fs-1.8.172.dist-info → maps4fs-1.8.173.dist-info}/METADATA +2 -2
- {maps4fs-1.8.172.dist-info → maps4fs-1.8.173.dist-info}/RECORD +8 -8
- {maps4fs-1.8.172.dist-info → maps4fs-1.8.173.dist-info}/LICENSE.md +0 -0
- {maps4fs-1.8.172.dist-info → maps4fs-1.8.173.dist-info}/WHEEL +0 -0
- {maps4fs-1.8.172.dist-info → maps4fs-1.8.173.dist-info}/top_level.txt +0 -0
@@ -235,24 +235,16 @@ class Background(MeshComponent, ImageComponent):
|
|
235
235
|
This setting is used for a Background Terrain, where the center part where the
|
236
236
|
playable area is will be cut out.
|
237
237
|
"""
|
238
|
-
resize_factor = 1 / self.map.background_settings.resize_factor
|
239
|
-
dem_data = cv2.resize(dem_data, (0, 0), fx=resize_factor, fy=resize_factor)
|
240
|
-
if remove_center:
|
241
|
-
half_size = int(self.map_size // 2 * resize_factor)
|
242
|
-
dem_data = self.cut_out_np(dem_data, half_size, set_zeros=True)
|
243
|
-
self.logger.debug("Center removed from DEM data.")
|
244
|
-
self.logger.debug(
|
245
|
-
"DEM data resized to shape: %s with factor: %s", dem_data.shape, resize_factor
|
246
|
-
)
|
247
|
-
|
248
238
|
mesh = self.mesh_from_np(
|
249
239
|
dem_data,
|
250
240
|
include_zeros=include_zeros,
|
251
241
|
z_scaling_factor=self.get_z_scaling_factor(),
|
252
|
-
resize_factor=resize_factor,
|
242
|
+
resize_factor=self.map.background_settings.resize_factor,
|
253
243
|
apply_decimation=self.map.background_settings.apply_decimation,
|
254
244
|
decimation_percent=self.map.background_settings.decimation_percent,
|
255
245
|
decimation_agression=self.map.background_settings.decimation_agression,
|
246
|
+
remove_center=remove_center,
|
247
|
+
remove_size=self.map_size,
|
256
248
|
)
|
257
249
|
|
258
250
|
mesh.export(save_path)
|
@@ -440,6 +432,12 @@ class Background(MeshComponent, ImageComponent):
|
|
440
432
|
|
441
433
|
# Single channeled 8 bit image, where the water have values of 255, and the rest 0.
|
442
434
|
plane_water = cv2.imread(self.water_resources_path, cv2.IMREAD_UNCHANGED)
|
435
|
+
|
436
|
+
# Check if the image contains non-zero values.
|
437
|
+
if not np.any(plane_water):
|
438
|
+
self.logger.warning("Water resources image is empty, skipping water generation.")
|
439
|
+
return
|
440
|
+
|
443
441
|
dilated_plane_water = cv2.dilate(
|
444
442
|
plane_water.astype(np.uint8), np.ones((5, 5), np.uint8), iterations=5
|
445
443
|
).astype(np.uint8)
|
@@ -53,10 +53,12 @@ class MeshComponent(Component):
|
|
53
53
|
image: np.ndarray,
|
54
54
|
include_zeros: bool,
|
55
55
|
z_scaling_factor: float,
|
56
|
-
resize_factor:
|
56
|
+
resize_factor: int,
|
57
57
|
apply_decimation: bool,
|
58
58
|
decimation_percent: int,
|
59
59
|
decimation_agression: int,
|
60
|
+
remove_center: bool,
|
61
|
+
remove_size: int,
|
60
62
|
) -> trimesh.Trimesh:
|
61
63
|
"""Generates a mesh from the given numpy array.
|
62
64
|
|
@@ -64,16 +66,21 @@ class MeshComponent(Component):
|
|
64
66
|
image (np.ndarray): The numpy array to generate the mesh from.
|
65
67
|
include_zeros (bool): Whether to include zero values in the mesh.
|
66
68
|
z_scaling_factor (float): The scaling factor for the Z-axis.
|
67
|
-
resize_factor (
|
69
|
+
resize_factor (int): The resizing factor.
|
68
70
|
apply_decimation (bool): Whether to apply decimation to the mesh.
|
69
71
|
decimation_percent (int): The percent of the decimation.
|
70
72
|
decimation_agression (int): The agression of the decimation.
|
73
|
+
remove_center (bool): Whether to remove the center from the mesh.
|
74
|
+
remove_size (int): The size of the center to remove.
|
71
75
|
|
72
76
|
Returns:
|
73
77
|
trimesh.Trimesh: The generated mesh.
|
74
78
|
"""
|
79
|
+
output_x_size, _ = image.shape
|
75
80
|
image = image.max() - image
|
76
81
|
|
82
|
+
image = image[::resize_factor, ::resize_factor]
|
83
|
+
|
77
84
|
rows, cols = image.shape
|
78
85
|
x = np.linspace(0, cols - 1, cols)
|
79
86
|
y = np.linspace(0, rows - 1, rows)
|
@@ -106,15 +113,7 @@ class MeshComponent(Component):
|
|
106
113
|
|
107
114
|
faces_np = np.array(faces)
|
108
115
|
mesh = trimesh.Trimesh(vertices=vertices, faces=faces_np)
|
109
|
-
|
110
|
-
# Apply rotation: 180 degrees around Y-axis and Z-axis
|
111
|
-
rotation_matrix_y = trimesh.transformations.rotation_matrix(np.pi, [0, 1, 0])
|
112
|
-
rotation_matrix_z = trimesh.transformations.rotation_matrix(np.pi, [0, 0, 1])
|
113
|
-
mesh.apply_transform(rotation_matrix_y)
|
114
|
-
mesh.apply_transform(rotation_matrix_z)
|
115
|
-
|
116
|
-
# if not include_zeros:
|
117
|
-
mesh.apply_scale([1 / resize_factor, 1 / resize_factor, z_scaling_factor])
|
116
|
+
mesh = MeshComponent.rotate_mesh(mesh)
|
118
117
|
|
119
118
|
if apply_decimation:
|
120
119
|
percent = decimation_percent / 100
|
@@ -122,4 +121,122 @@ class MeshComponent(Component):
|
|
122
121
|
percent=percent, aggression=decimation_agression
|
123
122
|
)
|
124
123
|
|
124
|
+
try:
|
125
|
+
if not mesh.is_watertight:
|
126
|
+
mesh = MeshComponent.fix_mesh(mesh)
|
127
|
+
except Exception:
|
128
|
+
pass
|
129
|
+
|
130
|
+
mesh = MeshComponent.mesh_to_output_size(
|
131
|
+
mesh,
|
132
|
+
resize_factor,
|
133
|
+
z_scaling_factor,
|
134
|
+
output_x_size,
|
135
|
+
skip_resize_to_expected_size=not include_zeros,
|
136
|
+
)
|
137
|
+
|
138
|
+
if remove_center:
|
139
|
+
mesh = MeshComponent.remove_center_from_mesh(mesh, remove_size)
|
140
|
+
|
125
141
|
return mesh
|
142
|
+
|
143
|
+
@staticmethod
|
144
|
+
def rotate_mesh(mesh: trimesh.Trimesh) -> trimesh.Trimesh:
|
145
|
+
"""Rotates the given mesh by 180 degrees around the Y-axis and Z-axis.
|
146
|
+
|
147
|
+
Arguments:
|
148
|
+
mesh (trimesh.Trimesh): The mesh to rotate.
|
149
|
+
|
150
|
+
Returns:
|
151
|
+
trimesh.Trimesh: The rotated mesh.
|
152
|
+
"""
|
153
|
+
mesh_copy = mesh.copy()
|
154
|
+
|
155
|
+
rotation_matrices = [
|
156
|
+
trimesh.transformations.rotation_matrix(np.pi, [0, 1, 0]),
|
157
|
+
trimesh.transformations.rotation_matrix(np.pi, [0, 0, 1]),
|
158
|
+
]
|
159
|
+
|
160
|
+
for rotation_matrix in tqdm(rotation_matrices, desc="Rotating mesh", unit="rotation"):
|
161
|
+
mesh_copy.apply_transform(rotation_matrix)
|
162
|
+
|
163
|
+
return mesh_copy
|
164
|
+
|
165
|
+
@staticmethod
|
166
|
+
def fix_mesh(mesh: trimesh.Trimesh) -> trimesh.Trimesh:
|
167
|
+
"""Fixes the given mesh by filling holes, fixing normals, fixing winding, fixing inversion,
|
168
|
+
fixing broken faces, and stitching.
|
169
|
+
|
170
|
+
Arguments:
|
171
|
+
mesh (trimesh.Trimesh): The mesh to fix.
|
172
|
+
|
173
|
+
Returns:
|
174
|
+
trimesh.Trimesh: The fixed mesh.
|
175
|
+
"""
|
176
|
+
mesh_copy = mesh.copy()
|
177
|
+
|
178
|
+
fix_methods = [
|
179
|
+
trimesh.repair.fill_holes,
|
180
|
+
trimesh.repair.fix_normals,
|
181
|
+
trimesh.repair.fix_winding,
|
182
|
+
trimesh.repair.fix_inversion,
|
183
|
+
trimesh.repair.broken_faces,
|
184
|
+
trimesh.repair.stitch,
|
185
|
+
]
|
186
|
+
|
187
|
+
for method in tqdm(fix_methods, desc="Fixing mesh", unit="method"):
|
188
|
+
method(mesh_copy) # type: ignore
|
189
|
+
|
190
|
+
return mesh_copy
|
191
|
+
|
192
|
+
@staticmethod
|
193
|
+
def mesh_to_output_size(
|
194
|
+
mesh: trimesh.Trimesh,
|
195
|
+
resize_factor: int,
|
196
|
+
z_scaling_factor: float,
|
197
|
+
expected_size: int,
|
198
|
+
skip_resize_to_expected_size: bool = False,
|
199
|
+
) -> trimesh.Trimesh:
|
200
|
+
"""Resizes the given mesh to the expected size.
|
201
|
+
|
202
|
+
Arguments:
|
203
|
+
mesh (trimesh.Trimesh): The mesh to resize.
|
204
|
+
resize_factor (int): The resizing factor.
|
205
|
+
z_scaling_factor (float): The scaling factor for the Z-axis.
|
206
|
+
expected_size (int): The expected size.
|
207
|
+
skip_resize_to_expected_size (bool): Whether to skip resizing to the expected size.
|
208
|
+
|
209
|
+
Returns:
|
210
|
+
trimesh.Trimesh: The resized mesh.
|
211
|
+
"""
|
212
|
+
mesh_copy = mesh.copy()
|
213
|
+
|
214
|
+
mesh_copy.apply_scale([resize_factor / 1, resize_factor / 1, z_scaling_factor])
|
215
|
+
|
216
|
+
if not skip_resize_to_expected_size:
|
217
|
+
x_size, y_size, _ = mesh_copy.extents
|
218
|
+
x_resize_factor = expected_size / x_size
|
219
|
+
y_resize_factor = expected_size / y_size
|
220
|
+
|
221
|
+
mesh_copy.apply_scale([x_resize_factor, y_resize_factor, 1])
|
222
|
+
return mesh_copy
|
223
|
+
|
224
|
+
@staticmethod
|
225
|
+
def remove_center_from_mesh(mesh: trimesh.Trimesh, remove_size: int) -> trimesh.Trimesh:
|
226
|
+
"""Removes the center from the given mesh.
|
227
|
+
|
228
|
+
Arguments:
|
229
|
+
mesh (trimesh.Trimesh): The mesh to remove the center from.
|
230
|
+
remove_size (int): The size of the center to remove.
|
231
|
+
|
232
|
+
Returns:
|
233
|
+
trimesh.Trimesh: The mesh with the center removed.
|
234
|
+
"""
|
235
|
+
mesh_copy = mesh.copy()
|
236
|
+
|
237
|
+
_, _, z_size = mesh_copy.extents
|
238
|
+
|
239
|
+
cube_mesh = trimesh.creation.box([remove_size, remove_size, z_size * 4])
|
240
|
+
cube_mesh.apply_translation(mesh_copy.centroid - cube_mesh.centroid)
|
241
|
+
|
242
|
+
return trimesh.boolean.difference([mesh_copy, cube_mesh], check_volume=False)
|
maps4fs/generator/settings.py
CHANGED
@@ -133,7 +133,7 @@ class BackgroundSettings(SettingsModel):
|
|
133
133
|
generate_background: bool = False
|
134
134
|
generate_water: bool = False
|
135
135
|
resize_factor: int = 8
|
136
|
-
remove_center: bool =
|
136
|
+
remove_center: bool = True
|
137
137
|
apply_decimation: bool = False
|
138
138
|
decimation_percent: int = 25
|
139
139
|
decimation_agression: int = 3
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: maps4fs
|
3
|
-
Version: 1.8.
|
3
|
+
Version: 1.8.173
|
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
|
@@ -582,7 +582,7 @@ You can also apply some advanced settings to the map generation process.<br>
|
|
582
582
|
|
583
583
|
- Resize factor - the factor by which the background terrain will be resized. It will be used as 1 / resize_factor while generating the models. Which means that the larger the value the more the terrain will be resized. The lowest value is 1, in this case background terrain will not be resized. Note, than low values will lead to long processing and enormous size of the obj files.
|
584
584
|
|
585
|
-
- Remove center - if enabled, the playable region (map terrain) will be removed from the background terrain.
|
585
|
+
- Remove center - if enabled, the playable region (map terrain) will be removed from the background terrain. By default, it's set to True.
|
586
586
|
|
587
587
|
- Apply decimation - if enabled, the mesh will be simplified to reduce the number of faces.
|
588
588
|
|
@@ -6,17 +6,17 @@ maps4fs/generator/game.py,sha256=YwtdzqwcBJm1FHtc1ehDd3WbfTTW_gBvxK-pzfU48zs,110
|
|
6
6
|
maps4fs/generator/map.py,sha256=c5GMhr5iTRdXvTXoBKyVYa2V1tocR3ZCc7D_hpU21k8,11523
|
7
7
|
maps4fs/generator/qgis.py,sha256=Es8hLuqN_KH8lDfnJE6He2rWYbAKJ3RGPn-o87S6CPI,6116
|
8
8
|
maps4fs/generator/satellite.py,sha256=t33EfaxWTCjcKYnqoppSlFdQQSekiBe7UFmLgTVhFQI,3650
|
9
|
-
maps4fs/generator/settings.py,sha256=
|
9
|
+
maps4fs/generator/settings.py,sha256=cFlN-gK8QcySqyPtcGm-2fLnxQnlmC3Y9kQufJxwI3Y,6270
|
10
10
|
maps4fs/generator/texture.py,sha256=_IfqIuxH4934VJXKtdABHa6ToPWk3T0xknvlu-rZ5Uc,36570
|
11
11
|
maps4fs/generator/component/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
|
12
|
-
maps4fs/generator/component/background.py,sha256=
|
12
|
+
maps4fs/generator/component/background.py,sha256=cBBp-ULrJzuNG9wfE_MaxzAn_mR24neqtL7WjxXEb3I,18749
|
13
13
|
maps4fs/generator/component/config.py,sha256=RitKgFDZPzjA1fi8GcEi1na75qqaueUvpcITHjBvCXc,3674
|
14
14
|
maps4fs/generator/component/grle.py,sha256=aKMjVJNuKHJJ2gsXaH00bz10kWaIbbZXU_JbP-ZAGw4,18990
|
15
15
|
maps4fs/generator/component/i3d.py,sha256=3x38yL-kSJ8ylBwICBb6wPYzRSky4gVj8XCk2jzYSeo,19861
|
16
16
|
maps4fs/generator/component/base/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
|
17
17
|
maps4fs/generator/component/base/component.py,sha256=U3XJae0GUvHN08psv2j24Y4PBAAytSkSK3AmD-VjjXE,21404
|
18
18
|
maps4fs/generator/component/base/component_image.py,sha256=vuiiJqsrKZgYsnK8Qa5yL2Pejqa6nJSTtXNAcBPL29c,3099
|
19
|
-
maps4fs/generator/component/base/component_mesh.py,sha256
|
19
|
+
maps4fs/generator/component/base/component_mesh.py,sha256=jtsEQZkqiCkycYpueq1M1eqgxdShL_bHaJT6Upu8PLI,8412
|
20
20
|
maps4fs/generator/component/base/component_xml.py,sha256=6OO1dKoceO1ACk7-k1oGtnkfNud8ZN3u3ZNjdNMpTqw,3967
|
21
21
|
maps4fs/generator/dtm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
maps4fs/generator/dtm/bavaria.py,sha256=7njrEvSCYAC8ZVyvS-_84iXHhWA0oHKrEqSzxdnZuGs,4293
|
@@ -42,8 +42,8 @@ maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,4
|
|
42
42
|
maps4fs/toolbox/background.py,sha256=RclEqxEWLbMxuEkkegQP8jybzugwQ1_R3rdfDe0s21U,2104
|
43
43
|
maps4fs/toolbox/custom_osm.py,sha256=X6ZlPqiOhNjkmdD_qVroIfdOl9Rb90cDwVSLDVYgx80,1892
|
44
44
|
maps4fs/toolbox/dem.py,sha256=z9IPFNmYbjiigb3t02ZenI3Mo8odd19c5MZbjDEovTo,3525
|
45
|
-
maps4fs-1.8.
|
46
|
-
maps4fs-1.8.
|
47
|
-
maps4fs-1.8.
|
48
|
-
maps4fs-1.8.
|
49
|
-
maps4fs-1.8.
|
45
|
+
maps4fs-1.8.173.dist-info/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
|
46
|
+
maps4fs-1.8.173.dist-info/METADATA,sha256=juPm5cwfn3XLlaUemJjP43yHQbW-9NYEljrHscMlGN4,42937
|
47
|
+
maps4fs-1.8.173.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
48
|
+
maps4fs-1.8.173.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
|
49
|
+
maps4fs-1.8.173.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|