maps4fs 1.8.0__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/__init__.py +22 -0
- maps4fs/generator/__init__.py +1 -0
- maps4fs/generator/background.py +625 -0
- maps4fs/generator/component.py +553 -0
- maps4fs/generator/config.py +109 -0
- maps4fs/generator/dem.py +297 -0
- maps4fs/generator/dtm/__init__.py +0 -0
- maps4fs/generator/dtm/base/wcs.py +71 -0
- maps4fs/generator/dtm/base/wms.py +70 -0
- maps4fs/generator/dtm/bavaria.py +113 -0
- maps4fs/generator/dtm/dtm.py +637 -0
- maps4fs/generator/dtm/england.py +31 -0
- maps4fs/generator/dtm/hessen.py +31 -0
- maps4fs/generator/dtm/niedersachsen.py +39 -0
- maps4fs/generator/dtm/nrw.py +30 -0
- maps4fs/generator/dtm/srtm.py +127 -0
- maps4fs/generator/dtm/usgs.py +87 -0
- maps4fs/generator/dtm/utils.py +61 -0
- maps4fs/generator/game.py +247 -0
- maps4fs/generator/grle.py +470 -0
- maps4fs/generator/i3d.py +624 -0
- maps4fs/generator/map.py +275 -0
- maps4fs/generator/qgis.py +196 -0
- maps4fs/generator/satellite.py +92 -0
- maps4fs/generator/settings.py +187 -0
- maps4fs/generator/texture.py +893 -0
- maps4fs/logger.py +46 -0
- maps4fs/toolbox/__init__.py +1 -0
- maps4fs/toolbox/background.py +63 -0
- maps4fs/toolbox/custom_osm.py +67 -0
- maps4fs/toolbox/dem.py +112 -0
- maps4fs-1.8.0.dist-info/LICENSE.md +190 -0
- maps4fs-1.8.0.dist-info/METADATA +693 -0
- maps4fs-1.8.0.dist-info/RECORD +36 -0
- maps4fs-1.8.0.dist-info/WHEEL +5 -0
- maps4fs-1.8.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
"""This module contains provider of Niedersachsen data."""
|
2
|
+
|
3
|
+
from maps4fs.generator.dtm.base.wms import WMSProvider
|
4
|
+
from maps4fs.generator.dtm.dtm import DTMProvider
|
5
|
+
|
6
|
+
|
7
|
+
# pylint: disable=R0801
|
8
|
+
class NiedersachsenProvider(WMSProvider, DTMProvider):
|
9
|
+
"""Provider of Niedersachsen data."""
|
10
|
+
|
11
|
+
_code = "niedersachsen"
|
12
|
+
_name = "Lower Saxony DGM1"
|
13
|
+
_region = "DE"
|
14
|
+
_icon = "🇩🇪"
|
15
|
+
_resolution = 1
|
16
|
+
_author = "[kbrandwijk](https://github.com/kbrandwijk)"
|
17
|
+
_is_community = True
|
18
|
+
_instructions = (
|
19
|
+
"Warning: The Niedersachsen DGM1 data is provided as 8-bit Cloud Optimized GeoTIFF "
|
20
|
+
"(whole meters only). You will need to use blur ('Blur Radius' under 'DEM Settings') "
|
21
|
+
"to smooth the data."
|
22
|
+
)
|
23
|
+
_is_base = False
|
24
|
+
_extents = (54.148101, 51.153098, 11.754046, 6.505772)
|
25
|
+
|
26
|
+
_url = "https://opendata.lgln.niedersachsen.de/doorman/noauth/dgm_wms"
|
27
|
+
_source_crs = "EPSG:25832"
|
28
|
+
_tile_size = 2000
|
29
|
+
_wms_version = "1.3.0"
|
30
|
+
|
31
|
+
def get_wms_parameters(self, tile):
|
32
|
+
return {
|
33
|
+
"layers": ["ni_dgm1_grau"],
|
34
|
+
"srs": "EPSG:25832",
|
35
|
+
"bbox": (tile[1], tile[0], tile[3], tile[2]),
|
36
|
+
"size": (2000, 2000),
|
37
|
+
"format": "image/tiff",
|
38
|
+
"transparent": False,
|
39
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"""This module contains provider of NRW data."""
|
2
|
+
|
3
|
+
from maps4fs.generator.dtm.base.wcs import WCSProvider
|
4
|
+
from maps4fs.generator.dtm.dtm import DTMProvider
|
5
|
+
|
6
|
+
|
7
|
+
class NRWProvider(WCSProvider, DTMProvider):
|
8
|
+
"""Provider of NRW data."""
|
9
|
+
|
10
|
+
_code = "NRW"
|
11
|
+
_name = "North Rhine-Westphalia DGM1"
|
12
|
+
_region = "DE"
|
13
|
+
_icon = "🇩🇪"
|
14
|
+
_resolution = 1
|
15
|
+
_author = "[kbrandwijk](https://github.com/kbrandwijk)"
|
16
|
+
_is_community = True
|
17
|
+
_is_base = False
|
18
|
+
_extents = (52.6008271, 50.1506045, 9.5315425, 5.8923538)
|
19
|
+
|
20
|
+
_url = "https://www.wcs.nrw.de/geobasis/wcs_nw_dgm"
|
21
|
+
_wcs_version = "2.0.1"
|
22
|
+
_source_crs = "EPSG:25832"
|
23
|
+
_tile_size = 1000
|
24
|
+
|
25
|
+
def get_wcs_parameters(self, tile: tuple[float, float, float, float]) -> dict:
|
26
|
+
return {
|
27
|
+
"identifier": ["nw_dgm"],
|
28
|
+
"subsets": [("y", str(tile[0]), str(tile[2])), ("x", str(tile[1]), str(tile[3]))],
|
29
|
+
"format": "image/tiff",
|
30
|
+
}
|
@@ -0,0 +1,127 @@
|
|
1
|
+
"""This module contains provider of Shuttle Radar Topography Mission (SRTM) 30m data."""
|
2
|
+
|
3
|
+
# Author: https://github.com/iwatkot
|
4
|
+
|
5
|
+
import gzip
|
6
|
+
import math
|
7
|
+
import os
|
8
|
+
import shutil
|
9
|
+
|
10
|
+
import requests
|
11
|
+
|
12
|
+
from maps4fs.generator.dtm.dtm import DTMProvider, DTMProviderSettings
|
13
|
+
|
14
|
+
|
15
|
+
class SRTM30ProviderSettings(DTMProviderSettings):
|
16
|
+
"""Settings for SRTM 30m provider."""
|
17
|
+
|
18
|
+
|
19
|
+
class SRTM30Provider(DTMProvider):
|
20
|
+
"""Provider of Shuttle Radar Topography Mission (SRTM) 30m data."""
|
21
|
+
|
22
|
+
_code = "srtm30"
|
23
|
+
_name = "SRTM 30 m"
|
24
|
+
_region = "Global"
|
25
|
+
_icon = "🌎"
|
26
|
+
_resolution = 30.0
|
27
|
+
|
28
|
+
_url = "https://elevation-tiles-prod.s3.amazonaws.com/skadi/{latitude_band}/{tile_name}.hgt.gz"
|
29
|
+
|
30
|
+
_author = "[iwatkot](https://github.com/iwatkot)"
|
31
|
+
|
32
|
+
_extents = (60, -65, 180, -180)
|
33
|
+
|
34
|
+
_settings = SRTM30ProviderSettings
|
35
|
+
|
36
|
+
def __init__(self, *args, **kwargs):
|
37
|
+
super().__init__(*args, **kwargs)
|
38
|
+
self.hgt_directory = os.path.join(self._tile_directory, "hgt")
|
39
|
+
self.gz_directory = os.path.join(self._tile_directory, "gz")
|
40
|
+
os.makedirs(self.hgt_directory, exist_ok=True)
|
41
|
+
os.makedirs(self.gz_directory, exist_ok=True)
|
42
|
+
self.data_info: dict[str, int | str | float] | None = None # type: ignore
|
43
|
+
|
44
|
+
def download_tiles(self):
|
45
|
+
"""Download SRTM tiles."""
|
46
|
+
north, south, east, west = self.get_bbox()
|
47
|
+
|
48
|
+
tiles = []
|
49
|
+
# Look at each corner of the bbox in case the bbox spans across multiple tiles
|
50
|
+
for pair in [(north, east), (south, west), (south, east), (north, west)]:
|
51
|
+
tile_parameters = self.get_tile_parameters(*pair)
|
52
|
+
tile_name = tile_parameters["tile_name"]
|
53
|
+
decompressed_tile_path = os.path.join(self.hgt_directory, f"{tile_name}.hgt")
|
54
|
+
|
55
|
+
if not os.path.isfile(decompressed_tile_path):
|
56
|
+
compressed_tile_path = os.path.join(self.gz_directory, f"{tile_name}.hgt.gz")
|
57
|
+
if not self.get_or_download_tile(compressed_tile_path, **tile_parameters):
|
58
|
+
raise FileNotFoundError(f"Tile {tile_name} not found.")
|
59
|
+
|
60
|
+
with gzip.open(compressed_tile_path, "rb") as f_in:
|
61
|
+
with open(decompressed_tile_path, "wb") as f_out:
|
62
|
+
shutil.copyfileobj(f_in, f_out)
|
63
|
+
tiles.append(decompressed_tile_path)
|
64
|
+
|
65
|
+
return list(set(tiles))
|
66
|
+
|
67
|
+
# region provider specific helpers
|
68
|
+
def download_tile(self, output_path: str, **kwargs) -> bool:
|
69
|
+
"""Download a tile from the provider.
|
70
|
+
|
71
|
+
Arguments:
|
72
|
+
output_path (str): Path to save the downloaded tile.
|
73
|
+
|
74
|
+
Returns:
|
75
|
+
bool: True if the tile was downloaded successfully, False otherwise.
|
76
|
+
"""
|
77
|
+
url = self.formatted_url(**kwargs)
|
78
|
+
response = requests.get(url, stream=True, timeout=10)
|
79
|
+
if response.status_code == 200:
|
80
|
+
with open(output_path, "wb") as file:
|
81
|
+
for chunk in response.iter_content(chunk_size=1024):
|
82
|
+
file.write(chunk)
|
83
|
+
return True
|
84
|
+
return False
|
85
|
+
|
86
|
+
def get_or_download_tile(self, output_path: str, **kwargs) -> str | None:
|
87
|
+
"""Get or download a tile from the provider.
|
88
|
+
|
89
|
+
Arguments:
|
90
|
+
output_path (str): Path to save the downloaded tile.
|
91
|
+
|
92
|
+
Returns:
|
93
|
+
str: Path to the downloaded tile or None if the tile not exists and was
|
94
|
+
not downloaded.
|
95
|
+
"""
|
96
|
+
if not os.path.exists(output_path):
|
97
|
+
if not self.download_tile(output_path, **kwargs):
|
98
|
+
return None
|
99
|
+
return output_path
|
100
|
+
|
101
|
+
def get_tile_parameters(self, *args) -> dict[str, str]:
|
102
|
+
"""Returns latitude band and tile name for SRTM tile from coordinates.
|
103
|
+
|
104
|
+
Arguments:
|
105
|
+
lat (float): Latitude.
|
106
|
+
lon (float): Longitude.
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
dict: Tile parameters.
|
110
|
+
"""
|
111
|
+
lat, lon = args
|
112
|
+
|
113
|
+
tile_latitude = math.floor(lat)
|
114
|
+
tile_longitude = math.floor(lon)
|
115
|
+
|
116
|
+
latitude_band = f"N{abs(tile_latitude):02d}" if lat >= 0 else f"S{abs(tile_latitude):02d}"
|
117
|
+
if lon < 0:
|
118
|
+
tile_name = f"{latitude_band}W{abs(tile_longitude):03d}"
|
119
|
+
else:
|
120
|
+
tile_name = f"{latitude_band}E{abs(tile_longitude):03d}"
|
121
|
+
|
122
|
+
self.logger.debug(
|
123
|
+
"Detected tile name: %s for coordinates: lat %s, lon %s.", tile_name, lat, lon
|
124
|
+
)
|
125
|
+
return {"latitude_band": latitude_band, "tile_name": tile_name}
|
126
|
+
|
127
|
+
# endregion
|
@@ -0,0 +1,87 @@
|
|
1
|
+
"""This module contains provider of USGS data."""
|
2
|
+
|
3
|
+
import os
|
4
|
+
from datetime import datetime
|
5
|
+
|
6
|
+
import numpy as np
|
7
|
+
import requests
|
8
|
+
|
9
|
+
from maps4fs.generator.dtm.dtm import DTMProvider, DTMProviderSettings
|
10
|
+
|
11
|
+
|
12
|
+
class USGSProviderSettings(DTMProviderSettings):
|
13
|
+
"""Settings for the USGS provider."""
|
14
|
+
|
15
|
+
dataset: tuple | str = (
|
16
|
+
"Digital Elevation Model (DEM) 1 meter",
|
17
|
+
"Alaska IFSAR 5 meter DEM",
|
18
|
+
"National Elevation Dataset (NED) 1/9 arc-second",
|
19
|
+
"National Elevation Dataset (NED) 1/3 arc-second",
|
20
|
+
"National Elevation Dataset (NED) 1 arc-second",
|
21
|
+
"National Elevation Dataset (NED) Alaska 2 arc-second",
|
22
|
+
"Original Product Resolution (OPR) Digital Elevation Model (DEM)",
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
class USGSProvider(DTMProvider):
|
27
|
+
"""Provider of USGS."""
|
28
|
+
|
29
|
+
_code = "USGS"
|
30
|
+
_name = "USGS"
|
31
|
+
_region = "USA"
|
32
|
+
_icon = "🇺🇸"
|
33
|
+
_resolution = "variable"
|
34
|
+
_data: np.ndarray | None = None
|
35
|
+
_settings = USGSProviderSettings
|
36
|
+
_author = "[ZenJakey](https://github.com/ZenJakey)"
|
37
|
+
_contributors = "[kbrandwijk](https://github.com/kbrandwijk)"
|
38
|
+
_is_community = True
|
39
|
+
_instructions = None
|
40
|
+
_extents = (50.0, 17.0, -64.0, -162.0)
|
41
|
+
|
42
|
+
_url = "https://tnmaccess.nationalmap.gov/api/v1/products?prodFormats=GeoTIFF,IMG"
|
43
|
+
|
44
|
+
def download_tiles(self):
|
45
|
+
download_urls = self.get_download_urls()
|
46
|
+
all_tif_files = self.download_tif_files(download_urls, self.shared_tiff_path)
|
47
|
+
return all_tif_files
|
48
|
+
|
49
|
+
def __init__(self, *args, **kwargs):
|
50
|
+
super().__init__(*args, **kwargs)
|
51
|
+
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
52
|
+
self.shared_tiff_path = os.path.join(self._tile_directory, "shared")
|
53
|
+
os.makedirs(self.shared_tiff_path, exist_ok=True)
|
54
|
+
self.output_path = os.path.join(self._tile_directory, f"timestamp_{timestamp}")
|
55
|
+
os.makedirs(self.output_path, exist_ok=True)
|
56
|
+
|
57
|
+
def get_download_urls(self) -> list[str]:
|
58
|
+
"""Get download URLs of the GeoTIFF files from the USGS API.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
list: List of download URLs.
|
62
|
+
"""
|
63
|
+
urls = []
|
64
|
+
try:
|
65
|
+
# Make the GET request
|
66
|
+
(north, south, east, west) = self.get_bbox()
|
67
|
+
response = requests.get( # pylint: disable=W3101
|
68
|
+
self.url # type: ignore
|
69
|
+
+ f"&datasets={self.user_settings.dataset}" # type: ignore
|
70
|
+
+ f"&bbox={west},{north},{east},{south}"
|
71
|
+
)
|
72
|
+
self.logger.debug("Getting file locations from USGS...")
|
73
|
+
|
74
|
+
# Check if the request was successful (HTTP status code 200)
|
75
|
+
if response.status_code == 200:
|
76
|
+
# Parse the JSON response
|
77
|
+
json_data = response.json()
|
78
|
+
items = json_data["items"]
|
79
|
+
for item in items:
|
80
|
+
urls.append(item["downloadURL"])
|
81
|
+
# self.download_tif_files(urls)
|
82
|
+
else:
|
83
|
+
self.logger.error("Failed to get data. HTTP Status Code: %s", response.status_code)
|
84
|
+
except requests.exceptions.RequestException as e:
|
85
|
+
self.logger.error("Failed to get data. Error: %s", e)
|
86
|
+
self.logger.debug("Received %s urls", len(urls))
|
87
|
+
return urls
|
@@ -0,0 +1,61 @@
|
|
1
|
+
"""Utility functions for the DTM generator."""
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
from pyproj import Transformer
|
5
|
+
|
6
|
+
|
7
|
+
def tile_bbox(
|
8
|
+
bbox: tuple[float, float, float, float], tile_size: float
|
9
|
+
) -> list[tuple[float, float, float, float]]:
|
10
|
+
"""Tile the bounding box into smaller bounding boxes of a specified size.
|
11
|
+
|
12
|
+
Arguments:
|
13
|
+
bbox (tuple): Bounding box to tile (north, south, east, west).
|
14
|
+
tile_size (int): Size of the tiles in meters.
|
15
|
+
|
16
|
+
Returns:
|
17
|
+
list: List of smaller bounding boxes (north, south, east, west).
|
18
|
+
"""
|
19
|
+
north, south, east, west = bbox
|
20
|
+
x_coords = np.arange(west, east, tile_size if east > west else -tile_size)
|
21
|
+
y_coords = np.arange(north, south, tile_size if south > north else -tile_size)
|
22
|
+
x_coords = np.append(x_coords, east).astype(x_coords.dtype)
|
23
|
+
y_coords = np.append(y_coords, south).astype(y_coords.dtype)
|
24
|
+
|
25
|
+
x_min, y_min = np.meshgrid(x_coords[:-1], y_coords[:-1], indexing="ij")
|
26
|
+
x_max, y_max = np.meshgrid(x_coords[1:], y_coords[1:], indexing="ij")
|
27
|
+
|
28
|
+
tiles = np.stack(
|
29
|
+
[x_min.ravel(), y_min.ravel(), x_max.ravel(), y_max.ravel()], axis=1, dtype=float
|
30
|
+
)
|
31
|
+
|
32
|
+
return [tuple(tile[i].item() for i in range(4)) for tile in tiles]
|
33
|
+
|
34
|
+
|
35
|
+
def transform_bbox(
|
36
|
+
bbox: tuple[float, float, float, float], to_crs: str
|
37
|
+
) -> tuple[float, float, float, float]:
|
38
|
+
"""Transform the bounding box to a different coordinate reference system (CRS).
|
39
|
+
|
40
|
+
Arguments:
|
41
|
+
bbox (tuple): Bounding box to transform (north, south, east, west).
|
42
|
+
to_crs (str): Target CRS (e.g., EPSG:4326 for CRS:84).
|
43
|
+
|
44
|
+
Returns:
|
45
|
+
tuple: Transformed bounding box (north, south, east, west).
|
46
|
+
"""
|
47
|
+
transformer = Transformer.from_crs("epsg:4326", to_crs)
|
48
|
+
north, south, east, west = bbox
|
49
|
+
|
50
|
+
# EPSG:4326 is lat, lon, so xx is lat and yy is lon
|
51
|
+
bottom_left_x, bottom_left_y = transformer.transform(xx=south, yy=west)
|
52
|
+
top_left_x, top_left_y = transformer.transform(xx=north, yy=west)
|
53
|
+
top_right_x, top_right_y = transformer.transform(xx=north, yy=east)
|
54
|
+
bottom_right_x, bottom_right_y = transformer.transform(xx=south, yy=east)
|
55
|
+
|
56
|
+
west = min(bottom_left_y, bottom_right_y)
|
57
|
+
east = max(top_left_y, top_right_y)
|
58
|
+
north = min(bottom_left_x, top_left_x)
|
59
|
+
south = max(bottom_right_x, top_right_x)
|
60
|
+
|
61
|
+
return north, south, east, west
|
@@ -0,0 +1,247 @@
|
|
1
|
+
"""This module contains the Game class and its subclasses. Game class is used to define
|
2
|
+
different versions of the game for which the map is generated. Each game has its own map
|
3
|
+
template file and specific settings for map generation."""
|
4
|
+
|
5
|
+
from __future__ import annotations
|
6
|
+
|
7
|
+
import os
|
8
|
+
|
9
|
+
from maps4fs.generator.background import Background
|
10
|
+
from maps4fs.generator.config import Config
|
11
|
+
from maps4fs.generator.grle import GRLE
|
12
|
+
from maps4fs.generator.i3d import I3d
|
13
|
+
from maps4fs.generator.satellite import Satellite
|
14
|
+
from maps4fs.generator.texture import Texture
|
15
|
+
|
16
|
+
working_directory = os.getcwd()
|
17
|
+
|
18
|
+
|
19
|
+
class Game:
|
20
|
+
"""Class used to define different versions of the game for which the map is generated.
|
21
|
+
|
22
|
+
Arguments:
|
23
|
+
map_template_path (str, optional): Path to the map template file. Defaults to None.
|
24
|
+
|
25
|
+
Attributes and Properties:
|
26
|
+
code (str): The code of the game.
|
27
|
+
components (list[Type[Component]]): List of components used for map generation.
|
28
|
+
map_template_path (str): Path to the map template file.
|
29
|
+
|
30
|
+
Public Methods:
|
31
|
+
from_code(cls, code: str) -> Game: Returns the game instance based on the game code.
|
32
|
+
"""
|
33
|
+
|
34
|
+
code: str | None = None
|
35
|
+
dem_multipliyer: int = 2
|
36
|
+
_additional_dem_name: str | None = None
|
37
|
+
_map_template_path: str | None = None
|
38
|
+
_texture_schema: str | None = None
|
39
|
+
_grle_schema: str | None = None
|
40
|
+
_tree_schema: str | None = None
|
41
|
+
|
42
|
+
# Order matters! Some components depend on others.
|
43
|
+
components = [Texture, Background, GRLE, I3d, Config, Satellite]
|
44
|
+
|
45
|
+
def __init__(self, map_template_path: str | None = None):
|
46
|
+
if map_template_path:
|
47
|
+
self._map_template_path = map_template_path
|
48
|
+
|
49
|
+
def map_xml_path(self, map_directory: str) -> str:
|
50
|
+
"""Returns the path to the map.xml file.
|
51
|
+
|
52
|
+
Arguments:
|
53
|
+
map_directory (str): The path to the map directory.
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
str: The path to the map.xml file.
|
57
|
+
"""
|
58
|
+
return os.path.join(map_directory, "maps", "map", "map.xml")
|
59
|
+
|
60
|
+
@classmethod
|
61
|
+
def from_code(cls, code: str, map_template_path: str | None = None) -> Game:
|
62
|
+
"""Returns the game instance based on the game code.
|
63
|
+
|
64
|
+
Arguments:
|
65
|
+
code (str): The code of the game.
|
66
|
+
map_template_path (str, optional): Path to the map template file. Defaults to None.
|
67
|
+
|
68
|
+
Returns:
|
69
|
+
Game: The game instance.
|
70
|
+
"""
|
71
|
+
for game in cls.__subclasses__():
|
72
|
+
if game.code and game.code.lower() == code.lower():
|
73
|
+
return game(map_template_path)
|
74
|
+
raise ValueError(f"Game with code {code} not found.")
|
75
|
+
|
76
|
+
@property
|
77
|
+
def template_path(self) -> str:
|
78
|
+
"""Returns the path to the map template file.
|
79
|
+
|
80
|
+
Raises:
|
81
|
+
ValueError: If the map template path is not set.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
str: The path to the map template file."""
|
85
|
+
if not self._map_template_path:
|
86
|
+
raise ValueError("Map template path not set.")
|
87
|
+
return self._map_template_path
|
88
|
+
|
89
|
+
@property
|
90
|
+
def texture_schema(self) -> str:
|
91
|
+
"""Returns the path to the texture layers schema file.
|
92
|
+
|
93
|
+
Raises:
|
94
|
+
ValueError: If the texture layers schema path is not set.
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
str: The path to the texture layers schema file."""
|
98
|
+
if not self._texture_schema:
|
99
|
+
raise ValueError("Texture layers schema path not set.")
|
100
|
+
return self._texture_schema
|
101
|
+
|
102
|
+
@property
|
103
|
+
def grle_schema(self) -> str:
|
104
|
+
"""Returns the path to the GRLE layers schema file.
|
105
|
+
|
106
|
+
Raises:
|
107
|
+
ValueError: If the GRLE layers schema path is not set.
|
108
|
+
|
109
|
+
Returns:
|
110
|
+
str: The path to the GRLE layers schema file."""
|
111
|
+
if not self._grle_schema:
|
112
|
+
raise ValueError("GRLE layers schema path not set.")
|
113
|
+
return self._grle_schema
|
114
|
+
|
115
|
+
@property
|
116
|
+
def tree_schema(self) -> str:
|
117
|
+
"""Returns the path to the tree layers schema file.
|
118
|
+
|
119
|
+
Raises:
|
120
|
+
ValueError: If the tree layers schema path is not set.
|
121
|
+
|
122
|
+
Returns:
|
123
|
+
str: The path to the tree layers schema file."""
|
124
|
+
if not self._tree_schema:
|
125
|
+
raise ValueError("Tree layers schema path not set.")
|
126
|
+
return self._tree_schema
|
127
|
+
|
128
|
+
def dem_file_path(self, map_directory: str) -> str:
|
129
|
+
"""Returns the path to the DEM file.
|
130
|
+
|
131
|
+
Arguments:
|
132
|
+
map_directory (str): The path to the map directory.
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
str: The path to the DEM file.
|
136
|
+
"""
|
137
|
+
raise NotImplementedError
|
138
|
+
|
139
|
+
def weights_dir_path(self, map_directory: str) -> str:
|
140
|
+
"""Returns the path to the weights directory.
|
141
|
+
|
142
|
+
Arguments:
|
143
|
+
map_directory (str): The path to the map directory.
|
144
|
+
|
145
|
+
Returns:
|
146
|
+
str: The path to the weights directory."""
|
147
|
+
raise NotImplementedError
|
148
|
+
|
149
|
+
def i3d_file_path(self, map_directory: str) -> str:
|
150
|
+
"""Returns the path to the i3d file.
|
151
|
+
|
152
|
+
Arguments:
|
153
|
+
map_directory (str): The path to the map directory.
|
154
|
+
|
155
|
+
Returns:
|
156
|
+
str: The path to the i3d file."""
|
157
|
+
raise NotImplementedError
|
158
|
+
|
159
|
+
@property
|
160
|
+
def additional_dem_name(self) -> str | None:
|
161
|
+
"""Returns the name of the additional DEM file.
|
162
|
+
|
163
|
+
Returns:
|
164
|
+
str | None: The name of the additional DEM file."""
|
165
|
+
return self._additional_dem_name
|
166
|
+
|
167
|
+
|
168
|
+
# pylint: disable=W0223
|
169
|
+
class FS22(Game):
|
170
|
+
"""Class used to define the game version FS22."""
|
171
|
+
|
172
|
+
code = "FS22"
|
173
|
+
_map_template_path = os.path.join(working_directory, "data", "fs22-map-template.zip")
|
174
|
+
_texture_schema = os.path.join(working_directory, "data", "fs22-texture-schema.json")
|
175
|
+
|
176
|
+
def dem_file_path(self, map_directory: str) -> str:
|
177
|
+
"""Returns the path to the DEM file.
|
178
|
+
|
179
|
+
Arguments:
|
180
|
+
map_directory (str): The path to the map directory.
|
181
|
+
|
182
|
+
Returns:
|
183
|
+
str: The path to the DEM file."""
|
184
|
+
return os.path.join(map_directory, "maps", "map", "data", "map_dem.png")
|
185
|
+
|
186
|
+
def weights_dir_path(self, map_directory: str) -> str:
|
187
|
+
"""Returns the path to the weights directory.
|
188
|
+
|
189
|
+
Arguments:
|
190
|
+
map_directory (str): The path to the map directory.
|
191
|
+
|
192
|
+
Returns:
|
193
|
+
str: The path to the weights directory."""
|
194
|
+
return os.path.join(map_directory, "maps", "map", "data")
|
195
|
+
|
196
|
+
|
197
|
+
class FS25(Game):
|
198
|
+
"""Class used to define the game version FS25."""
|
199
|
+
|
200
|
+
code = "FS25"
|
201
|
+
dem_multipliyer: int = 2
|
202
|
+
_additional_dem_name = "unprocessedHeightMap.png"
|
203
|
+
_map_template_path = os.path.join(working_directory, "data", "fs25-map-template.zip")
|
204
|
+
_texture_schema = os.path.join(working_directory, "data", "fs25-texture-schema.json")
|
205
|
+
_grle_schema = os.path.join(working_directory, "data", "fs25-grle-schema.json")
|
206
|
+
_tree_schema = os.path.join(working_directory, "data", "fs25-tree-schema.json")
|
207
|
+
|
208
|
+
def dem_file_path(self, map_directory: str) -> str:
|
209
|
+
"""Returns the path to the DEM file.
|
210
|
+
|
211
|
+
Arguments:
|
212
|
+
map_directory (str): The path to the map directory.
|
213
|
+
|
214
|
+
Returns:
|
215
|
+
str: The path to the DEM file."""
|
216
|
+
return os.path.join(map_directory, "map", "data", "dem.png")
|
217
|
+
|
218
|
+
def map_xml_path(self, map_directory: str) -> str:
|
219
|
+
"""Returns the path to the map.xml file.
|
220
|
+
|
221
|
+
Arguments:
|
222
|
+
map_directory (str): The path to the map directory.
|
223
|
+
|
224
|
+
Returns:
|
225
|
+
str: The path to the map.xml file.
|
226
|
+
"""
|
227
|
+
return os.path.join(map_directory, "map", "map.xml")
|
228
|
+
|
229
|
+
def weights_dir_path(self, map_directory: str) -> str:
|
230
|
+
"""Returns the path to the weights directory.
|
231
|
+
|
232
|
+
Arguments:
|
233
|
+
map_directory (str): The path to the map directory.
|
234
|
+
|
235
|
+
Returns:
|
236
|
+
str: The path to the weights directory."""
|
237
|
+
return os.path.join(map_directory, "map", "data")
|
238
|
+
|
239
|
+
def i3d_file_path(self, map_directory: str) -> str:
|
240
|
+
"""Returns the path to the i3d file.
|
241
|
+
|
242
|
+
Arguments:
|
243
|
+
map_directory (str): The path to the map directory.
|
244
|
+
|
245
|
+
Returns:
|
246
|
+
str: The path to the i3d file."""
|
247
|
+
return os.path.join(map_directory, "map", "map.i3d")
|