maps4fs 1.8.17__py3-none-any.whl → 1.8.172__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.
@@ -414,10 +414,18 @@ class Background(MeshComponent, ImageComponent):
414
414
  water_resources_image = cv2.imread(self.water_resources_path, cv2.IMREAD_UNCHANGED)
415
415
  dem_image = cv2.imread(self.output_path, cv2.IMREAD_UNCHANGED)
416
416
 
417
+ # fall back to default value for height_scale 255, it is defined as float | None
418
+ # but it is always set at this point
419
+ z_scaling_factor: float = (
420
+ self.map.shared_settings.mesh_z_scaling_factor
421
+ if self.map.shared_settings.mesh_z_scaling_factor is not None
422
+ else 257
423
+ )
424
+
417
425
  dem_image = self.subtract_by_mask(
418
426
  dem_image,
419
427
  water_resources_image,
420
- self.map.dem_settings.water_depth,
428
+ int(self.map.dem_settings.water_depth * z_scaling_factor),
421
429
  )
422
430
 
423
431
  # Save the modified dem_image back to the output path
maps4fs/generator/dem.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """This module contains DEM class for processing Digital Elevation Model data."""
2
2
 
3
- import os
3
+ import math
4
4
  from typing import Any
5
5
 
6
6
  import cv2
@@ -31,10 +31,6 @@ class DEM(Component):
31
31
  def preprocess(self) -> None:
32
32
  self._dem_path = self.game.dem_file_path(self.map_directory)
33
33
  self.temp_dir = "temp"
34
- self.hgt_dir = os.path.join(self.temp_dir, "hgt")
35
- self.gz_dir = os.path.join(self.temp_dir, "gz")
36
- os.makedirs(self.hgt_dir, exist_ok=True)
37
- os.makedirs(self.gz_dir, exist_ok=True)
38
34
 
39
35
  self.logger.debug("Map size: %s x %s.", self.map_size, self.map_size)
40
36
  self.logger.debug(
@@ -116,24 +112,8 @@ class DEM(Component):
116
112
  )
117
113
  return dem_size, dem_size
118
114
 
119
- def to_ground(self, data: np.ndarray) -> np.ndarray:
120
- """Receives the signed 16-bit integer array and converts it to the ground level.
121
- If the min value is negative, it will become zero value and the rest of the values
122
- will be shifted accordingly.
123
- """
124
- # For examlem, min value was -50, it will become 0 and for all values we'll +50.
125
-
126
- if data.min() < 0:
127
- self.logger.debug("Array contains negative values, will be shifted to the ground.")
128
- data = data + abs(data.min())
129
-
130
- self.logger.debug(
131
- "Array was shifted to the ground. Min: %s, max: %s.", data.min(), data.max()
132
- )
133
- return data
134
-
135
115
  def process(self) -> None:
136
- """Reads SRTM file, crops it to map size, normalizes and blurs it,
116
+ """Reads DTM file, crops it to map size, normalizes and blurs it,
137
117
  saves to map directory."""
138
118
 
139
119
  dem_output_resolution = self.output_resolution
@@ -142,7 +122,7 @@ class DEM(Component):
142
122
  try:
143
123
  data = self.dtm_provider.get_numpy()
144
124
  except Exception as e: # pylint: disable=W0718
145
- self.logger.error("Failed to get DEM data from SRTM: %s.", e)
125
+ self.logger.error("Failed to get DEM data from DTM provider: %s.", e)
146
126
  self._save_empty_dem(dem_output_resolution)
147
127
  return
148
128
 
@@ -151,7 +131,7 @@ class DEM(Component):
151
131
  self._save_empty_dem(dem_output_resolution)
152
132
  return
153
133
 
154
- if data.dtype not in ["int16", "uint16"]:
134
+ if data.dtype not in ["int16", "uint16", "float", "float32"]:
155
135
  self.logger.error("DTM provider returned incorrect data type: %s.", data.dtype)
156
136
  self._save_empty_dem(dem_output_resolution)
157
137
  return
@@ -164,93 +144,158 @@ class DEM(Component):
164
144
  data.max(),
165
145
  )
166
146
 
167
- data = self.to_ground(data)
147
+ # 1. Resize DEM data to the output resolution.
148
+ resampled_data = self.resize_to_output(data)
168
149
 
169
- resampled_data = cv2.resize(
170
- data, dem_output_resolution, interpolation=cv2.INTER_LINEAR
171
- ).astype("uint16")
150
+ # 2. Apply multiplier (-10 to 120.4 becomes -20 to 240.8)
151
+ resampled_data = self.apply_multiplier(resampled_data)
172
152
 
173
- size_of_resampled_data = asizeof.asizeof(resampled_data) / 1024 / 1024
174
- self.logger.debug("Size of resampled data: %s MB.", size_of_resampled_data)
153
+ # 3. Raise terrain, and optionally lower to plateau level+water depth
154
+ # e.g. -20 to 240.8m becomes 20 to 280.8m
155
+ resampled_data = self.raise_or_lower(resampled_data)
156
+
157
+ # 4. Determine actual height scale value using ceiling
158
+ # e.g. 255 becomes 280.8+10 = 291
159
+ height_scale_value = self.determine_height_scale(resampled_data)
160
+
161
+ # 5. Normalize DEM data to 16-bit unsigned integer range (0 to 65535)
162
+ # e.g. multiply by 65535/291, clip and return as uint16
163
+ resampled_data = self.normalize_data(resampled_data, height_scale_value)
164
+
165
+ # 6. Blur DEM data.
166
+ resampled_data = self.apply_blur(resampled_data)
167
+
168
+ cv2.imwrite(self._dem_path, resampled_data)
169
+ self.logger.debug("DEM data was saved to %s.", self._dem_path)
170
+
171
+ if self.rotation:
172
+ self.rotate_dem()
175
173
 
174
+ def normalize_data(self, data: np.ndarray, height_scale_value: int) -> np.ndarray:
175
+ """Normalize DEM data to 16-bit unsigned integer range (0 to 65535).
176
+
177
+ Arguments:
178
+ data (np.ndarray): DEM data.
179
+ height_scale_value (int): Height scale value.
180
+
181
+ Returns:
182
+ np.ndarray: Normalized DEM data.
183
+ """
184
+ normalized_data = np.clip((data / height_scale_value) * 65535, 0, 65535).astype(np.uint16)
176
185
  self.logger.debug(
177
- "Maximum value in resampled data: %s, minimum value: %s. Data type: %s.",
178
- resampled_data.max(),
179
- resampled_data.min(),
180
- resampled_data.dtype,
186
+ "DEM data was normalized and clipped to 16-bit unsigned integer range. "
187
+ "Min: %s, max: %s.",
188
+ normalized_data.min(),
189
+ normalized_data.max(),
181
190
  )
191
+ return normalized_data
192
+
193
+ def determine_height_scale(self, data: np.ndarray) -> int:
194
+ """Determine height scale value using ceiling.
195
+
196
+ Arguments:
197
+ data (np.ndarray): DEM data.
198
+
199
+ Returns:
200
+ int: Height scale value.
201
+ """
202
+ height_scale = self.map.dem_settings.minimum_height_scale
203
+ adjusted_height_scale = math.ceil(
204
+ max(height_scale, data.max() + self.map.dem_settings.ceiling)
205
+ )
206
+
207
+ self.map.shared_settings.height_scale_value = adjusted_height_scale # type: ignore
208
+ self.map.shared_settings.mesh_z_scaling_factor = 65535 / adjusted_height_scale
209
+ self.map.shared_settings.height_scale_multiplier = adjusted_height_scale / 255
210
+ self.map.shared_settings.change_height_scale = True # type: ignore
211
+
212
+ self.logger.debug("Height scale value is %s.", adjusted_height_scale)
213
+ return adjusted_height_scale
214
+
215
+ def raise_or_lower(self, data: np.ndarray) -> np.ndarray:
216
+ """Raise or lower terrain to the level of plateau+water depth."""
217
+
218
+ if not self.map.dem_settings.adjust_terrain_to_ground_level:
219
+ return data
220
+
221
+ desired_ground_level = self.map.dem_settings.plateau + self.map.dem_settings.water_depth
222
+ current_ground_level = data.min()
182
223
 
183
- if self.multiplier != 1:
184
- resampled_data = resampled_data * self.multiplier
185
-
186
- self.logger.debug(
187
- "DEM data was multiplied by %s. Min: %s, max: %s. Data type: %s.",
188
- self.multiplier,
189
- resampled_data.min(),
190
- resampled_data.max(),
191
- resampled_data.dtype,
192
- )
193
-
194
- size_of_resampled_data = asizeof.asizeof(resampled_data) / 1024 / 1024
195
- self.logger.debug("Size of resampled data: %s MB.", size_of_resampled_data)
196
-
197
- # Clip values to 16-bit unsigned integer range.
198
- resampled_data = np.clip(resampled_data, 0, 65535)
199
- resampled_data = resampled_data.astype("uint16")
200
- self.logger.debug(
201
- "DEM data was multiplied by %s and clipped to 16-bit unsigned integer range. "
202
- "Min: %s, max: %s.",
203
- self.multiplier,
204
- resampled_data.min(),
205
- resampled_data.max(),
206
- )
224
+ data = data + (desired_ground_level - current_ground_level)
207
225
 
208
226
  self.logger.debug(
209
- "DEM data was resampled. Shape: %s, dtype: %s. Min: %s, max: %s.",
210
- resampled_data.shape,
211
- resampled_data.dtype,
212
- resampled_data.min(),
213
- resampled_data.max(),
227
+ "Array was shifted to the ground level %s. Min: %s, max: %s.",
228
+ desired_ground_level,
229
+ data.min(),
230
+ data.max(),
214
231
  )
232
+ return data
215
233
 
216
- if self.blur_radius > 0:
217
- resampled_data = cv2.GaussianBlur(
218
- resampled_data, (self.blur_radius, self.blur_radius), sigmaX=40, sigmaY=40
219
- )
220
- self.logger.debug(
221
- "Gaussion blur applied to DEM data with kernel size %s.",
222
- self.blur_radius,
223
- )
234
+ def apply_multiplier(self, data: np.ndarray) -> np.ndarray:
235
+ """Apply multiplier to DEM data.
236
+
237
+ Arguments:
238
+ data (np.ndarray): DEM data.
224
239
 
240
+ Returns:
241
+ np.ndarray: Multiplied DEM data.
242
+ """
243
+ if not self.multiplier != 1:
244
+ return data
245
+
246
+ multiplied_data = data * self.multiplier
225
247
  self.logger.debug(
226
- "DEM data was blurred. Shape: %s, dtype: %s. Min: %s, max: %s.",
227
- resampled_data.shape,
228
- resampled_data.dtype,
229
- resampled_data.min(),
230
- resampled_data.max(),
248
+ "DEM data was multiplied by %s. Min: %s, max: %s.",
249
+ self.multiplier,
250
+ multiplied_data.min(),
251
+ multiplied_data.max(),
231
252
  )
253
+ return multiplied_data
232
254
 
233
- if self.map.dem_settings.plateau:
234
- # Plateau is a flat area with a constant height.
235
- # So we just add this value to each pixel of the DEM.
236
- # And also need to ensure that there will be no values with height greater than
237
- # it's allowed in 16-bit unsigned integer.
255
+ def resize_to_output(self, data: np.ndarray) -> np.ndarray:
256
+ """Resize DEM data to the output resolution.
238
257
 
239
- resampled_data += self.map.dem_settings.plateau
240
- resampled_data = np.clip(resampled_data, 0, 65535)
258
+ Arguments:
259
+ data (np.ndarray): DEM data.
241
260
 
242
- self.logger.debug(
243
- "Plateau with height %s was added to DEM data. Min: %s, max: %s.",
244
- self.map.dem_settings.plateau,
245
- resampled_data.min(),
246
- resampled_data.max(),
247
- )
261
+ Returns:
262
+ np.ndarray: Resized DEM data.
263
+ """
264
+ resampled_data = cv2.resize(data, self.output_resolution, interpolation=cv2.INTER_LINEAR)
248
265
 
249
- cv2.imwrite(self._dem_path, resampled_data)
250
- self.logger.debug("DEM data was saved to %s.", self._dem_path)
266
+ size_of_resampled_data = asizeof.asizeof(resampled_data) / 1024 / 1024
267
+ self.logger.debug("Size of resampled data: %s MB.", size_of_resampled_data)
251
268
 
252
- if self.rotation:
253
- self.rotate_dem()
269
+ return resampled_data
270
+
271
+ def apply_blur(self, data: np.ndarray) -> np.ndarray:
272
+ """Apply blur to DEM data.
273
+
274
+ Arguments:
275
+ data (np.ndarray): DEM data.
276
+
277
+ Returns:
278
+ np.ndarray: Blurred DEM data.
279
+ """
280
+ if self.blur_radius == 0:
281
+ return data
282
+
283
+ self.logger.debug(
284
+ "Applying Gaussion blur to DEM data with kernel size %s.",
285
+ self.blur_radius,
286
+ )
287
+
288
+ blurred_data = cv2.GaussianBlur(
289
+ data, (self.blur_radius, self.blur_radius), sigmaX=10, sigmaY=10
290
+ )
291
+ self.logger.debug(
292
+ "DEM data was blurred. Shape: %s, dtype: %s. Min: %s, max: %s.",
293
+ blurred_data.shape,
294
+ blurred_data.dtype,
295
+ blurred_data.min(),
296
+ blurred_data.max(),
297
+ )
298
+ return blurred_data
254
299
 
255
300
  def rotate_dem(self) -> None:
256
301
  """Rotate DEM image."""
@@ -29,9 +29,6 @@ if TYPE_CHECKING:
29
29
  class DTMProviderSettings(BaseModel):
30
30
  """Base class for DTM provider settings models."""
31
31
 
32
- easy_mode: bool = True
33
- power_factor: int = 0
34
-
35
32
 
36
33
  # pylint: disable=too-many-public-methods, too-many-instance-attributes
37
34
  class DTMProvider(ABC):
@@ -56,20 +53,7 @@ class DTMProvider(ABC):
56
53
 
57
54
  _instructions: str | None = None
58
55
 
59
- _base_instructions = (
60
- "ℹ️ Using **Easy mode** is recommended, as it automatically adjusts the values in the "
61
- "image, so the terrain elevation in Giants Editor will match real world "
62
- "elevation in meters. \n"
63
- "ℹ️ If the terrain height difference in the real world is bigger than 255 meters, "
64
- "the [Height scale](https://github.com/iwatkot/maps4fs/blob/main/docs/dem.md#height-scale)"
65
- " parameter in the **map.i3d** file will be automatically adjusted. \n"
66
- "⚡ If the **Easy mode** option is disabled, you will probably get completely flat "
67
- "terrain, unless you adjust the DEM Multiplier Setting or the Height scale parameter in "
68
- "the Giants Editor. \n"
69
- "💡 You can use the **Power factor** setting to make the difference between heights "
70
- "bigger. Be extremely careful with this setting, and use only low values, otherwise your "
71
- "terrain may be completely broken. \n"
72
- )
56
+ _base_instructions = None
73
57
 
74
58
  # pylint: disable=R0913, R0917
75
59
  def __init__(
@@ -304,64 +288,8 @@ class DTMProvider(ABC):
304
288
  # extract region of interest from the tile
305
289
  data = self.extract_roi(tile)
306
290
 
307
- # process elevation data to be compatible with the game
308
- data = self.process_elevation(data)
309
-
310
291
  return data
311
292
 
312
- def process_elevation(self, data: np.ndarray) -> np.ndarray:
313
- """Process elevation data.
314
-
315
- Arguments:
316
- data (np.ndarray): Elevation data.
317
-
318
- Returns:
319
- np.ndarray: Processed elevation data.
320
- """
321
- self.data_info = {}
322
- self.add_numpy_params(data, "original")
323
-
324
- data = self.ground_height_data(data)
325
- self.add_numpy_params(data, "grounded")
326
-
327
- original_deviation = int(self.data_info["original_deviation"])
328
- in_game_maximum_height = 65535 // 255
329
- if original_deviation > in_game_maximum_height:
330
- suggested_height_scale_multiplier = (
331
- original_deviation / in_game_maximum_height # type: ignore
332
- )
333
- suggested_height_scale_value = int(255 * suggested_height_scale_multiplier)
334
- else:
335
- suggested_height_scale_multiplier = 1
336
- suggested_height_scale_value = 255
337
-
338
- self.data_info["suggested_height_scale_multiplier"] = suggested_height_scale_multiplier
339
- self.data_info["suggested_height_scale_value"] = suggested_height_scale_value
340
-
341
- self.map.shared_settings.height_scale_multiplier = ( # type: ignore
342
- suggested_height_scale_multiplier
343
- )
344
- self.map.shared_settings.height_scale_value = suggested_height_scale_value # type: ignore
345
-
346
- if self.user_settings.easy_mode: # type: ignore
347
- try:
348
- data = self.normalize_dem(data)
349
- self.add_numpy_params(data, "normalized")
350
-
351
- normalized_deviation = self.data_info["normalized_deviation"]
352
- z_scaling_factor = normalized_deviation / original_deviation # type: ignore
353
- self.data_info["z_scaling_factor"] = z_scaling_factor
354
-
355
- self.map.shared_settings.mesh_z_scaling_factor = z_scaling_factor # type: ignore
356
- self.map.shared_settings.change_height_scale = True # type: ignore
357
-
358
- except Exception as e: # pylint: disable=W0718
359
- self.logger.error(
360
- "Failed to normalize DEM data. Error: %s. Using original data.", e
361
- )
362
-
363
- return data.astype(np.uint16)
364
-
365
293
  def info_sequence(self) -> dict[str, int | str | float] | None:
366
294
  """Returns the information sequence for the component. Must be implemented in the child
367
295
  class. If the component does not have an information sequence, an empty dictionary must be
@@ -414,6 +342,7 @@ class DTMProvider(ABC):
414
342
  desc="Downloading tiles",
415
343
  unit="tile",
416
344
  initial=len(tif_files),
345
+ total=len(urls),
417
346
  ):
418
347
  try:
419
348
  file_name = os.path.basename(url)
@@ -570,84 +499,4 @@ class DTMProvider(ABC):
570
499
 
571
500
  return data
572
501
 
573
- def normalize_dem(self, data: np.ndarray) -> np.ndarray:
574
- """Normalize DEM data to 16-bit unsigned integer using max height from settings.
575
-
576
- Arguments:
577
- data (np.ndarray): DEM data from SRTM file after cropping.
578
-
579
- Returns:
580
- np.ndarray: Normalized DEM data.
581
- """
582
- maximum_height = int(data.max())
583
- minimum_height = int(data.min())
584
- deviation = maximum_height - minimum_height
585
- self.logger.debug(
586
- "Maximum height: %s. Minimum height: %s. Deviation: %s.",
587
- maximum_height,
588
- minimum_height,
589
- deviation,
590
- )
591
- self.logger.debug("Number of unique values in original DEM data: %s.", np.unique(data).size)
592
-
593
- adjusted_maximum_height = maximum_height * 255
594
- adjusted_maximum_height = min(adjusted_maximum_height, 65535)
595
- scaling_factor = adjusted_maximum_height / maximum_height
596
- self.logger.debug(
597
- "Adjusted maximum height: %s. Scaling factor: %s.",
598
- adjusted_maximum_height,
599
- scaling_factor,
600
- )
601
-
602
- if self.user_settings.power_factor: # type: ignore
603
- power_factor = 1 + self.user_settings.power_factor / 10 # type: ignore
604
- self.logger.debug(
605
- "Applying power factor: %s to the DEM data.",
606
- power_factor,
607
- )
608
- data = np.power(data, power_factor)
609
-
610
- normalized_data = np.round(data * scaling_factor).astype(np.uint16)
611
- self.logger.debug(
612
- "Normalized data maximum height: %s. Minimum height: %s. Number of unique values: %s.",
613
- normalized_data.max(),
614
- normalized_data.min(),
615
- np.unique(normalized_data).size,
616
- )
617
- return normalized_data
618
-
619
- @staticmethod
620
- def ground_height_data(data: np.ndarray, add_one: bool = True) -> np.ndarray:
621
- """Shift the data to ground level (0 meter).
622
- Optionally add one meter to the data to leave some room
623
- for the water level and pit modifications.
624
-
625
- Arguments:
626
- data (np.ndarray): DEM data after cropping.
627
- add_one (bool): Add one meter to the data
628
-
629
- Returns:
630
- np.ndarray: Unsigned DEM data.
631
- """
632
- data = data - data.min()
633
- if add_one:
634
- data = data + 1
635
- return data
636
-
637
- def add_numpy_params(
638
- self,
639
- data: np.ndarray,
640
- prefix: str,
641
- ) -> None:
642
- """Add numpy array parameters to the data_info dictionary.
643
-
644
- Arguments:
645
- data (np.ndarray): Numpy array of the tile.
646
- prefix (str): Prefix for the parameters.
647
- """
648
- self.data_info[f"{prefix}_minimum_height"] = int(data.min()) # type: ignore
649
- self.data_info[f"{prefix}_maximum_height"] = int(data.max()) # type: ignore
650
- self.data_info[f"{prefix}_deviation"] = int(data.max() - data.min()) # type: ignore
651
- self.data_info[f"{prefix}_unique_values"] = int(np.unique(data).size) # type: ignore
652
-
653
502
  # endregion
@@ -31,6 +31,8 @@ class SRTM30Provider(DTMProvider):
31
31
 
32
32
  _settings = SRTM30ProviderSettings
33
33
 
34
+ _instructions = "ℹ️ Recommended settings: \nDEM Settings -> Blur Radius: **35**"
35
+
34
36
  def __init__(self, *args, **kwargs):
35
37
  super().__init__(*args, **kwargs)
36
38
  self.hgt_directory = os.path.join(self._tile_directory, "hgt")
@@ -102,18 +102,22 @@ class DEMSettings(SettingsModel):
102
102
  """Represents the advanced settings for DEM component.
103
103
 
104
104
  Attributes:
105
- multiplier (int): multiplier for the heightmap, every pixel will be multiplied by this
106
- value.
105
+ adjust_terrain_to_ground_level (bool): adjust terrain to ground level or not.
106
+ multiplier (int): multiplier for the heightmap.
107
107
  blur_radius (int): radius of the blur filter.
108
- plateau (int): plateau height, will be added to each pixel.
109
- water_depth (int): water depth, will be subtracted from each pixel where the water
110
- is present.
108
+ minimum_height_scale (int): minimum height scale for the i3d.
109
+ plateau (int): plateau height.
110
+ ceiling (int): ceiling height.
111
+ water_depth (int): water depth.
111
112
  """
112
113
 
114
+ adjust_terrain_to_ground_level: bool = True
113
115
  multiplier: int = 1
114
- blur_radius: int = 35
116
+ minimum_height_scale: int = 255
115
117
  plateau: int = 0
118
+ ceiling: int = 0
116
119
  water_depth: int = 0
120
+ blur_radius: int = 3
117
121
 
118
122
 
119
123
  class BackgroundSettings(SettingsModel):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: maps4fs
3
- Version: 1.8.17
3
+ Version: 1.8.172
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
@@ -562,13 +562,17 @@ You can also apply some advanced settings to the map generation process.<br>
562
562
 
563
563
  ### DEM Advanced settings
564
564
 
565
- - Multiplier: the height of the map is multiplied by this value. So the DEM map is just a 16-bit grayscale image, which means that the maximum available value there is 65535, while the actual difference between the deepest and the highest point on Earth is about 20 km. Just note that this setting mostly does not matter, because you can always adjust it in the Giants Editor, learn more about the DEM file and the heightScale parameter in [docs](docs/dem.md). To match the in-game heights with SRTM Data provider, the recommended value is 255 (if easy mode is disabled), but depending on the place, you will need to play with both multiplier and the height scale in Giants Editor to find the best values.
565
+ - Adjust terrain to ground level: Enabling this setting (default) will raise or lower the terrain so that it's lowest point is at ground level (taking into account the plateau and water depth settings).
566
566
 
567
- - Blur radius: the radius of the Gaussian blur filter applied to the DEM map. By default, it's set to 21. This filter just makes the DEM map smoother, so the height transitions will be more natural. You can set it to 1 to disable the filter, but it will result in a Minecraft-like map.
567
+ - Multiplier: DEM multiplier can be used to make the terrain more pronounced. By default the DEM file will be exact copy of the real terrain. If you want to make it more steep, you can increase this value. The recommended value of the multiplier is 1.
568
568
 
569
- - Plateau: this value will be added to each pixel of the DEM image, making it "higher". It's useful when you want to add some negative heights on the map, that appear to be in a "low" place. By default, it's set to 0.
569
+ - Minimum height scale: This value is used as the heightScale in your map i3d. It will automatically be set higher if the elevation in your map (plus plateau, ceiling and water depth) is higher than this value.
570
570
 
571
- - Water depth: this value will be subtracted from each pixel of the DEM image, where water resources are located. Pay attention that it's not in meters, instead it in the pixel value of DEM, which is 16 bit image with possible values from 0 to 65535. When this value is set, the same value will be added to the plateau setting to avoid negative heights.
571
+ - Plateau: DEM plateau value (in meters) is used to make the whole map higher or lower. This value will be added to each pixel of the DEM image, making it higher. It can be useful if you're working on a plain area and need to add some negative height (to make rivers, for example).
572
+
573
+ - Ceiling: DEM ceiling value (in meters) is used to add padding in the DEM above the highest elevation in your map area. It can be useful if you plan to manually add some height to the map by sculpting the terrain in GE.
574
+
575
+ - Water depth: Water depth value (in meters) will be subtracted from the DEM image, making the water deeper. The pixel value used for this is calculated based on the heightScale value for your map.
572
576
 
573
577
  ### Background terrain Advanced settings
574
578
 
@@ -703,4 +707,3 @@ But also, I want to thank the people who helped me with the project in some way,
703
707
  - [kbrandwijk](https://github.com/kbrandwijk) - for providing [awesome tool](https://github.com/Paint-a-Farm/satmap_downloader) to download the satellite images from the Google Maps and giving a permission to modify it and create a Python Package.
704
708
  - [Maaslandmods](https://github.com/Maaslandmods) - for the awesome idea to edit the tree schema in UI, images and code snippets on how to do it.
705
709
  - [StrauntMaunt](https://gitlab.com/StrauntMaunt) - for developing procedural generation scripts, providing with the required updates for maps4fs and preparing the docs on how to use procedural generation.
706
-
@@ -1,15 +1,15 @@
1
1
  maps4fs/__init__.py,sha256=iq4GcHoQ-by-BK6CzDOfVcdDww6osyi9Wv6pKXub68U,1307
2
2
  maps4fs/logger.py,sha256=B-NEYpMjPAAqlV4VpfTi6nbBFnEABVtQOaYe6nMpidg,1489
3
3
  maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
4
- maps4fs/generator/dem.py,sha256=RsIaL3LabYnZzow2fzmccsnzBo0m1YjcVVxUkJJGJMU,10735
4
+ maps4fs/generator/dem.py,sha256=oLN02bWNax73HzFsseRBOV47Azl_1L7qdrzuxHh4i_c,11886
5
5
  maps4fs/generator/game.py,sha256=YwtdzqwcBJm1FHtc1ehDd3WbfTTW_gBvxK-pzfU48zs,11015
6
6
  maps4fs/generator/map.py,sha256=c5GMhr5iTRdXvTXoBKyVYa2V1tocR3ZCc7D_hpU21k8,11523
7
7
  maps4fs/generator/qgis.py,sha256=Es8hLuqN_KH8lDfnJE6He2rWYbAKJ3RGPn-o87S6CPI,6116
8
8
  maps4fs/generator/satellite.py,sha256=t33EfaxWTCjcKYnqoppSlFdQQSekiBe7UFmLgTVhFQI,3650
9
- maps4fs/generator/settings.py,sha256=psZC3k95roptV6-YQMDz9ofoKw5dBNc1TZ66DEECmSc,6134
9
+ maps4fs/generator/settings.py,sha256=sMyDY29fweF_Yo_buaUELFSYBYkOqf8VsZPL8lM8j1c,6271
10
10
  maps4fs/generator/texture.py,sha256=_IfqIuxH4934VJXKtdABHa6ToPWk3T0xknvlu-rZ5Uc,36570
11
11
  maps4fs/generator/component/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
12
- maps4fs/generator/component/background.py,sha256=pN1iMXm5Xg87OWh4XFml4bVIrueTJMdwVJvS3YWm0x0,18588
12
+ maps4fs/generator/component/background.py,sha256=HWwQnZ5k-D4MdDSUdRvvNmWGUTtqps942DVGdpEQRoE,18947
13
13
  maps4fs/generator/component/config.py,sha256=RitKgFDZPzjA1fi8GcEi1na75qqaueUvpcITHjBvCXc,3674
14
14
  maps4fs/generator/component/grle.py,sha256=aKMjVJNuKHJJ2gsXaH00bz10kWaIbbZXU_JbP-ZAGw4,18990
15
15
  maps4fs/generator/component/i3d.py,sha256=3x38yL-kSJ8ylBwICBb6wPYzRSky4gVj8XCk2jzYSeo,19861
@@ -21,7 +21,7 @@ maps4fs/generator/component/base/component_xml.py,sha256=6OO1dKoceO1ACk7-k1oGtnk
21
21
  maps4fs/generator/dtm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  maps4fs/generator/dtm/bavaria.py,sha256=7njrEvSCYAC8ZVyvS-_84iXHhWA0oHKrEqSzxdnZuGs,4293
23
23
  maps4fs/generator/dtm/canada.py,sha256=lYONwm6aNX5cjVggR3AiZZF9dlCDAWg0M8RMaObog8s,1288
24
- maps4fs/generator/dtm/dtm.py,sha256=Bu6-wHH2MXxLmfSEz_LYjfRdXmzsvnTBs18qHgdta0E,23191
24
+ maps4fs/generator/dtm/dtm.py,sha256=L824mwmd_cNTujwWBsRg7RZLq9KEXf0-xIzKx8M3y1Q,16872
25
25
  maps4fs/generator/dtm/england.py,sha256=YyCYwnNUJuBeeMNUozfKIj_yNjHpGeuH1Mz0NiAJL-U,1122
26
26
  maps4fs/generator/dtm/finland.py,sha256=Chi3-3sanLIYpipjtPpTu9tqnL3DYcnygSDCPm1s24c,1753
27
27
  maps4fs/generator/dtm/flanders.py,sha256=81pKkrM40SeOe1LSlcsTNXSmUNpofC4D454DG6WFSyA,1037
@@ -33,7 +33,7 @@ maps4fs/generator/dtm/norway.py,sha256=kSsNZGEqb3IQ3a82UCJ_Iw_0wqdCgEvuRJ4JpEK7Q
33
33
  maps4fs/generator/dtm/nrw.py,sha256=1zMa10O0NdQbiTwOa7XXGrx3NhdHUqRXI4yBn_Scb2M,958
34
34
  maps4fs/generator/dtm/scotland.py,sha256=Od4dDMuCM_iteewjGBbmZXJ26S0bDwrhRhXeV4HyyOA,4803
35
35
  maps4fs/generator/dtm/spain.py,sha256=HxN0MvrtRqqeTmhl47q60-1DGaMDb2wq6neMcDlDCl8,1005
36
- maps4fs/generator/dtm/srtm.py,sha256=abggmxrR1rC22llkJ6kFle9MYLqP-raMc76O9qm6qag,4411
36
+ maps4fs/generator/dtm/srtm.py,sha256=ob6AUuEn3G3G9kdqTA2VhT335N65RRBJsqAfHuw0gA8,4502
37
37
  maps4fs/generator/dtm/usgs.py,sha256=1XzLP5GJbe6xcqzkOrEBUtR2SPw7gm6rl1nw5YXmBP8,3253
38
38
  maps4fs/generator/dtm/utils.py,sha256=I-wUSA_J85Xbt8sZCZAVKHSIcrMj5Ng-0adtPVhVmk0,2315
39
39
  maps4fs/generator/dtm/base/wcs.py,sha256=UfkLNHqsYTr2ytjyZjWDocq2hFC_qyFCvl-_tnz6gHM,2510
@@ -42,8 +42,8 @@ maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,4
42
42
  maps4fs/toolbox/background.py,sha256=RclEqxEWLbMxuEkkegQP8jybzugwQ1_R3rdfDe0s21U,2104
43
43
  maps4fs/toolbox/custom_osm.py,sha256=X6ZlPqiOhNjkmdD_qVroIfdOl9Rb90cDwVSLDVYgx80,1892
44
44
  maps4fs/toolbox/dem.py,sha256=z9IPFNmYbjiigb3t02ZenI3Mo8odd19c5MZbjDEovTo,3525
45
- maps4fs-1.8.17.dist-info/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
46
- maps4fs-1.8.17.dist-info/METADATA,sha256=TRJU38laadwnDBkXQ9yJNPVQf06oq9FtJOfkQvTHxGQ,43207
47
- maps4fs-1.8.17.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
48
- maps4fs-1.8.17.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
49
- maps4fs-1.8.17.dist-info/RECORD,,
45
+ maps4fs-1.8.172.dist-info/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
46
+ maps4fs-1.8.172.dist-info/METADATA,sha256=E5nc98xim9woImXF8JqFv44PLOjeqiBHhqdFfB8H3WA,43012
47
+ maps4fs-1.8.172.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
48
+ maps4fs-1.8.172.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
49
+ maps4fs-1.8.172.dist-info/RECORD,,