maps4fs 0.9.3__py3-none-any.whl → 0.9.4__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.
@@ -95,11 +95,13 @@ class Background(Component):
95
95
  for tile in self.tiles:
96
96
  north, south, east, west = tile.bbox
97
97
  epsg3857_string = tile.get_epsg3857_string()
98
+ epsg3857_string_with_margin = tile.get_epsg3857_string(add_margin=True)
98
99
 
99
100
  tile_entry = {
100
101
  "center_latitude": tile.coordinates[0],
101
102
  "center_longitude": tile.coordinates[1],
102
103
  "epsg3857_string": epsg3857_string,
104
+ "epsg3857_string_with_margin": epsg3857_string_with_margin,
103
105
  "height": tile.map_height,
104
106
  "width": tile.map_width,
105
107
  "north": north,
@@ -115,10 +117,16 @@ class Background(Component):
115
117
  def qgis_sequence(self) -> None:
116
118
  """Generates QGIS scripts for creating bounding box layers and rasterizing them."""
117
119
  qgis_layers = [
118
- (f"Background_bbox_{tile.code}", *tile.get_espg3857_bbox()) for tile in self.tiles
120
+ (f"Background_{tile.code}", *tile.get_espg3857_bbox()) for tile in self.tiles
119
121
  ]
122
+ qgis_layers_with_margin = [
123
+ (f"Background_{tile.code}_margin", *tile.get_espg3857_bbox(add_margin=True))
124
+ for tile in self.tiles
125
+ ]
126
+
127
+ layers = qgis_layers + qgis_layers_with_margin
120
128
 
121
- self.create_qgis_scripts(qgis_layers) # type: ignore
129
+ self.create_qgis_scripts(layers)
122
130
 
123
131
  def generate_obj_files(self) -> None:
124
132
  """Iterates over all tiles and generates 3D obj files based on DEM data.
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Any
10
10
  import osmnx as ox # type: ignore
11
11
  from pyproj import Transformer
12
12
 
13
- from maps4fs.generator.qgis import get_bbox_template, get_rasterize_template
13
+ from maps4fs.generator.qgis import save_scripts
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from maps4fs.generator.game import Game
@@ -214,16 +214,17 @@ class Component:
214
214
  return west, south, east, north
215
215
 
216
216
  def get_espg3857_bbox(
217
- self, bbox: tuple[int, int, int, int] | None = None
218
- ) -> tuple[int, int, int, int]:
217
+ self, bbox: tuple[float, float, float, float] | None = None, add_margin: bool = False
218
+ ) -> tuple[float, float, float, float]:
219
219
  """Converts the bounding box to EPSG:3857.
220
220
  If the bounding box is not provided, the instance variable is used.
221
221
 
222
222
  Args:
223
- bbox (tuple[int, int, int, int], optional): The bounding box to convert.
223
+ bbox (tuple[float, float, float, float], optional): The bounding box to convert.
224
+ add_margin (bool, optional): Whether to add a margin to the bounding box.
224
225
 
225
226
  Returns:
226
- tuple[int, int, int, int]: The bounding box in EPSG:3857.
227
+ tuple[float, float, float, float]: The bounding box in EPSG:3857.
227
228
  """
228
229
  bbox = bbox or self.bbox
229
230
  north, south, east, west = bbox
@@ -231,19 +232,29 @@ class Component:
231
232
  epsg3857_north, epsg3857_west = transformer.transform(north, west)
232
233
  epsg3857_south, epsg3857_east = transformer.transform(south, east)
233
234
 
235
+ if add_margin:
236
+ MARGIN = 500 # pylint: disable=C0103
237
+ epsg3857_north = int(epsg3857_north - MARGIN)
238
+ epsg3857_south = int(epsg3857_south + MARGIN)
239
+ epsg3857_east = int(epsg3857_east - MARGIN)
240
+ epsg3857_west = int(epsg3857_west + MARGIN)
241
+
234
242
  return epsg3857_north, epsg3857_south, epsg3857_east, epsg3857_west
235
243
 
236
- def get_epsg3857_string(self, bbox: tuple[int, int, int, int] | None = None) -> str:
244
+ def get_epsg3857_string(
245
+ self, bbox: tuple[float, float, float, float] | None = None, add_margin: bool = False
246
+ ) -> str:
237
247
  """Converts the bounding box to EPSG:3857 string.
238
248
  If the bounding box is not provided, the instance variable is used.
239
249
 
240
250
  Args:
241
- bbox (tuple[int, int, int, int], optional): The bounding box to convert.
251
+ bbox (tuple[float, float, float, float], optional): The bounding box to convert.
252
+ add_margin (bool, optional): Whether to add a margin to the bounding box.
242
253
 
243
254
  Returns:
244
255
  str: The bounding box in EPSG:3857 string.
245
256
  """
246
- north, south, east, west = self.get_espg3857_bbox(bbox)
257
+ north, south, east, west = self.get_espg3857_bbox(bbox, add_margin=add_margin)
247
258
  return f"{north},{south},{east},{west} [EPSG:3857]"
248
259
 
249
260
  def create_qgis_scripts(
@@ -259,17 +270,4 @@ class Component:
259
270
  create scripts for.
260
271
  """
261
272
  class_name = self.__class__.__name__.lower()
262
-
263
- script_files = [
264
- (f"{class_name}_bbox.py", get_bbox_template),
265
- (f"{class_name}_rasterize.py", get_rasterize_template),
266
- ]
267
-
268
- for script_file, process_function in script_files:
269
- script_path = os.path.join(self.scripts_directory, script_file)
270
- script_content = process_function(qgis_layers) # type: ignore
271
-
272
- with open(script_path, "w", encoding="utf-8") as file:
273
- file.write(script_content)
274
-
275
- self.logger.info("QGIS script saved: %s", script_path)
273
+ save_scripts(qgis_layers, class_name, self.scripts_directory)
@@ -70,11 +70,13 @@ class Config(Component):
70
70
  bbox = self.get_bbox(height_distance=self.map_height, width_distance=self.map_width)
71
71
  south, west, north, east = bbox
72
72
  epsg3857_string = self.get_epsg3857_string(bbox=bbox)
73
+ epsg3857_string_with_margin = self.get_epsg3857_string(bbox=bbox, add_margin=True)
73
74
 
74
75
  self.qgis_sequence()
75
76
 
76
77
  overview_data = {
77
78
  "epsg3857_string": epsg3857_string,
79
+ "epsg3857_string_with_margin": epsg3857_string_with_margin,
78
80
  "south": south,
79
81
  "west": west,
80
82
  "north": north,
@@ -93,7 +95,11 @@ class Config(Component):
93
95
  """Generates QGIS scripts for creating bounding box layers and rasterizing them."""
94
96
  bbox = self.get_bbox(height_distance=self.map_height, width_distance=self.map_width)
95
97
  espg3857_bbox = self.get_espg3857_bbox(bbox=bbox)
98
+ espg3857_bbox_with_margin = self.get_espg3857_bbox(bbox=bbox, add_margin=True)
96
99
 
97
100
  qgis_layers = [("Overview_bbox", *espg3857_bbox)]
101
+ qgis_layers_with_margin = [("Overview_bbox_with_margin", *espg3857_bbox_with_margin)]
98
102
 
99
- self.create_qgis_scripts(qgis_layers) # type: ignore
103
+ layers = qgis_layers + qgis_layers_with_margin
104
+
105
+ self.create_qgis_scripts(layers)
maps4fs/generator/qgis.py CHANGED
@@ -1,11 +1,13 @@
1
1
  """This module contains templates for generating QGIS scripts."""
2
2
 
3
+ import os
4
+
3
5
  BBOX_TEMPLATE = """
4
6
  layers = [
5
7
  {layers}
6
8
  ]
7
9
  for layer in layers:
8
- name = layer[0]
10
+ name = "Bounding_Box_" + layer[0]
9
11
  north, south, east, west = layer[1:]
10
12
 
11
13
  # Create a rectangle geometry from the bounding box.
@@ -34,6 +36,42 @@ for layer in layers:
34
36
  layer.triggerRepaint()
35
37
  """
36
38
 
39
+ POINT_TEMPLATE = """
40
+ layers = [
41
+ {layers}
42
+ ]
43
+ for layer in layers:
44
+ name = "Points_" + layer[0]
45
+ north, south, east, west = layer[1:]
46
+
47
+ top_left = QgsPointXY(north, west)
48
+ top_right = QgsPointXY(north, east)
49
+ bottom_right = QgsPointXY(south, east)
50
+ bottom_left = QgsPointXY(south, west)
51
+
52
+ points = [top_left, top_right, bottom_right, bottom_left, top_left]
53
+
54
+ # Create a new layer
55
+ layer = QgsVectorLayer('Point?crs=EPSG:4326', name, 'memory')
56
+ provider = layer.dataProvider()
57
+
58
+ # Add fields
59
+ provider.addAttributes([QgsField("id", QVariant.Int)])
60
+ layer.updateFields()
61
+
62
+ # Create and add features for each point
63
+ for i, point in enumerate(points):
64
+ feature = QgsFeature()
65
+ feature.setGeometry(QgsGeometry.fromPointXY(point))
66
+ feature.setAttributes([i + 1])
67
+ provider.addFeature(feature)
68
+
69
+ layer.updateExtents()
70
+
71
+ # Add the layer to the project
72
+ QgsProject.instance().addMapLayer(layer)
73
+ """
74
+
37
75
  RASTERIZE_TEMPLATE = """
38
76
  import processing
39
77
 
@@ -74,17 +112,18 @@ for layer in layers:
74
112
  """
75
113
 
76
114
 
77
- def get_bbox_template(layers: list[tuple[str, float, float, float, float]]) -> str:
78
- """Returns a template for creating bounding box layers in QGIS.
115
+ def _get_template(layers: list[tuple[str, float, float, float, float]], template: str) -> str:
116
+ """Returns a template for creating layers in QGIS.
79
117
 
80
118
  Args:
81
119
  layers (list[tuple[str, float, float, float, float]]): A list of tuples containing the
82
120
  layer name and the bounding box coordinates.
121
+ template (str): The template for creating layers in QGIS.
83
122
 
84
123
  Returns:
85
- str: The template for creating bounding box layers in QGIS.
124
+ str: The template for creating layers in QGIS.
86
125
  """
87
- return BBOX_TEMPLATE.format(
126
+ return template.format(
88
127
  layers=",\n ".join(
89
128
  [
90
129
  f'("{name}", {north}, {south}, {east}, {west})'
@@ -94,6 +133,32 @@ def get_bbox_template(layers: list[tuple[str, float, float, float, float]]) -> s
94
133
  )
95
134
 
96
135
 
136
+ def get_bbox_template(layers: list[tuple[str, float, float, float, float]]) -> str:
137
+ """Returns a template for creating bounding box layers in QGIS.
138
+
139
+ Args:
140
+ layers (list[tuple[str, float, float, float, float]]): A list of tuples containing the
141
+ layer name and the bounding box coordinates.
142
+
143
+ Returns:
144
+ str: The template for creating bounding box layers in QGIS.
145
+ """
146
+ return _get_template(layers, BBOX_TEMPLATE)
147
+
148
+
149
+ def get_point_template(layers: list[tuple[str, float, float, float, float]]) -> str:
150
+ """Returns a template for creating point layers in QGIS.
151
+
152
+ Args:
153
+ layers (list[tuple[str, float, float, float, float]]): A list of tuples containing the
154
+ layer name and the bounding box coordinates.
155
+
156
+ Returns:
157
+ str: The template for creating point layers in QGIS.
158
+ """
159
+ return _get_template(layers, POINT_TEMPLATE)
160
+
161
+
97
162
  def get_rasterize_template(layers: list[tuple[str, float, float, float, float]]) -> str:
98
163
  """Returns a template for rasterizing bounding box layers in QGIS.
99
164
 
@@ -104,11 +169,28 @@ def get_rasterize_template(layers: list[tuple[str, float, float, float, float]])
104
169
  Returns:
105
170
  str: The template for rasterizing bounding box layers in QGIS.
106
171
  """
107
- return RASTERIZE_TEMPLATE.format(
108
- layers=",\n ".join(
109
- [
110
- f'("{name}", {north}, {south}, {east}, {west})'
111
- for name, north, south, east, west in layers
112
- ]
113
- )
114
- )
172
+ return _get_template(layers, RASTERIZE_TEMPLATE)
173
+
174
+
175
+ def save_scripts(
176
+ layers: list[tuple[str, float, float, float, float]], file_prefix: str, save_directory: str
177
+ ) -> None:
178
+ """Saves QGIS scripts for creating bounding box, point, and raster layers.
179
+
180
+ Args:
181
+ layers (list[tuple[str, float, float, float, float]]): A list of tuples containing the
182
+ layer name and the bounding box coordinates.
183
+ save_dir (str): The directory to save the scripts.
184
+ """
185
+ script_files = [
186
+ (f"{file_prefix}_bbox.py", get_bbox_template),
187
+ (f"{file_prefix}_rasterize.py", get_rasterize_template),
188
+ (f"{file_prefix}_point.py", get_point_template),
189
+ ]
190
+
191
+ for script_file, process_function in script_files:
192
+ script_path = os.path.join(save_directory, script_file)
193
+ script_content = process_function(layers) # type: ignore
194
+
195
+ with open(script_path, "w", encoding="utf-8") as file:
196
+ file.write(script_content)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: maps4fs
3
- Version: 0.9.3
3
+ Version: 0.9.4
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
@@ -23,7 +23,9 @@ Requires-Dist: imageio
23
23
  Requires-Dist: tifffile
24
24
 
25
25
  <div align="center" markdown>
26
- <img src="https://github.com/iwatkot/maps4fs/assets/118521851/ffd7f0a3-e317-4c3f-911f-2c2fb736fbfa">
26
+ <a href="https://discord.gg/Sj5QKKyE42">
27
+ <img src="https://github.com/user-attachments/assets/37043333-d6ef-4ca3-9f3c-81323d9d0b71">
28
+ </a>
27
29
 
28
30
  <p align="center">
29
31
  <a href="#Quick-Start">Quick Start</a> •
@@ -41,6 +43,7 @@ Requires-Dist: tifffile
41
43
  </p>
42
44
 
43
45
 
46
+ [![Join Discord](https://img.shields.io/badge/join-discord-blue)](https://discord.gg/Sj5QKKyE42)
44
47
  [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/iwatkot/maps4fs)](https://github.com/iwatkot/maps4fs/releases)
45
48
  [![PyPI - Version](https://img.shields.io/pypi/v/maps4fs)](https://pypi.org/project/maps4fs)
46
49
  [![Docker Pulls](https://img.shields.io/docker/pulls/iwatkot/maps4fs)](https://hub.docker.com/repository/docker/iwatkot/maps4fs/general)
@@ -1,19 +1,19 @@
1
1
  maps4fs/__init__.py,sha256=da4jmND2Ths9AffnkAKgzLHNkvKFOc_l21gJisPXqWY,155
2
2
  maps4fs/logger.py,sha256=8oZzAKJllilYrVp452LX0zx-dNFwpS6UngbTrI6KfwA,2148
3
3
  maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
4
- maps4fs/generator/background.py,sha256=M43VNwiAnL4-1iUGAFwwwl5lV5EVy4luvZZmsuGO_Co,12642
5
- maps4fs/generator/component.py,sha256=tLjjbrFn3v4CrUrUOgH9s8NuJhmQcBs74ShefkNg1VE,10584
6
- maps4fs/generator/config.py,sha256=JL7leQv8C06JQOXIbgQ-jve2re7cNsx8vKa8dfbnxPM,3896
4
+ maps4fs/generator/background.py,sha256=6mN2xRg5XEqsLaXPUqdNGgDR1Ats60fBK93WlDeB8EI,13002
5
+ maps4fs/generator/component.py,sha256=ZEDjChPnvqAsgnBu2f2YBOlwGOlfax4VaAYBcJerLIQ,10684
6
+ maps4fs/generator/config.py,sha256=ZO5BWDU-S3p0-ndKDSFa8Oin3YcYy0iH8B4lqEA_07Q,4275
7
7
  maps4fs/generator/dem.py,sha256=p7THncPUdYWtNR2HrTXe0bCuJ8psUV8rRpYPJkzL2gA,15220
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
11
11
  maps4fs/generator/path_steps.py,sha256=yeN6hmOD8O2LMozUf4HcQMIy8WJ5sHF5pGQT_s2FfOw,3147
12
- maps4fs/generator/qgis.py,sha256=k19miPEFyOdu_ogBFHmFVfYQ-IgF38ufJZ5DM5NSHBQ,3400
12
+ maps4fs/generator/qgis.py,sha256=vhV-EwZKK-p1qEV-2H_yckuktx8ezlCMnmJJfUt1HGI,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.3.dist-info/LICENSE.md,sha256=-JY0v7p3dwXze61EbYiK7YEJ2aKrjaFZ8y2xYEOrmRY,1068
16
- maps4fs-0.9.3.dist-info/METADATA,sha256=0iPJEUJXeSqgNXqhcD2BM5lqkvX7YBK2O-UFWY5HxvM,23996
17
- maps4fs-0.9.3.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
18
- maps4fs-0.9.3.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
19
- maps4fs-0.9.3.dist-info/RECORD,,
15
+ maps4fs-0.9.4.dist-info/LICENSE.md,sha256=-JY0v7p3dwXze61EbYiK7YEJ2aKrjaFZ8y2xYEOrmRY,1068
16
+ maps4fs-0.9.4.dist-info/METADATA,sha256=WVUjB4PmrCnuWZNIVurx3_1XPqS2oBEwWdVaU22uX2Y,24130
17
+ maps4fs-0.9.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
18
+ maps4fs-0.9.4.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
19
+ maps4fs-0.9.4.dist-info/RECORD,,