maps4fs 1.8.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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")
|