Minor improvements to water area generation

This commit is contained in:
louis-e
2025-07-21 22:19:28 +02:00
parent 33097aa302
commit c298300a27
2 changed files with 83 additions and 25 deletions

View File

@@ -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);

View File

@@ -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::<i32>().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<ProcessedNode>> = 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<Vec<XZPoint>> = individual_outers
.iter()
.map(|x| x.iter().map(|y| y.xz()).collect::<Vec<_>>())
.collect();
let empty_inners_xz: Vec<Vec<XZPoint>> = 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<Vec<XZPoint>> = individual_outers
.iter()
.map(|x| x.iter().map(|y| y.xz()).collect::<Vec<_>>())
.collect();
let inners_xz: Vec<Vec<XZPoint>> = inners
.iter()
.map(|x| x.iter().map(|y| y.xz()).collect::<Vec<_>>())
.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<Vec<XZPoint>> = outers
.iter()
.map(|x| x.iter().map(|y| y.xz()).collect::<Vec<_>>())
.collect();
let inners: Vec<Vec<XZPoint>> = inners
.iter()
.map(|x| x.iter().map(|y| y.xz()).collect::<Vec<_>>())
.collect();
inverse_floodfill(
min_x, min_z, max_x, max_z, outers, inners, editor, start_time,
);
}
// Merges ways that share nodes into full loops