diff --git a/src/data_processing.rs b/src/data_processing.rs index 917f9c37b..92c132da0 100644 --- a/src/data_processing.rs +++ b/src/data_processing.rs @@ -83,21 +83,6 @@ pub fn generate_world_with_options( // Amenity processors use this for O(1) nearest-road-block lookups. let road_mask = highways::collect_road_surface_coords(&elements, &xzbbox, args.scale); - // Process all elements (no longer need to partition boundaries) - let elements_count: usize = elements.len(); - let process_pb: ProgressBar = ProgressBar::new(elements_count as u64); - process_pb.set_style(ProgressStyle::default_bar() - .template("{spinner:.green} [{elapsed_precise}] [{bar:45.white/black}] {pos}/{len} elements ({eta}) {msg}") - .unwrap() - .progress_chars("█▓░")); - - let progress_increment_prcs: f64 = 45.0 / elements_count as f64; - let mut current_progress_prcs: f64 = 25.0; - let mut last_emitted_progress: f64 = current_progress_prcs; - let desired_updates: u64 = 500; - let pb_batch_size: u64 = (elements_count as u64 / desired_updates).max(1); - let mut element_counter: u64 = 0; - // Pre-scan: detect building relation outlines that should be suppressed. // Only applies to type=building relations (NOT type=multipolygon). // When a type=building relation has "part" members, the outline way should not @@ -125,8 +110,73 @@ pub fn generate_world_with_options( outlines }; - // Process all elements + // Separate landuse elements from other elements + let mut landuse_elements: Vec = Vec::new(); + let mut other_elements: Vec = Vec::new(); + for element in elements.into_iter() { + match &element { + // First landuse + ProcessedElement::Way(way) if way.tags.contains_key("landuse") => { + landuse_elements.push(element); + } + ProcessedElement::Relation(rel) if rel.tags.contains_key("landuse") => { + landuse_elements.push(element); + } + // Then others + _ => { + other_elements.push(element); + } + } + } + + // Sort landuse elements by priority (grass > meadow > forest) + landuse_elements.sort_by(|a, b| { + let get_priority = |elem: &ProcessedElement| -> u8 { + match elem { + ProcessedElement::Way(way) => match way.tags.get("landuse").unwrap().as_str() { + "grass" => 3, + "meadow" => 2, + "forest" => 1, + _ => 0, + }, + ProcessedElement::Relation(rel) => match rel.tags.get("landuse").unwrap().as_str() { + "grass" => 3, + "meadow" => 2, + "forest" => 1, + _ => 0, + }, + _ => 0, + } + }; + let b_prio = get_priority(b); + let a_prio = get_priority(a); + b_prio.cmp(&a_prio) + }); + + // Combine all elements in the correct order + let sorted_elements = other_elements + .into_iter() + .chain(landuse_elements.into_iter()) + .collect::>(); + + // Set elements count to new length + let elements_count: usize = sorted_elements.len(); + let process_pb: ProgressBar = ProgressBar::new(elements_count as u64); + process_pb.set_style(ProgressStyle::default_bar() + .template("{spinner:.green} [{elapsed_precise}] [{bar:45.white/black}] {pos}/{len} elements ({eta}) {msg}") + .unwrap() + .progress_chars("█▓░")); + + let progress_increment_prcs: f64 = 45.0 / elements_count as f64; + let mut current_progress_prcs: f64 = 25.0; + let mut last_emitted_progress: f64 = current_progress_prcs; + let desired_updates: u64 = 500; + let pb_batch_size: u64 = (elements_count as u64 / desired_updates).max(1); + let mut element_counter: u64 = 0; + + // Process all elements + for element in sorted_elements.into_iter() { element_counter += 1; if element_counter.is_multiple_of(pb_batch_size) { process_pb.inc(pb_batch_size); diff --git a/src/element_processing/landuse.rs b/src/element_processing/landuse.rs index b67c63be8..042624d6a 100644 --- a/src/element_processing/landuse.rs +++ b/src/element_processing/landuse.rs @@ -135,6 +135,17 @@ pub fn generate_landuse( ]), ); + let new_prio = WorldEditor::landuse_priority(landuse_tag); + + // Check if high prio landuse already exists + if let Some(existing_prio) = editor.get_landuse_priority(x, z) { + if existing_prio >= new_prio { + continue; + } + } + + editor.set_landuse(x, z, landuse_tag); + if landuse_tag == "traffic_island" { editor.set_block(actual_block, x, 1, z, None, None); } else if landuse_tag == "construction" || landuse_tag == "railway" { diff --git a/src/element_processing/leisure.rs b/src/element_processing/leisure.rs index 6369cbc26..9c3635c51 100644 --- a/src/element_processing/leisure.rs +++ b/src/element_processing/leisure.rs @@ -3,7 +3,6 @@ use crate::block_definitions::*; use crate::bresenham::bresenham_line; use crate::deterministic_rng::element_rng; use crate::element_processing::surfaces::get_blocks_for_surface; -use crate::element_processing::tree::Tree; use crate::floodfill_cache::{BuildingFootprintBitmap, FloodFillCache}; use crate::osm_parser::{ProcessedMemberRole, ProcessedRelation, ProcessedWay}; use crate::world_editor::WorldEditor; @@ -14,7 +13,7 @@ pub fn generate_leisure( element: &ProcessedWay, args: &Args, flood_fill_cache: &FloodFillCache, - building_footprints: &BuildingFootprintBitmap, + _building_footprints: &BuildingFootprintBitmap, ) { if let Some(leisure_type) = element.tags.get("leisure") { let mut previous_node: Option<(i32, i32)> = None; @@ -115,10 +114,6 @@ pub fn generate_leisure( // Oak leaves editor.set_block(OAK_LEAVES, x, 1, z, None, None); } - 105..120 => { - // Tree - Tree::create(editor, (x, 1, z), Some(building_footprints)); - } _ => {} } } diff --git a/src/ground_generation.rs b/src/ground_generation.rs index 130731766..ca6b77c4d 100644 --- a/src/ground_generation.rs +++ b/src/ground_generation.rs @@ -1029,6 +1029,7 @@ pub fn generate_ground_layer( LIGHT_GRAY_CONCRETE, WHITE_CONCRETE, DIRT_PATH, + SAND, ]), None, ) && editor.check_for_block_absolute( diff --git a/src/world_editor/mod.rs b/src/world_editor/mod.rs index 6a8d62a75..1d18a4607 100644 --- a/src/world_editor/mod.rs +++ b/src/world_editor/mod.rs @@ -138,6 +138,7 @@ pub struct WorldEditor<'a> { bedrock_spawn_point: Option<(i32, i32)>, #[cfg(feature = "bedrock")] bedrock_extend_height: bool, + landuse_map: HashMap<(i32, i32), String>, } impl<'a> WorldEditor<'a> { @@ -160,6 +161,7 @@ impl<'a> WorldEditor<'a> { bedrock_spawn_point: None, #[cfg(feature = "bedrock")] bedrock_extend_height: false, + landuse_map: HashMap::new(), } } @@ -194,6 +196,7 @@ impl<'a> WorldEditor<'a> { bedrock_spawn_point, #[cfg(feature = "bedrock")] bedrock_extend_height, + landuse_map: HashMap::new(), } } @@ -1162,6 +1165,28 @@ impl<'a> WorldEditor<'a> { Ok(()) } + + /// Set landuse for given position + pub fn set_landuse(&mut self, x: i32, z: i32, landuse_tag: &str) { + self.landuse_map.insert((x, z), landuse_tag.to_string()); + } + + /// Get priority for landuse if available + pub fn get_landuse_priority(&self, x: i32, z: i32) -> Option { + self.landuse_map + .get(&(x, z)) + .map(|tag| Self::landuse_priority(tag)) + } + + /// Landuse priority helper + pub fn landuse_priority(tag: &str) -> u8 { + match tag { + "grass" => 3, + "meadow" => 2, + "forest" => 1, + _ => 0, + } + } } #[allow(dead_code)]