Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 66 additions & 16 deletions src/data_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<ProcessedElement> = Vec::new();
let mut other_elements: Vec<ProcessedElement> = 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::<Vec<_>>();

// 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);
Expand Down
11 changes: 11 additions & 0 deletions src/element_processing/landuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down
7 changes: 1 addition & 6 deletions src/element_processing/leisure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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));
}
_ => {}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/ground_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ pub fn generate_ground_layer(
LIGHT_GRAY_CONCRETE,
WHITE_CONCRETE,
DIRT_PATH,
SAND,
]),
None,
) && editor.check_for_block_absolute(
Expand Down
25 changes: 25 additions & 0 deletions src/world_editor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand All @@ -160,6 +161,7 @@ impl<'a> WorldEditor<'a> {
bedrock_spawn_point: None,
#[cfg(feature = "bedrock")]
bedrock_extend_height: false,
landuse_map: HashMap::new(),
}
}

Expand Down Expand Up @@ -194,6 +196,7 @@ impl<'a> WorldEditor<'a> {
bedrock_spawn_point,
#[cfg(feature = "bedrock")]
bedrock_extend_height,
landuse_map: HashMap::new(),
}
}

Expand Down Expand Up @@ -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<u8> {
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)]
Expand Down
Loading