maps4fs 2.2.1__py3-none-any.whl → 2.2.3__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.
@@ -597,6 +597,7 @@ class Background(MeshComponent, ImageComponent):
597
597
  polygon_points=polygon.exterior.coords,
598
598
  angle=self.rotation,
599
599
  canvas_size=self.background_size,
600
+ xshift=-Parameters.BACKGROUND_DISTANCE,
600
601
  )
601
602
  fitted_polygon = shapely.Polygon(fitted_polygon_points)
602
603
  fitted_polygons.append(fitted_polygon)
@@ -365,6 +365,8 @@ class Component:
365
365
  angle: int = 0,
366
366
  border: int = 0,
367
367
  canvas_size: int | None = None,
368
+ xshift: int = 0,
369
+ yshift: int = 0,
368
370
  ) -> list[tuple[int, int]]:
369
371
  """Fits a polygon into the bounds of the map.
370
372
 
@@ -374,6 +376,9 @@ class Component:
374
376
  margin (int, optional): The margin to add to the polygon. Defaults to 0.
375
377
  angle (int, optional): The angle to rotate the polygon by. Defaults to 0.
376
378
  border (int, optional): The border to add to the bounds. Defaults to 0.
379
+ canvas_size (int, optional): The size of the canvas. Defaults to None.
380
+ xshift (int, optional): The x-axis shift to apply. Will be added to calculated offset.
381
+ yshift (int, optional): The y-axis shift to apply. Will be added to calculated offset.
377
382
 
378
383
  Returns:
379
384
  list[tuple[int, int]]: The points of the polygon fitted into the map bounds.
@@ -400,8 +405,11 @@ class Component:
400
405
  )
401
406
  osm_object = rotate(osm_object, -angle, origin=(center_x, center_y))
402
407
  offset = int((self.map_size / 2) - (self.map_rotated_size / 2)) * self.map.size_scale
403
- self.logger.debug("Translating the osm_object by %s", offset)
404
- osm_object = translate(osm_object, xoff=offset, yoff=offset)
408
+ xoff = yoff = offset
409
+ xoff += xshift
410
+ yoff += yshift
411
+ self.logger.debug("Translating the osm_object by X: %s, Y: %s", xoff, yoff)
412
+ osm_object = translate(osm_object, xoff=xoff, yoff=yoff)
405
413
  self.logger.debug("Rotated and translated the osm_object.")
406
414
 
407
415
  if margin and object_type is Polygon:
@@ -49,6 +49,7 @@ class Layer:
49
49
  area_type: str | None = None,
50
50
  area_water: bool = False,
51
51
  indoor: bool = False,
52
+ merge_into: str | None = None,
52
53
  ):
53
54
  self.name = name
54
55
  self.count = count
@@ -68,6 +69,7 @@ class Layer:
68
69
  self.area_type = area_type
69
70
  self.area_water = area_water
70
71
  self.indoor = indoor
72
+ self.merge_into = merge_into
71
73
 
72
74
  def to_json(self) -> dict[str, str | list[str] | bool]: # type: ignore
73
75
  """Returns dictionary with layer data.
@@ -93,6 +95,7 @@ class Layer:
93
95
  "area_type": self.area_type,
94
96
  "area_water": self.area_water,
95
97
  "indoor": self.indoor,
98
+ "merge_into": self.merge_into,
96
99
  }
97
100
 
98
101
  data = {k: v for k, v in data.items() if v is not None}
@@ -172,6 +172,7 @@ class Texture(ImageComponent):
172
172
  self._read_parameters()
173
173
  self.draw()
174
174
  self.rotate_textures()
175
+ self.merge_into()
175
176
 
176
177
  if not self.kwargs.get("skip_scaling", False):
177
178
  self.scale_textures()
@@ -256,6 +257,46 @@ class Texture(ImageComponent):
256
257
  "Procedural file %s copied from %s.", procedural_save_path, texture_paths[0]
257
258
  )
258
259
 
260
+ def get_layer_by_name(self, layer_name: str) -> Layer | None:
261
+ """Returns the layer with the given name.
262
+
263
+ Arguments:
264
+ layer_name: The name of the layer to retrieve.
265
+
266
+ Returns:
267
+ The layer with the given name, or None if not found.
268
+ """
269
+ for layer in self.layers:
270
+ if layer.name == layer_name:
271
+ return layer
272
+ return None
273
+
274
+ def merge_into(self) -> None:
275
+ """Merges the content of layers into their target layers."""
276
+ for layer in self.layers:
277
+ if layer.merge_into:
278
+ target_layer = self.get_layer_by_name(layer.merge_into)
279
+ if target_layer:
280
+ target_layer_image = cv2.imread(
281
+ target_layer.path(self._weights_dir), cv2.IMREAD_UNCHANGED
282
+ )
283
+ layer_image = cv2.imread(layer.path(self._weights_dir), cv2.IMREAD_UNCHANGED)
284
+ if target_layer_image is not None and layer_image is not None:
285
+ if target_layer_image.shape != layer_image.shape:
286
+ self.logger.warning(
287
+ "Layer %s and target layer %s have different shapes, skipping merge.",
288
+ layer.name,
289
+ target_layer.name,
290
+ )
291
+ continue
292
+ target_layer_image = cv2.add(target_layer_image, layer_image)
293
+ cv2.imwrite(target_layer.path(self._weights_dir), target_layer_image)
294
+ self.logger.debug("Merged layer %s into %s.", layer.name, target_layer.name)
295
+
296
+ # Clear the content of the layer which have merge_into property.
297
+ cv2.imwrite(layer.path(self._weights_dir), np.zeros_like(layer_image))
298
+ self.logger.debug("Cleared layer %s.", layer.name)
299
+
259
300
  def rotate_textures(self) -> None:
260
301
  """Rotates textures of the layers which have tags."""
261
302
  if self.rotation:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maps4fs
3
- Version: 2.2.1
3
+ Version: 2.2.3
4
4
  Summary: Generate map templates for Farming Simulator from real places.
5
5
  Author-email: iwatkot <iwatkot@gmail.com>
6
6
  License: Apache License 2.0
@@ -54,6 +54,7 @@ Dynamic: license-file
54
54
  <a href="docs/step_by_step.md">Create a map in 10 steps</a> •
55
55
  <a href="docs/recommendations.md">Practical recommendations</a> •
56
56
  <a href="#How-To-Run">How-To-Run</a><br>
57
+ <a href="docs/my_maps.md">My Maps</a> •
57
58
  <a href="docs/FAQ.md">FAQ</a> •
58
59
  <a href="docs/map_structure.md">Map Structure</a> •
59
60
  <a href="#Schemas-Editor">Schemas Editor</a> •
@@ -565,6 +566,7 @@ Let's have a closer look at the fields:
565
566
  - `area_type` - one of the supported by Giants Editor area types, such as: "open_land", "city", "village", "harbor", "industrial", "open_water". It will be reflected in the environment info layer file.
566
567
  - `area_water` - whenever this field is set to true, the area will be considered as water, and it will be changed in the environment info layer file.
567
568
  - `indoor` - whenever this field is set to true, the area will be considered as indoor, and it will be reflected in the indoorMask info layer.
569
+ - `merge_into` - if specified, the layer with this parameter will be merged into the target layer and the content of the layer will be transferred to the target layer.
568
570
 
569
571
  ## Background terrain
570
572
 
@@ -8,21 +8,21 @@ maps4fs/generator/qgis.py,sha256=Es8hLuqN_KH8lDfnJE6He2rWYbAKJ3RGPn-o87S6CPI,611
8
8
  maps4fs/generator/settings.py,sha256=NukAt1s4CS0HEWmUcBPc8OiqkWqjts3AvvkX0APZKes,11385
9
9
  maps4fs/generator/statistics.py,sha256=aynS3zbAtiwnU_YLKHPTiiaKW98_suvQUhy1SGBA6mc,2448
10
10
  maps4fs/generator/component/__init__.py,sha256=s01yVVVi8R2xxNvflu2D6wTd9I_g73AMM2x7vAC7GX4,490
11
- maps4fs/generator/component/background.py,sha256=JANbVgcBXpaQ0HB1eeV16KkFgpU-Txj5kB5eJNEDAv0,34473
11
+ maps4fs/generator/component/background.py,sha256=-GNA6zdQmfu7Oi4Cny0uhxlgl39VbvhEGhl4wKdh0ew,34533
12
12
  maps4fs/generator/component/config.py,sha256=uL76h9UwyhZKZmbxz0mBmWtEPN6qYay4epTEqqtej60,8601
13
13
  maps4fs/generator/component/dem.py,sha256=mtsdTIcEHmR9mW1LMcCaX4F2OCch9BM_WXHkvJby9ZY,11930
14
14
  maps4fs/generator/component/grle.py,sha256=3BKGlR0q0t0NvmqeT81WieS6MIc_UlMQjIDDZiqTiws,27243
15
15
  maps4fs/generator/component/i3d.py,sha256=RvpiW9skkZ6McyahC-AeIdPuSQjpXiFs1l0xOioJAu4,26638
16
- maps4fs/generator/component/layer.py,sha256=U_DzJTn1m_yGOtwuvbXxr7oL7YHHBGBcK37lyJNnZDk,6508
16
+ maps4fs/generator/component/layer.py,sha256=bdy1XGOODyPqYUM3b_wEY2H9Piz-AaHsCDecl-qRHiM,6627
17
17
  maps4fs/generator/component/satellite.py,sha256=9nKwL8zQ-BB6WFMx2m8zduFn6RaxSNv6Vtpge1-QMYE,5052
18
- maps4fs/generator/component/texture.py,sha256=Ngvfe51grb6Ead6WvNjx1Zr0yz65y8y2vY8xUteLoNo,35019
18
+ maps4fs/generator/component/texture.py,sha256=gXZgr73ehT3_qjuIku0j7N7exloywtmmEQKBJ-MDcco,36988
19
19
  maps4fs/generator/component/base/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
20
- maps4fs/generator/component/base/component.py,sha256=AP7b6rmYV_HdyyHlCTo9s6fyBXyyqGyBv-DYVynBGws,22884
20
+ maps4fs/generator/component/base/component.py,sha256=lf0V9CLUXMg88Nm2yI3rP5taVYYlNivud0x6kbhBYqA,23312
21
21
  maps4fs/generator/component/base/component_image.py,sha256=WTGC6v1KuS5sLNCC95Z48nCspvATKKNOuhTNYzTWXr4,8315
22
22
  maps4fs/generator/component/base/component_mesh.py,sha256=3hC-qDT8Vde6SmRMqs9USAkrF-gL2dDTYW71ATpxUS4,9130
23
23
  maps4fs/generator/component/base/component_xml.py,sha256=MT-VhU2dEckLFxAgmxg6V3gnv11di_94Qq6atfpOLdc,5342
24
- maps4fs-2.2.1.dist-info/licenses/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
25
- maps4fs-2.2.1.dist-info/METADATA,sha256=cMaMkvanQQIYGtV3u0BV5CXZ9t4Jlm64ngl9DqVUf5w,46032
26
- maps4fs-2.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- maps4fs-2.2.1.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
28
- maps4fs-2.2.1.dist-info/RECORD,,
24
+ maps4fs-2.2.3.dist-info/licenses/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
25
+ maps4fs-2.2.3.dist-info/METADATA,sha256=_DBytlg4xeIbCRKklRtwA_dgB6FWk7bF3OAMXqPfnLk,46244
26
+ maps4fs-2.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ maps4fs-2.2.3.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
28
+ maps4fs-2.2.3.dist-info/RECORD,,