Skip to content

Commit

Permalink
Merge pull request #241 from louis-e/data-retrieval-error-handling
Browse files Browse the repository at this point in the history
Improved error handling and fixed some minor bugs
  • Loading branch information
louis-e authored Jan 7, 2025
2 parents 486541b + 9b33ed1 commit cc5e691
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 69 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,15 @@ Make sure to teleport to the generation starting point (/tp 0 0 0). If there is
Feel free to choose an item from the To-Do or Known Bugs list, or bring your own idea to the table. Bug reports shall be raised as a Github issue. Contributions are highly welcome and appreciated!
- [ ] Fix compilation for Linux
- [ ] Rotate maps (https://github.com/louis-e/arnis/issues/97)
- [ ] Fix coastal cities generation duration time (water_areas.rs)
- [ ] Add street names as signs
- [ ] Add support for older Minecraft versions (<=1.16.5) (https://github.com/louis-e/arnis/issues/124, https://github.com/louis-e/arnis/issues/137)
- [ ] Mapping real coordinates to Minecraft coordinates (https://github.com/louis-e/arnis/issues/29)
- [ ] Add interior to buildings
- [ ] Implement house roof types
- [ ] Evaluate and implement elevation (https://github.com/louis-e/arnis/issues/66)
- [ ] Add support for inner attribute in multipolygons and multipolygon elements other than buildings
- [ ] Fix Github Action Workflow for releasing Linux & MacOS Binary
- [ ] Fix Github Action Workflow for releasing MacOS Binary
- [ ] Evaluate and implement faster region saving
- [ ] Refactor bridges implementation
- [ ] Refactor railway implementation
Expand Down
4 changes: 2 additions & 2 deletions gui-src/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ function normalizeLongitude(lon) {
return ((lon + 180) % 360 + 360) % 360 - 180;
}

const threshold1 = 35000000.00;
const threshold2 = 50000000.00;
const threshold1 = 30000000.00;
const threshold2 = 45000000.00;
let selectedBBox = "";

// Function to handle incoming bbox data
Expand Down
2 changes: 1 addition & 1 deletion src/data_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn generate_world(
} else if way.tags.contains_key("waterway") {
waterways::generate_waterways(&mut editor, way, ground_level);
} else if way.tags.contains_key("bridge") {
bridges::generate_bridges(&mut editor, way, ground_level);
//bridges::generate_bridges(&mut editor, way, ground_level); // TODO FIX
} else if way.tags.contains_key("railway") {
railways::generate_railways(&mut editor, way, ground_level);
} else if way.tags.contains_key("aeroway") || way.tags.contains_key("area:aeroway")
Expand Down
77 changes: 24 additions & 53 deletions src/element_processing/bridges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,38 @@ use crate::bresenham::bresenham_line;
use crate::osm_parser::ProcessedWay;
use crate::world_editor::WorldEditor;

// TODO FIX
#[allow(dead_code)]
pub fn generate_bridges(editor: &mut WorldEditor, element: &ProcessedWay, ground_level: i32) {
if let Some(_bridge_type) = element.tags.get("bridge") {
let bridge_height: i32 = element
.tags
.get("layer")
.and_then(|layer: &String| layer.parse::<i32>().ok())
.unwrap_or(1); // Default height if not specified

// Calculate the total length of the bridge
let total_steps: usize = element
.nodes
.windows(2)
.map(|nodes: &[crate::osm_parser::ProcessedNode]| {
let x1: i32 = nodes[0].x;
let z1: i32 = nodes[0].z;
let x2: i32 = nodes[1].x;
let z2: i32 = nodes[1].z;

bresenham_line(x1, ground_level, z1, x2, ground_level, z2).len()
})
.sum();

let half_steps: usize = total_steps / 2; // Calculate midpoint for descending after rising
let mut current_step: usize = 0;
let bridge_height = 3; // Fixed height

for i in 1..element.nodes.len() {
let prev: &crate::osm_parser::ProcessedNode = &element.nodes[i - 1];
let x1: i32 = prev.x;
let z1: i32 = prev.z;

let cur: &crate::osm_parser::ProcessedNode = &element.nodes[i];
let x2: i32 = cur.x;
let z2: i32 = cur.z;

// Generate the line of coordinates between the two nodes
let bresenham_points: Vec<(i32, i32, i32)> =
bresenham_line(x1, ground_level, z1, x2, ground_level, z2);

for (bx, _, bz) in bresenham_points {
// Calculate the current height of the bridge
let current_height: i32 = if current_step <= half_steps {
ground_level + bridge_height + current_step as i32 / 5 // Rise for the first half
let prev = &element.nodes[i - 1];
let cur = &element.nodes[i];
let points = bresenham_line(prev.x, ground_level, prev.z, cur.x, ground_level, cur.z);

let total_length = points.len();
let ramp_length = 6; // Length of ramp at each end

for (idx, (x, _, z)) in points.iter().enumerate() {
let height = if idx < ramp_length {
// Start ramp (rising)
(idx * bridge_height) / ramp_length
} else if idx >= total_length - ramp_length {
// End ramp (descending)
((total_length - idx) * bridge_height) / ramp_length
} else {
ground_level + bridge_height + (half_steps as i32 / 5)
- ((current_step - half_steps) as i32 / 5) // Descend for the second half
// Middle section (constant height)
bridge_height
};

// Set bridge blocks
editor.set_block(LIGHT_GRAY_CONCRETE, bx, current_height, bz, None, None);
for (offset_x, offset_z) in &[(-1, -1), (1, -1), (1, 1), (-1, 1)] {
editor.set_block(
LIGHT_GRAY_CONCRETE,
bx + offset_x,
current_height,
bz + offset_z,
None,
None,
);
}
let bridge_y = ground_level + height as i32;

current_step += 1;
// Place bridge blocks
for dx in -2..=2 {
editor.set_block(LIGHT_GRAY_CONCRETE, *x + dx, bridge_y, *z, None, None);
}
}
}
}
Expand Down
22 changes: 21 additions & 1 deletion src/element_processing/water_areas.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use geo::{Contains, Intersects, LineString, Point, Polygon, Rect};
use std::time::Instant;

use crate::{
block_definitions::WATER,
Expand All @@ -11,6 +12,8 @@ pub fn generate_water_areas(
element: &ProcessedRelation,
ground_level: i32,
) {
let start_time = Instant::now();

if !element.tags.contains_key("water") {
return;
}
Expand Down Expand Up @@ -60,7 +63,15 @@ pub fn generate_water_areas(
})
.collect();

inverse_floodfill(max_x, max_z, outers, inners, editor, ground_level);
inverse_floodfill(
max_x,
max_z,
outers,
inners,
editor,
ground_level,
start_time,
);
}

// Merges ways that share nodes into full loops
Expand Down Expand Up @@ -157,6 +168,7 @@ fn inverse_floodfill(
inners: Vec<Vec<(f64, f64)>>,
editor: &mut WorldEditor,
ground_level: i32,
start_time: Instant,
) {
let min_x: i32 = 0;
let min_z: i32 = 0;
Expand All @@ -178,6 +190,7 @@ fn inverse_floodfill(
&outers,
&inners,
editor,
start_time,
);
}

Expand All @@ -188,7 +201,13 @@ fn inverse_floodfill_recursive(
outers: &[Polygon],
inners: &[Polygon],
editor: &mut WorldEditor,
start_time: Instant,
) {
// Check if we've exceeded 25 seconds
if start_time.elapsed().as_secs() > 25 {
println!("Water area generation exceeded 25 seconds, continuing anyway");
}

const ITERATIVE_THRES: i32 = 10_000;

if min.0 > max.0 || min.1 > max.1 {
Expand Down Expand Up @@ -253,6 +272,7 @@ fn inverse_floodfill_recursive(
&outers_intersects,
&inners_intersects,
editor,
start_time,
);
}
}
Expand Down
24 changes: 13 additions & 11 deletions src/retrieve_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,21 @@ use std::time::Duration;
/// Function to download data using reqwest
fn download_with_reqwest(url: &str, query: &str) -> Result<String, Box<dyn std::error::Error>> {
let client: Client = ClientBuilder::new()
.timeout(Duration::from_secs(1800))
.timeout(Duration::from_secs(360))
.build()?;

let response: Result<reqwest::blocking::Response, reqwest::Error> =
client.get(url).query(&[("data", query)]).send();

match response {
Ok(resp) => {
emit_gui_progress_update(3.0, "Downloading data...");
if resp.status().is_success() {
Ok(resp.text()?)
let text = resp.text()?;
if text.is_empty() {
return Err("Error! Received invalid from server".into());
}
Ok(text)
} else {
Err(format!("Error! Received response code: {}", resp.status()).into())
}
Expand All @@ -36,15 +41,11 @@ fn download_with_reqwest(url: &str, query: &str) -> Result<String, Box<dyn std::
);
emit_gui_error("Request timed out. Try selecting a smaller area.");
} else {
eprintln!("{}", format!("Error! {}", e).red().bold());
emit_gui_error(&e.to_string());
}

if !is_running_with_gui() {
std::process::exit(1);
} else {
Ok("".to_string())
eprintln!("{}", format!("Error! {:.52}", e).red().bold());
emit_gui_error(&format!("{:.52}", e.to_string()));
}
// Always propagate errors
Err(e.into())
}
}
}
Expand Down Expand Up @@ -94,12 +95,13 @@ pub fn fetch_data(
"https://z.overpass-api.de/api/interpreter",
"https://overpass.kumi.systems/api/interpreter",
"https://overpass.private.coffee/api/interpreter",
"https://overpass.osm.ch/api/interpreter",
];
let url: &&str = api_servers.choose(&mut rand::thread_rng()).unwrap();

// Generate Overpass API query for bounding box
let query: String = format!(
r#"[out:json][timeout:1800][bbox:{},{},{},{}];
r#"[out:json][timeout:360][bbox:{},{},{},{}];
(
nwr["building"];
nwr["highway"];
Expand Down

0 comments on commit cc5e691

Please sign in to comment.