Skip to content

Commit

Permalink
Preview update and custom map size
Browse files Browse the repository at this point in the history
* Preview update and custom size.

* Version update.

* README update.

* README update.
  • Loading branch information
iwatkot authored Nov 18, 2024
1 parent 9d37788 commit da5c21a
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 36 deletions.
31 changes: 15 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
<a href="#Quick-Start">Quick Start</a> •
<a href="#Overview">Overview</a> •
<a href="#How-To-Run">How-To-Run</a> •
<a href="#Features">Features</a> •
<a href="#Supported-objects">Supported objects</a> •
<a href="#Advanced Settings">Advanced Settings</a> •
<a href="#For-advanced-users">For advanced users</a> •
<a href="#Bugs-and-feature-requests">Bugs and feature requests</a>
</p>

Expand All @@ -24,10 +23,13 @@

</div>

### Supported Games
🗺️ Supports 2x2, 4x4, 8x8, 16x16 and any custom size maps<br>
🌍 Based on real-world data from OpenStreetMap<br>
🏞️ Generates height using SRTM dataset<br>
📦 Provides a ready-to-use map template for the Giants Editor<br>
🚜 Supports Farming Simulator 22 and 25*<br>

✅ Farming Simulator 22<br>
🔃 Farming Simulator 25 (changes in the library are ready, waiting for the Giants to release the Giants Editor v10)<br>
\* changes in the library are ready, waiting for the Giants to release the Giants Editor v10. Meanwhile the option to generate a map for FS25 is disabled.

## Quick Start
There are several ways to use the tool. You obviously need the **first one**, but you can choose any of the others depending on your needs.<br>
Expand Down Expand Up @@ -80,15 +82,13 @@ You'll find detailed instructions on how to run the project below. But if you pr
<i>Video tutorial: How to generate a Farming Simulator 22 map from real-world data.</i>

### Option 1: StreamLit
**🗺️ Supported map sizes:** 2x2, 4x4, 8x8, 16x16 km.<br>
🟢 Recommended for all users, you don't need to install anything.<br>
Using the [StreamLit](https://maps4fs.streamlit.app) version of the tool is the easiest way to generate a map template. Just open the link and follow the instructions.
Note: due to CPU and RAM limitations of the hosting, the generation may take some time. If you need faster processing, use the [Docker version](#option-2-docker-version).<br>

Using it is easy and doesn't require any guides. Enjoy!

### Option 2: Docker version
**🗺️ Supported map sizes:** 2x2, 4x4, 8x8, 16x16 km.<br>
🟠 Recommended for users who want faster processing, very simple installation.<br>
You can launch the project with minimalistic UI in your browser using Docker. Follow these steps:

Expand All @@ -101,10 +101,9 @@ docker run -d -p 8501:8501 iwatkot/maps4fs
4. Fill in the required fields and click on the `Generate` button.
5. When the map is generated click on the `Download` button to get the map.

![WebUI](https://github.com/user-attachments/assets/e3b48c9d-7b87-4ce7-8ad7-98332a558a88)
![WebUI](https://github.com/user-attachments/assets/581e1206-2abd-4b3c-ad31-80554ad92d99)

### Option 3: Python package
**🗺️ Supported map sizes:** 2x2, 4x4, 8x8, 16x16 km (and ANY other you may add).<br>
🔴 Recommended for developers.<br>
You can use the Python package to generate maps. Follow these steps:

Expand Down Expand Up @@ -149,12 +148,6 @@ map.generate()

The map will be saved in the `map_directory` directory.

## Features
- Allows to enter a location by lat and lon (e.g. from Google Maps).
- Allows to select a size of the map (2x2, 4x4, 8x8 km, 16x16 km).
- Generates a map template (check the list of supported objects in [this section](#supported-objects)).
- Generates a height map.

## Supported objects
The project is based on the [OpenStreetMap](https://www.openstreetmap.org/) data. So, refer to [this page](https://wiki.openstreetmap.org/wiki/Map_Features) to understand the list below.
- "building": True
Expand Down Expand Up @@ -187,7 +180,13 @@ The script will also generate the `generation_info.json` file in the `output` fo

You can use this information to adjust some other sources of data to the map, e.g. textures, height maps, etc.

## Advanced Settings
## For advanced users
The tool supports the custom size of the map. To use this feature select `Custom` in the `Map size` dropdown and enter the desired size. The tool will generate a map with the size you entered.<br>

⛔️ Do not use this feature, if you don't know what you're doing. In most cases the Giants Editor will just crash on opening the file, because you need to enter a specific values for the map size.<br><br>

![Advanced settings and custom size](https://github.com/user-attachments/assets/327b6065-09ed-41d0-86a8-7d904025707c)

You can also apply some advanced settings to the map generation process. Note that they're ADVANCED, so you don't need to use them if you're not sure what they do.<br>

Here's the list of the advanced settings:
Expand Down
8 changes: 5 additions & 3 deletions maps4fs/generator/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ def get_bbox(self, project_utm: bool = False) -> tuple[int, int, int, int]:
)
bbox = north, south, east, west
self.logger.debug(
f"Calculated bounding box for component: {self.__class__.__name__}: {bbox}, "
f"project_utm: {project_utm}"
"Calculated bounding box for component: %s: %s, project_utm: %s",
self.__class__.__name__,
bbox,
project_utm,
)
return bbox

Expand All @@ -96,4 +98,4 @@ def save_bbox(self) -> None:
height and width of the map.
"""
self.bbox = self.get_bbox(project_utm=False)
self.logger.debug(f"Saved bounding box: {self.bbox}")
self.logger.debug("Saved bounding box: %s", self.bbox)
35 changes: 23 additions & 12 deletions maps4fs/generator/dem.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,35 +85,45 @@ def process(self) -> None:
return

self.logger.debug(
f"DEM data was read from SRTM file. Shape: {data.shape}, dtype: {data.dtype}. "
f"Min: {data.min()}, max: {data.max()}."
"DEM data was read from SRTM file. Shape: %s, dtype: %s. Min: %s, max: %s.",
data.shape,
data.dtype,
data.min(),
data.max(),
)

resampled_data = cv2.resize(
data, dem_output_resolution, interpolation=cv2.INTER_LINEAR
).astype("uint16")

self.logger.debug(
f"Maximum value in resampled data: {resampled_data.max()}, "
f"minimum value: {resampled_data.min()}."
"Maximum value in resampled data: %s, minimum value: %s.",
resampled_data.max(),
resampled_data.min(),
)

resampled_data = resampled_data * self.multiplier
self.logger.debug(
f"DEM data multiplied by {self.multiplier}. Shape: {resampled_data.shape}, "
f"dtype: {resampled_data.dtype}. "
f"Min: {resampled_data.min()}, max: {resampled_data.max()}."
"DEM data multiplied by %s. Shape: %s, dtype: %s. Min: %s, max: %s.",
self.multiplier,
resampled_data.shape,
resampled_data.dtype,
resampled_data.min(),
resampled_data.max(),
)

self.logger.debug(
f"DEM data was resampled. Shape: {resampled_data.shape}, "
f"dtype: {resampled_data.dtype}. "
f"Min: {resampled_data.min()}, max: {resampled_data.max()}."
"DEM data was resampled. Shape: %s, dtype: %s. Min: %s, max: %s.",
resampled_data.shape,
resampled_data.dtype,
resampled_data.min(),
resampled_data.max(),
)

resampled_data = cv2.GaussianBlur(resampled_data, (self.blur_radius, self.blur_radius), 0)
self.logger.debug(
f"Gaussion blur applied to DEM data with kernel size {self.blur_radius}. "
"Gaussion blur applied to DEM data with kernel size %s.",
self.blur_radius,
)

cv2.imwrite(self._dem_path, resampled_data)
Expand Down Expand Up @@ -179,7 +189,8 @@ def _srtm_tile(self) -> str | None:
decompressed_file_path = os.path.join(self.hgt_dir, f"{tile_name}.hgt")
if os.path.isfile(decompressed_file_path):
self.logger.info(
f"Decompressed tile already exists: {decompressed_file_path}, skipping download."
"Decompressed tile already exists: %s, skipping download.",
decompressed_file_path,
)
return decompressed_file_path

Expand Down
21 changes: 19 additions & 2 deletions maps4fs/generator/texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

from maps4fs.generator.component import Component

PREVIEW_MAXIMUM_SIZE = 2048


# pylint: disable=R0902
class Texture(Component):
Expand Down Expand Up @@ -387,7 +389,20 @@ def _osm_preview(self) -> str:
Returns:
str: Path to the preview.
"""
preview_size = (2048, 2048)
scaling_factor = min(
PREVIEW_MAXIMUM_SIZE / self.map_width, PREVIEW_MAXIMUM_SIZE / self.map_height
)

preview_size = (
int(self.map_width * scaling_factor),
int(self.map_height * scaling_factor),
)
self.logger.debug(
"Scaling factor: %s. Preview size: %s.",
scaling_factor,
preview_size,
)

images = [
cv2.resize(
cv2.imread(layer.path(self._weights_dir), cv2.IMREAD_UNCHANGED), preview_size
Expand All @@ -402,7 +417,9 @@ def _osm_preview(self) -> str:
color_images.append(color_img)
merged = np.sum(color_images, axis=0, dtype=np.uint8)
self.logger.debug(
f"Merged layers into one image. Shape: {merged.shape}, dtype: {merged.dtype}."
"Merged layers into one image. Shape: %s, dtype: %s.",
merged.shape,
merged.dtype,
)
preview_path = os.path.join(self.map_directory, "preview_osm.png")
cv2.imwrite(preview_path, merged) # pylint: disable=no-member
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "maps4fs"
version = "0.7.2"
version = "0.7.3"
description = "Generate map templates for Farming Simulator from real places."
authors = [{name = "iwatkot", email = "iwatkot@gmail.com"}]
license = {text = "MIT License"}
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
opencv-python
opencv-python-headless
osmnx<2.0.0
rasterio
tqdm
Expand Down
7 changes: 6 additions & 1 deletion webui/webui.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,16 @@ def add_widgets(self) -> None:
st.write("Select size of the map:")
self.map_size_input = st.selectbox(
"Map Size (meters)",
options=["2048x2048", "4096x4096", "8192x8192", "16384x16384"], # , "Custom"],
options=["2048x2048", "4096x4096", "8192x8192", "16384x16384", "Custom"],
label_visibility="collapsed",
)

if self.map_size_input == "Custom":
st.warning(
"This feature is for advanced users only, you need to know exact correct values, "
"otherwise the Giants Editor will crash on opening the file. Do not use it, "
"if you are not sure what you are doing."
)
st.write("Enter map height (meters):")
map_height_input = st.number_input(
"Height (meters)", 1, 16384, 2048, key="map_height", label_visibility="collapsed"
Expand Down

0 comments on commit da5c21a

Please sign in to comment.