diff --git a/README.md b/README.md index 959f829a..e454e23c 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ 🌲 Automatically generates forests πŸ†•
🌊 Automatically generates water planes πŸ†•
🌍 Based on real-world data from OpenStreetMap
+πŸ—ΊοΈ Supports [custom OSM maps](/docs/custom_osm.md)
🏞️ Generates height map using SRTM dataset
πŸ“¦ Provides a ready-to-use map template for the Giants Editor
🚜 Supports Farming Simulator 22 and 25
@@ -502,4 +503,5 @@ But also, I want to thank the people who helped me with the project in some way, - [OneSunnySunday](https://www.artstation.com/onesunnysunday) - for expert advice on Blender, help in processing background terrain, and compiling detailed tutorials on how to prepare the OBJ files for use in Giants Editor. - [BFernaesds](https://github.com/BFernaesds) - for the manual tests of the app. - [gamerdesigns](https://github.com/gamerdesigns) - for the manual tests of the app. -- [Tox3](https://github.com/Tox3) - for the manual tests of the app. \ No newline at end of file +- [Tox3](https://github.com/Tox3) - for the manual tests of the app. +- [Lucandia](https://github.com/Lucandia) - for the awesome StreamLit [widget to preview STL files](https://github.com/Lucandia/streamlit_stl). \ No newline at end of file diff --git a/dev/clean_trash.ps1 b/dev/clean_trash.ps1 index d5e3f14b..ac516f29 100644 --- a/dev/clean_trash.ps1 +++ b/dev/clean_trash.ps1 @@ -1,5 +1,5 @@ # Directories to be removed -$dirs = @(".mypy_cache", ".pytest_cache", "htmlcov", "dist", "archives", "cache", "logs", "maps", "temp", "osmps") +$dirs = @(".mypy_cache", ".pytest_cache", "htmlcov", "dist", "archives", "cache", "logs", "maps", "temp", "osmps", "tests/data") # Files to be removed $files = @(".coverage", "queue.json") diff --git a/dev/requirements.txt b/dev/requirements.txt index 72762889..7e15e92c 100644 --- a/dev/requirements.txt +++ b/dev/requirements.txt @@ -15,4 +15,4 @@ pyproj trimesh pympler pydoc-markdown -streamlit-stl==0.0.2 \ No newline at end of file +streamlit-stl==0.0.4 \ No newline at end of file diff --git a/docs/custom_osm.md b/docs/custom_osm.md new file mode 100644 index 00000000..4faadbfa --- /dev/null +++ b/docs/custom_osm.md @@ -0,0 +1,35 @@ +## How to create a custom OSM file + +If you don't want to bother yourself editing the public version of the OSM data, deal with the community and so on, you can easily create your own OSM file and do there whatever you want. Here is a step-by-step guide on how to do it. + +1. Download the JOSM editor from the [official website](https://josm.openstreetmap.de/) or directly from the [Windows Store](https://apps.microsoft.com/detail/xpfcg1gv0wwgzx) with one click. + +2. Create a new layer (Ctrl + N). + +3. Add imagery to see the map (Ctrl + Shift + N). You can use any map provider you want, in this example I'm using Bing. + +![Add imagery](https://github.com/user-attachments/assets/8b6f0a68-821f-42d4-aff7-fda56485c175) + +4. Download the OSM data: **File** -> **Download data** (Ctrl + Shift + Down). + +![Download OSM data](https://github.com/user-attachments/assets/35b78426-73f8-4332-94dc-952510e025f1) + +5. Draw the area of your ROI (region of interest). You don't need precision here, just ensure that it's large enough to cover the area you want to work with. +After selecting the area, click **Download**. +If you see the error message "Download area too large", download it in parts. + +![Draw the area](https://github.com/user-attachments/assets/ba033f1a-adcb-4215-9852-4f01dfe1e4ef) + +6. Now you should see all the data from the selected area. + +7. You need to remove all the relations, otherwise the file can not be read by the `osmnx` library. To do it, go to the **Relations** tab, select everything and delete it. + +![Remove relations](https://github.com/user-attachments/assets/65e1ef68-fdc2-4117-8032-2429cbaeb574) + +8. Pay attention to the fact, that removing relations may lead to some areas to disappear, which was not defined separately from another objects. You can't do anything with it; if you miss something, you'll need to add it manually. + +9. You can start editing your map. You can add new objects, remove existing ones, change their properties, etc. And there will be no one to tell you that you're doing something wrong or reverse your changes. + +10. Save the file: **File** -> **Save as** (Ctrl + Shift + S). +Now, you can use this file in the generator. +Friendly reminder: save your file in some safe place, so you won't lose your changes. \ No newline at end of file diff --git a/maps4fs/generator/map.py b/maps4fs/generator/map.py index 4704f4c9..3ae9324b 100644 --- a/maps4fs/generator/map.py +++ b/maps4fs/generator/map.py @@ -79,7 +79,7 @@ class TextureSettings(NamedTuple): skip_drains: bool = False -# pylint: disable=R0913, R0902 +# pylint: disable=R0913, R0902, R0914 class Map: """Class used to generate map using all components. @@ -99,6 +99,7 @@ def __init__( # pylint: disable=R0917 rotation: int, map_directory: str, logger: Any = None, + custom_osm: str | None = None, dem_settings: DEMSettings = DEMSettings(), background_settings: BackgroundSettings = BackgroundSettings(), grle_settings: GRLESettings = GRLESettings(), @@ -126,6 +127,9 @@ def __init__( # pylint: disable=R0917 self.logger.info("Game was set to %s", game.code) + self.custom_osm = custom_osm + self.logger.info("Custom OSM file: %s", custom_osm) + self.dem_settings = dem_settings self.logger.info("DEM settings: %s", dem_settings) self.background_settings = background_settings diff --git a/maps4fs/generator/texture.py b/maps4fs/generator/texture.py index 5d9b3e2e..4507e3e3 100644 --- a/maps4fs/generator/texture.py +++ b/maps4fs/generator/texture.py @@ -635,7 +635,10 @@ def polygons( """ is_fieds = info_layer == "fields" try: - objects = ox.features_from_bbox(bbox=self.new_bbox, tags=tags) + if self.map.custom_osm is not None: + objects = ox.features_from_xml(self.map.custom_osm, tags=tags) + else: + objects = ox.features_from_bbox(bbox=self.new_bbox, tags=tags) except Exception: # pylint: disable=W0718 self.logger.debug("Error fetching objects for tags: %s.", tags) return diff --git a/requirements.txt b/requirements.txt index 12ba31a3..21820823 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,6 +7,6 @@ geopy trimesh pyproj fast-simplification -streamlit-stl==0.0.2 +streamlit-stl==0.0.4 pympler maps4fs \ No newline at end of file diff --git a/webui/generator.py b/webui/generator.py index 1a1fc190..f9800088 100644 --- a/webui/generator.py +++ b/webui/generator.py @@ -234,6 +234,29 @@ def add_left_widgets(self) -> None: st.info(Messages.AUTO_PRESET_DISABLED) + self.custom_osm_path = None + + st.write("[ALPHA] Custom OSM:") + self.custom_osm_enabled = st.checkbox( + "Upload custom OSM file", + value=False, + key="custom_osm_enabled", + ) + + if self.custom_osm_enabled: + st.warning("⚠️ ALPHA FEATURE: Use it at your own risk.") + st.info(Messages.CUSTOM_OSM_INFO) + + uploaded_file = st.file_uploader("Choose a file", type=["osm"]) + if uploaded_file is not None: + timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + self.custom_osm_path = os.path.join( + config.INPUT_DIRECTORY, f"custom_osm_{timestamp}.osm" + ) + with open(self.custom_osm_path, "wb") as f: + f.write(uploaded_file.read()) + st.success(f"Custom OSM file uploaded: {uploaded_file.name}") + # Add checkbox for advanced settings. st.write("Advanced settings:") self.advanced_settings = st.checkbox( @@ -589,6 +612,11 @@ def generate_map(self) -> None: st.error("Invalid tree schema!") return + if self.custom_osm_enabled: + osm_path = self.custom_osm_path + else: + osm_path = None + mp = mfs.Map( game, coordinates, @@ -596,6 +624,7 @@ def generate_map(self) -> None: self.rotation, map_directory, logger=self.logger, + custom_osm=osm_path, dem_settings=dem_settings, background_settings=background_settings, grle_settings=grle_settings, @@ -699,6 +728,7 @@ def show_preview(self, mp: mfs.Map) -> None: auto_rotate=True, height="400", key=None, + max_view_distance=10000, ) except Exception: continue diff --git a/webui/templates.py b/webui/templates.py index 45546951..441342aa 100644 --- a/webui/templates.py +++ b/webui/templates.py @@ -124,3 +124,8 @@ class Messages: "This section contains the schema which is used to generate the trees. " "Any changes here can lead to errors or completely broken map. " ) + CUSTOM_OSM_INFO = ( + "To prepare the custom OSM file, please refer to the [documentation](" + "https://github.com/iwatkot/maps4fs/blob/main/docs/custom_osm.md). \n" + "Note, that incorrect file can lead to errors or completely broken map." + )