From c298300a275d028c086a35d52e8f7cfa042bfbca Mon Sep 17 00:00:00 2001 From: louis-e <44675238+louis-e@users.noreply.github.com> Date: Mon, 21 Jul 2025 22:19:28 +0200 Subject: [PATCH] Minor improvements to water area generation --- src/data_processing.rs | 4 +- src/element_processing/water_areas.rs | 104 ++++++++++++++++++++------ 2 files changed, 83 insertions(+), 25 deletions(-) diff --git a/src/data_processing.rs b/src/data_processing.rs index a6c3651..ac41a36 100644 --- a/src/data_processing.rs +++ b/src/data_processing.rs @@ -106,7 +106,9 @@ pub fn generate_world( ProcessedElement::Relation(rel) => { if rel.tags.contains_key("building") || rel.tags.contains_key("building:part") { buildings::generate_building_from_relation(&mut editor, rel, args); - } else if rel.tags.contains_key("water") { + } else if rel.tags.contains_key("water") + || rel.tags.get("natural") == Some(&"water".to_string()) + { water_areas::generate_water_areas(&mut editor, rel); } else if rel.tags.contains_key("natural") { natural::generate_natural_from_relation(&mut editor, rel, args); diff --git a/src/element_processing/water_areas.rs b/src/element_processing/water_areas.rs index 708c7a0..ff6c06b 100644 --- a/src/element_processing/water_areas.rs +++ b/src/element_processing/water_areas.rs @@ -11,10 +11,19 @@ use crate::{ pub fn generate_water_areas(editor: &mut WorldEditor, element: &ProcessedRelation) { let start_time = Instant::now(); - if !element.tags.contains_key("water") { + // Check if this is a water relation (either with water tag or natural=water) + let is_water = element.tags.contains_key("water") + || element.tags.get("natural") == Some(&"water".to_string()); + + if !is_water { return; } + println!( + "Processing water relation ID: {} with tags: {:?}", + element.id, element.tags + ); + // Don't handle water below layer 0 if let Some(layer) = element.tags.get("layer") { if layer.parse::().map(|x| x < 0).unwrap_or(false) { @@ -32,30 +41,77 @@ pub fn generate_water_areas(editor: &mut WorldEditor, element: &ProcessedRelatio } } - merge_loopy_loops(&mut outers); - if !verify_loopy_loops(&outers) { - return; + // Process each outer polygon individually + for (i, outer_nodes) in outers.iter().enumerate() { + println!( + "Processing outer polygon {} of {} for relation {}", + i + 1, + outers.len(), + element.id + ); + + let mut individual_outers = vec![outer_nodes.clone()]; + + merge_loopy_loops(&mut individual_outers); + if !verify_loopy_loops(&individual_outers) { + println!( + "Skipping invalid outer polygon {} for relation {}", + i + 1, + element.id + ); + continue; // Skip this outer if it's not valid + } + + merge_loopy_loops(&mut inners); + if !verify_loopy_loops(&inners) { + // If inners are invalid, process outer without inners + let empty_inners: Vec> = vec![]; + let mut temp_inners = empty_inners; + merge_loopy_loops(&mut temp_inners); + + let (min_x, min_z) = editor.get_min_coords(); + let (max_x, max_z) = editor.get_max_coords(); + let individual_outers_xz: Vec> = individual_outers + .iter() + .map(|x| x.iter().map(|y| y.xz()).collect::>()) + .collect(); + let empty_inners_xz: Vec> = vec![]; + + inverse_floodfill( + min_x, + min_z, + max_x, + max_z, + individual_outers_xz, + empty_inners_xz, + editor, + start_time, + ); + continue; + } + + let (min_x, min_z) = editor.get_min_coords(); + let (max_x, max_z) = editor.get_max_coords(); + let individual_outers_xz: Vec> = individual_outers + .iter() + .map(|x| x.iter().map(|y| y.xz()).collect::>()) + .collect(); + let inners_xz: Vec> = inners + .iter() + .map(|x| x.iter().map(|y| y.xz()).collect::>()) + .collect(); + + inverse_floodfill( + min_x, + min_z, + max_x, + max_z, + individual_outers_xz, + inners_xz, + editor, + start_time, + ); } - - merge_loopy_loops(&mut inners); - if !verify_loopy_loops(&inners) { - return; - } - - let (min_x, min_z) = editor.get_min_coords(); - let (max_x, max_z) = editor.get_max_coords(); - let outers: Vec> = outers - .iter() - .map(|x| x.iter().map(|y| y.xz()).collect::>()) - .collect(); - let inners: Vec> = inners - .iter() - .map(|x| x.iter().map(|y| y.xz()).collect::>()) - .collect(); - - inverse_floodfill( - min_x, min_z, max_x, max_z, outers, inners, editor, start_time, - ); } // Merges ways that share nodes into full loops