maps4fs 1.6.91__py3-none-any.whl → 1.7.1__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.py +6 -15
- maps4fs/generator/settings.py +1 -1
- maps4fs/generator/texture.py +42 -47
- {maps4fs-1.6.91.dist-info → maps4fs-1.7.1.dist-info}/METADATA +14 -9
- {maps4fs-1.6.91.dist-info → maps4fs-1.7.1.dist-info}/RECORD +8 -8
- {maps4fs-1.6.91.dist-info → maps4fs-1.7.1.dist-info}/WHEEL +1 -1
- {maps4fs-1.6.91.dist-info → maps4fs-1.7.1.dist-info}/LICENSE.md +0 -0
- {maps4fs-1.6.91.dist-info → maps4fs-1.7.1.dist-info}/top_level.txt +0 -0
maps4fs/generator/component.py
CHANGED
@@ -188,8 +188,7 @@ class Component:
|
|
188
188
|
self,
|
189
189
|
coordinates: tuple[float, float] | None = None,
|
190
190
|
distance: int | None = None,
|
191
|
-
|
192
|
-
) -> tuple[int, int, int, int]:
|
191
|
+
) -> tuple[float, float, float, float]:
|
193
192
|
"""Calculates the bounding box of the map from the coordinates and the height and
|
194
193
|
width of the map.
|
195
194
|
If coordinates and distance are not provided, the instance variables are used.
|
@@ -199,24 +198,23 @@ class Component:
|
|
199
198
|
of the map. Defaults to None.
|
200
199
|
distance (int, optional): The distance from the center of the map to the edge of the
|
201
200
|
map in all directions. Defaults to None.
|
202
|
-
project_utm (bool, optional): Whether to project the bounding box to UTM.
|
203
201
|
|
204
202
|
Returns:
|
205
|
-
tuple[
|
203
|
+
tuple[float, float, float, float]: The bounding box of the map.
|
206
204
|
"""
|
207
205
|
coordinates = coordinates or self.coordinates
|
208
206
|
distance = distance or int(self.map_rotated_size / 2)
|
209
207
|
|
210
208
|
west, south, east, north = ox.utils_geo.bbox_from_point( # type: ignore
|
211
|
-
coordinates,
|
209
|
+
coordinates,
|
210
|
+
dist=distance,
|
212
211
|
)
|
213
212
|
|
214
213
|
bbox = north, south, east, west
|
215
214
|
self.logger.debug(
|
216
|
-
"Calculated bounding box for component: %s: %s,
|
215
|
+
"Calculated bounding box for component: %s: %s, distance: %s",
|
217
216
|
self.__class__.__name__,
|
218
217
|
bbox,
|
219
|
-
project_utm,
|
220
218
|
distance,
|
221
219
|
)
|
222
220
|
return bbox
|
@@ -225,7 +223,7 @@ class Component:
|
|
225
223
|
"""Saves the bounding box of the map to the component instance from the coordinates and the
|
226
224
|
height and width of the map.
|
227
225
|
"""
|
228
|
-
self.bbox = self.get_bbox(
|
226
|
+
self.bbox = self.get_bbox()
|
229
227
|
self.logger.debug("Saved bounding box: %s", self.bbox)
|
230
228
|
|
231
229
|
@property
|
@@ -544,17 +542,10 @@ class Component:
|
|
544
542
|
"""
|
545
543
|
|
546
544
|
scaling_factor = 1 / self.map.dem_settings.multiplier
|
547
|
-
self.logger.debug("Z scaling factor including DEM multiplier: %s", scaling_factor)
|
548
545
|
|
549
546
|
if self.map.shared_settings.height_scale_multiplier:
|
550
547
|
scaling_factor *= self.map.shared_settings.height_scale_multiplier
|
551
|
-
self.logger.debug(
|
552
|
-
"Z scaling factor including height scale multiplier: %s", scaling_factor
|
553
|
-
)
|
554
548
|
if self.map.shared_settings.mesh_z_scaling_factor:
|
555
549
|
scaling_factor *= 1 / self.map.shared_settings.mesh_z_scaling_factor
|
556
|
-
self.logger.debug(
|
557
|
-
"Z scaling factor including mesh z scaling factor: %s", scaling_factor
|
558
|
-
)
|
559
550
|
|
560
551
|
return scaling_factor
|
maps4fs/generator/settings.py
CHANGED
maps4fs/generator/texture.py
CHANGED
@@ -336,19 +336,12 @@ class Texture(Component):
|
|
336
336
|
# pylint: disable=W0201
|
337
337
|
def _read_parameters(self) -> None:
|
338
338
|
"""Reads map parameters from OSM data, such as:
|
339
|
-
- minimum and maximum coordinates
|
339
|
+
- minimum and maximum coordinates
|
340
340
|
- map dimensions in meters
|
341
341
|
- map coefficients (meters per pixel)
|
342
342
|
"""
|
343
|
-
|
344
|
-
|
345
|
-
# Parameters of the map in UTM format (meters).
|
346
|
-
self.minimum_x = min(west, east)
|
347
|
-
self.minimum_y = min(south, north)
|
348
|
-
self.maximum_x = max(west, east)
|
349
|
-
self.maximum_y = max(south, north)
|
350
|
-
self.logger.debug("Map minimum coordinates (XxY): %s x %s.", self.minimum_x, self.minimum_y)
|
351
|
-
self.logger.debug("Map maximum coordinates (XxY): %s x %s.", self.maximum_x, self.maximum_y)
|
343
|
+
bbox = ox.utils_geo.bbox_from_point(self.coordinates, dist=self.map_rotated_size / 2)
|
344
|
+
self.minimum_x, self.minimum_y, self.maximum_x, self.maximum_y = bbox
|
352
345
|
|
353
346
|
def info_sequence(self) -> dict[str, Any]:
|
354
347
|
"""Returns the JSON representation of the generation info for textures."""
|
@@ -576,29 +569,19 @@ class Texture(Component):
|
|
576
569
|
cv2.imwrite(layer_path, img)
|
577
570
|
self.logger.debug("Base texture %s saved.", layer_path)
|
578
571
|
|
579
|
-
def
|
580
|
-
"""Converts
|
572
|
+
def latlon_to_pixel(self, lat: float, lon: float) -> tuple[int, int]:
|
573
|
+
"""Converts latitude and longitude to pixel coordinates.
|
581
574
|
|
582
575
|
Arguments:
|
583
|
-
|
576
|
+
lat (float): Latitude.
|
577
|
+
lon (float): Longitude.
|
584
578
|
|
585
579
|
Returns:
|
586
|
-
int:
|
580
|
+
tuple[int, int]: Pixel coordinates.
|
587
581
|
"""
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
"""Converts UTM Y coordinate to relative Y coordinate in map image.
|
592
|
-
|
593
|
-
Arguments:
|
594
|
-
y (float): UTM Y coordinate.
|
595
|
-
|
596
|
-
Returns:
|
597
|
-
int: Relative Y coordinate in map image.
|
598
|
-
"""
|
599
|
-
return int(
|
600
|
-
self.map_rotated_size * (1 - (y - self.minimum_y) / (self.maximum_y - self.minimum_y))
|
601
|
-
)
|
582
|
+
x = int((lon - self.minimum_x) / (self.maximum_x - self.minimum_x) * self.map_rotated_size)
|
583
|
+
y = int((lat - self.maximum_y) / (self.minimum_y - self.maximum_y) * self.map_rotated_size)
|
584
|
+
return x, y
|
602
585
|
|
603
586
|
def np_to_polygon_points(self, np_array: np.ndarray) -> list[tuple[int, int]]:
|
604
587
|
"""Converts numpy array of polygon points to list of tuples.
|
@@ -623,11 +606,13 @@ class Texture(Component):
|
|
623
606
|
Returns:
|
624
607
|
np.ndarray: Numpy array of polygon points.
|
625
608
|
"""
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
609
|
+
coords = list(geometry.exterior.coords)
|
610
|
+
pts = np.array(
|
611
|
+
[self.latlon_to_pixel(coord[1], coord[0]) for coord in coords],
|
612
|
+
np.int32,
|
613
|
+
)
|
614
|
+
pts = pts.reshape((-1, 1, 2))
|
615
|
+
return pts
|
631
616
|
|
632
617
|
def _to_polygon(
|
633
618
|
self, obj: pd.core.series.Series, width: int | None
|
@@ -664,9 +649,20 @@ class Texture(Component):
|
|
664
649
|
Returns:
|
665
650
|
shapely.geometry.polygon.Polygon: Polygon geometry.
|
666
651
|
"""
|
667
|
-
polygon = geometry.buffer(width)
|
652
|
+
polygon = geometry.buffer(self.meters_to_degrees(width) if width else 0)
|
668
653
|
return polygon
|
669
654
|
|
655
|
+
def meters_to_degrees(self, meters: int) -> float:
|
656
|
+
"""Converts meters to degrees.
|
657
|
+
|
658
|
+
Arguments:
|
659
|
+
meters (int): Meters.
|
660
|
+
|
661
|
+
Returns:
|
662
|
+
float: Degrees.
|
663
|
+
"""
|
664
|
+
return meters / 111320
|
665
|
+
|
670
666
|
def _skip(
|
671
667
|
self, geometry: shapely.geometry.polygon.Polygon, *args, **kwargs
|
672
668
|
) -> shapely.geometry.polygon.Polygon:
|
@@ -724,46 +720,43 @@ class Texture(Component):
|
|
724
720
|
except Exception as e: # pylint: disable=W0718
|
725
721
|
self.logger.debug("Error fetching objects for tags: %s. Error: %s.", tags, e)
|
726
722
|
return
|
727
|
-
|
728
|
-
self.logger.debug("Fetched %s elements for tags: %s.", len(objects_utm), tags)
|
723
|
+
self.logger.debug("Fetched %s elements for tags: %s.", len(objects), tags)
|
729
724
|
|
730
725
|
method = self.linestrings_generator if yield_linestrings else self.polygons_generator
|
731
726
|
|
732
|
-
yield from method(
|
727
|
+
yield from method(objects, width, is_fieds)
|
733
728
|
|
734
729
|
def linestrings_generator(
|
735
|
-
self,
|
730
|
+
self, objects: pd.core.frame.DataFrame, *args, **kwargs
|
736
731
|
) -> Generator[list[tuple[int, int]], None, None]:
|
737
732
|
"""Generator which yields lists of point coordinates which represent LineStrings from OSM.
|
738
733
|
|
739
734
|
Arguments:
|
740
|
-
|
735
|
+
objects (pd.core.frame.DataFrame): Dataframe with OSM objects.
|
741
736
|
|
742
737
|
Yields:
|
743
738
|
Generator[list[tuple[int, int]], None, None]: List of point coordinates.
|
744
739
|
"""
|
745
|
-
for _, obj in
|
740
|
+
for _, obj in objects.iterrows():
|
746
741
|
geometry = obj["geometry"]
|
747
742
|
if isinstance(geometry, shapely.geometry.linestring.LineString):
|
748
|
-
points = [
|
749
|
-
(self.get_relative_x(x), self.get_relative_y(y)) for x, y in geometry.coords
|
750
|
-
]
|
743
|
+
points = [self.latlon_to_pixel(x, y) for y, x in geometry.coords]
|
751
744
|
yield points
|
752
745
|
|
753
746
|
def polygons_generator(
|
754
|
-
self,
|
747
|
+
self, objects: pd.core.frame.DataFrame, width: int | None, is_fieds: bool
|
755
748
|
) -> Generator[np.ndarray, None, None]:
|
756
749
|
"""Generator which yields numpy arrays of polygons from OSM data.
|
757
750
|
|
758
751
|
Arguments:
|
759
|
-
|
752
|
+
objects (pd.core.frame.DataFrame): Dataframe with OSM objects.
|
760
753
|
width (int | None): Width of the polygon in meters (only for LineString).
|
761
754
|
is_fieds (bool): Flag to determine if the fields should be padded.
|
762
755
|
|
763
756
|
Yields:
|
764
757
|
Generator[np.ndarray, None, None]: Numpy array of polygon points.
|
765
758
|
"""
|
766
|
-
for _, obj in
|
759
|
+
for _, obj in objects.iterrows():
|
767
760
|
try:
|
768
761
|
polygon = self._to_polygon(obj, width)
|
769
762
|
except Exception as e: # pylint: disable=W0703
|
@@ -773,7 +766,9 @@ class Texture(Component):
|
|
773
766
|
continue
|
774
767
|
|
775
768
|
if is_fieds and self.map.texture_settings.fields_padding > 0:
|
776
|
-
padded_polygon = polygon.buffer(
|
769
|
+
padded_polygon = polygon.buffer(
|
770
|
+
-self.meters_to_degrees(self.map.texture_settings.fields_padding)
|
771
|
+
)
|
777
772
|
|
778
773
|
if not isinstance(padded_polygon, shapely.geometry.polygon.Polygon):
|
779
774
|
self.logger.warning("The padding value is too high, field will not padded.")
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: maps4fs
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.7.1
|
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
|
@@ -69,16 +69,15 @@ Requires-Dist: pydantic
|
|
69
69
|
</div>
|
70
70
|
|
71
71
|
🗺️ Supports 2x2, 4x4, 8x8, 16x16 and any custom size maps<br>
|
72
|
-
🔄 Support map rotation
|
72
|
+
🔄 Support map rotation<br>
|
73
73
|
🌐 Supports custom [DTM Providers](#DTM-Providers) 🆕<br>
|
74
|
-
🌾 Automatically generates fields
|
75
|
-
🌽 Automatically generates farmlands
|
76
|
-
🌿 Automatically generates decorative foliage
|
77
|
-
🌲 Automatically generates forests
|
78
|
-
🌊 Automatically generates water planes
|
74
|
+
🌾 Automatically generates fields<br>
|
75
|
+
🌽 Automatically generates farmlands<br>
|
76
|
+
🌿 Automatically generates decorative foliage<br>
|
77
|
+
🌲 Automatically generates forests<br>
|
78
|
+
🌊 Automatically generates water planes<br>
|
79
79
|
📈 Automatically generates splines 🆕<br>
|
80
80
|
🛰️ Automatically downloads high resolution satellite images 🆕<br>
|
81
|
-
🏔️ Allows to use multiple DTM providers for elevation models 🆕<br>
|
82
81
|
🌍 Based on real-world data from OpenStreetMap<br>
|
83
82
|
🗺️ Supports [custom OSM maps](/docs/custom_osm.md)<br>
|
84
83
|
🏞️ Generates height map using SRTM dataset<br>
|
@@ -99,10 +98,14 @@ Requires-Dist: pydantic
|
|
99
98
|
🌿 Automatically generates decorative foliage.<br><br>
|
100
99
|
<img src="https://github.com/user-attachments/assets/27a5e541-a9f5-4504-b8d2-64aae9fb3e52"><br>
|
101
100
|
🌲 Automatically generates forests.<br><br>
|
101
|
+
<img src="https://github.com/user-attachments/assets/891911d7-081d-431e-a677-b4ae96870286"><br>
|
102
|
+
🌲 Allows to select trees for generation.<br><br>
|
102
103
|
<img src="https://github.com/user-attachments/assets/cce7d4e0-cba2-4dd2-b22d-03137fb2e860"><br>
|
103
104
|
🌊 Automatically generates water planes.<br><br>
|
104
105
|
<img src="https://github.com/user-attachments/assets/0b05b511-a595-48e7-a353-8298081314a4"><br>
|
105
106
|
📈 Automatically generates splines.<br><br>
|
107
|
+
<img src="https://github.com/user-attachments/assets/0957db9e-7b95-4951-969c-9d1edd9f073b"><br>
|
108
|
+
🖌️ Allows customization of the texture schema.<br><br>
|
106
109
|
<img src="https://github.com/user-attachments/assets/80e5923c-22c7-4dc0-8906-680902511f3a"><br>
|
107
110
|
🗒️ True-to-life blueprints for fast and precise modding.<br><br>
|
108
111
|
<img width="480" src="https://github.com/user-attachments/assets/1a8802d2-6a3b-4bfa-af2b-7c09478e199b"><br>
|
@@ -259,6 +262,8 @@ Tools are divided into categories, which are listed below.
|
|
259
262
|
#### For custom schemas
|
260
263
|
- **Tree Schema Editor** - allows you to view all the supported trees models and select the ones you need on your map. After it, you should click the Show updated schema button and copy the JSON schema to the clipboard. Then you can use it in the Expert settings to generate the map with the selected trees.
|
261
264
|
|
265
|
+
- **Texture Schema Editor** - allows you to view all the supported textures and edit their parameters, such as priority, OSM tags and so on. After editing, you should click the Show updated schema button and copy the JSON schema to the clipboard. Then you can use it in the Expert settings to generate the map with the updated textures.
|
266
|
+
|
262
267
|
#### For Textures and DEM
|
263
268
|
- **GeoTIFF windowing** - allows you to upload your GeoTIFF file and select the region of interest to extract it from the image. It's useful when you have high-resolution DEM data and want to create a height map using it.
|
264
269
|
|
@@ -2,7 +2,7 @@ maps4fs/__init__.py,sha256=LrWSsyWaU28Dzcs7sRycywO_LvM-j34UvtafyBhvdx4,490
|
|
2
2
|
maps4fs/logger.py,sha256=B-NEYpMjPAAqlV4VpfTi6nbBFnEABVtQOaYe6nMpidg,1489
|
3
3
|
maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
|
4
4
|
maps4fs/generator/background.py,sha256=tV4UXvtkNN-OSvv6ujp4jFWRU1xGBgEvSakVGZ1H4nc,24877
|
5
|
-
maps4fs/generator/component.py,sha256=
|
5
|
+
maps4fs/generator/component.py,sha256=pbpGaWy5C0UzxpcJ72HPY2gMol98snDr-bvNZSX4yY0,20823
|
6
6
|
maps4fs/generator/config.py,sha256=0QmK052B8bxyHVhg3jzCORLfOBMMmqVfhhbqXKf6OMk,4383
|
7
7
|
maps4fs/generator/dem.py,sha256=20gx0dzX0LyO6ipvDitst-BwGfcKogFqgQf9Q2qMH5U,10933
|
8
8
|
maps4fs/generator/game.py,sha256=Nf5r2ubV4YVAVHGzJyhbF2GnOC0qV3HlHYIZBCWciHs,7992
|
@@ -11,8 +11,8 @@ maps4fs/generator/i3d.py,sha256=pUyHKWKcw43xVCf3Y8iabtbQba05LYxMHi8vziGksIA,2484
|
|
11
11
|
maps4fs/generator/map.py,sha256=a50KQEr1XZKjS_WKXywGwh4OC3gyjY6M8FTc0eNcxpg,10183
|
12
12
|
maps4fs/generator/qgis.py,sha256=Es8hLuqN_KH8lDfnJE6He2rWYbAKJ3RGPn-o87S6CPI,6116
|
13
13
|
maps4fs/generator/satellite.py,sha256=_7RcuNmR1mjxEJWMDsjnzKUIqWxnGUn50XtjB7HmSPg,3661
|
14
|
-
maps4fs/generator/settings.py,sha256=
|
15
|
-
maps4fs/generator/texture.py,sha256=
|
14
|
+
maps4fs/generator/settings.py,sha256=9vbXISQrE-aDY7ATpvZ7LVJMqjfwa3-gNl-huI8XLO0,5666
|
15
|
+
maps4fs/generator/texture.py,sha256=tDC9lIx2qn8d09Gu6PW_Lbq7EK7s1N4l25p50v92xl8,33548
|
16
16
|
maps4fs/generator/dtm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
maps4fs/generator/dtm/dtm.py,sha256=nCQKQygARLxaz4HkREQQd0Yb03oKOf1Iav5_VoZsFWI,9819
|
18
18
|
maps4fs/generator/dtm/srtm.py,sha256=2-pX6bWrJX6gr8IM7ueX6mm_PW7_UQ58MtdzDHae2OQ,9030
|
@@ -20,8 +20,8 @@ maps4fs/generator/dtm/usgs.py,sha256=hwVjoSNTNRU6hwnfwJ2d3rOdtOjadCmx2QESA2REn6s
|
|
20
20
|
maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
|
21
21
|
maps4fs/toolbox/background.py,sha256=9BXWNqs_n3HgqDiPztWylgYk_QM4YgBpe6_ZNQAWtSc,2154
|
22
22
|
maps4fs/toolbox/dem.py,sha256=z9IPFNmYbjiigb3t02ZenI3Mo8odd19c5MZbjDEovTo,3525
|
23
|
-
maps4fs-1.
|
24
|
-
maps4fs-1.
|
25
|
-
maps4fs-1.
|
26
|
-
maps4fs-1.
|
27
|
-
maps4fs-1.
|
23
|
+
maps4fs-1.7.1.dist-info/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
|
24
|
+
maps4fs-1.7.1.dist-info/METADATA,sha256=QMIGgmKUnYvtc-Ln_rxPm7WeF8Q9L82Eo_aY2g2Uc8c,39697
|
25
|
+
maps4fs-1.7.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
26
|
+
maps4fs-1.7.1.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
|
27
|
+
maps4fs-1.7.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|