mirror of
https://github.com/louis-e/arnis.git
synced 2025-12-28 16:58:04 -05:00
Compare commits
4 Commits
main
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bcec3dcc0 | ||
|
|
e86af9e006 | ||
|
|
7575141837 | ||
|
|
eb288e9a03 |
@@ -84,8 +84,9 @@ pub fn fetch_elevation_data(
|
||||
let tiles: Vec<(u32, u32)> = get_tile_coordinates(bbox, zoom);
|
||||
|
||||
// Match grid dimensions with Minecraft world size
|
||||
let grid_width: usize = scale_factor_x as usize;
|
||||
let grid_height: usize = scale_factor_z as usize;
|
||||
// Ensure minimum grid size of 1 to prevent division by zero and indexing errors
|
||||
let grid_width: usize = (scale_factor_x as usize).max(1);
|
||||
let grid_height: usize = (scale_factor_z as usize).max(1);
|
||||
|
||||
// Initialize height grid with proper dimensions
|
||||
let mut height_grid: Vec<Vec<f64>> = vec![vec![f64::NAN; grid_width]; grid_height];
|
||||
@@ -381,6 +382,11 @@ fn get_tile_coordinates(bbox: &LLBBox, zoom: u8) -> Vec<(u32, u32)> {
|
||||
}
|
||||
|
||||
fn apply_gaussian_blur(heights: &[Vec<f64>], sigma: f64) -> Vec<Vec<f64>> {
|
||||
// Guard against empty input
|
||||
if heights.is_empty() || heights[0].is_empty() {
|
||||
return heights.to_owned();
|
||||
}
|
||||
|
||||
let kernel_size: usize = (sigma * 3.0).ceil() as usize * 2 + 1;
|
||||
let kernel: Vec<f64> = create_gaussian_kernel(kernel_size, sigma);
|
||||
|
||||
@@ -450,6 +456,11 @@ fn create_gaussian_kernel(size: usize, sigma: f64) -> Vec<f64> {
|
||||
}
|
||||
|
||||
fn fill_nan_values(height_grid: &mut [Vec<f64>]) {
|
||||
// Guard against empty grid
|
||||
if height_grid.is_empty() || height_grid[0].is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let height: usize = height_grid.len();
|
||||
let width: usize = height_grid[0].len();
|
||||
|
||||
@@ -490,6 +501,11 @@ fn fill_nan_values(height_grid: &mut [Vec<f64>]) {
|
||||
}
|
||||
|
||||
fn filter_elevation_outliers(height_grid: &mut [Vec<f64>]) {
|
||||
// Guard against empty grid
|
||||
if height_grid.is_empty() || height_grid[0].is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let height = height_grid.len();
|
||||
let width = height_grid[0].len();
|
||||
|
||||
@@ -604,4 +620,46 @@ mod tests {
|
||||
.unwrap()
|
||||
.contains("image"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_grid_handling() {
|
||||
// Test that empty grids don't cause panics
|
||||
let empty_grid: Vec<Vec<f64>> = vec![];
|
||||
let result = apply_gaussian_blur(&empty_grid, 5.0);
|
||||
assert!(result.is_empty());
|
||||
|
||||
// Test grid with empty rows
|
||||
let grid_with_empty_rows: Vec<Vec<f64>> = vec![vec![]];
|
||||
let result = apply_gaussian_blur(&grid_with_empty_rows, 5.0);
|
||||
assert_eq!(result.len(), 1);
|
||||
assert!(result[0].is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_nan_values_empty_grid() {
|
||||
// Test that empty grids don't cause panics
|
||||
let mut empty_grid: Vec<Vec<f64>> = vec![];
|
||||
fill_nan_values(&mut empty_grid);
|
||||
assert!(empty_grid.is_empty());
|
||||
|
||||
// Test grid with empty rows
|
||||
let mut grid_with_empty_rows: Vec<Vec<f64>> = vec![vec![]];
|
||||
fill_nan_values(&mut grid_with_empty_rows);
|
||||
assert_eq!(grid_with_empty_rows.len(), 1);
|
||||
assert!(grid_with_empty_rows[0].is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_outliers_empty_grid() {
|
||||
// Test that empty grids don't cause panics
|
||||
let mut empty_grid: Vec<Vec<f64>> = vec![];
|
||||
filter_elevation_outliers(&mut empty_grid);
|
||||
assert!(empty_grid.is_empty());
|
||||
|
||||
// Test grid with empty rows
|
||||
let mut grid_with_empty_rows: Vec<Vec<f64>> = vec![vec![]];
|
||||
filter_elevation_outliers(&mut grid_with_empty_rows);
|
||||
assert_eq!(grid_with_empty_rows.len(), 1);
|
||||
assert!(grid_with_empty_rows[0].is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,10 @@ impl Ground {
|
||||
/// Converts game coordinates to elevation data coordinates
|
||||
#[inline(always)]
|
||||
fn get_data_coordinates(&self, coord: XZPoint, data: &ElevationData) -> (f64, f64) {
|
||||
// Guard against division by zero for edge cases
|
||||
if data.width == 0 || data.height == 0 {
|
||||
return (0.0, 0.0);
|
||||
}
|
||||
let x_ratio: f64 = coord.x as f64 / data.width as f64;
|
||||
let z_ratio: f64 = coord.z as f64 / data.height as f64;
|
||||
(x_ratio.clamp(0.0, 1.0), z_ratio.clamp(0.0, 1.0))
|
||||
@@ -83,8 +87,17 @@ impl Ground {
|
||||
/// Interpolates height value from the elevation grid
|
||||
#[inline(always)]
|
||||
fn interpolate_height(&self, x_ratio: f64, z_ratio: f64, data: &ElevationData) -> i32 {
|
||||
// Guard against out of bounds access
|
||||
if data.width == 0 || data.height == 0 || data.heights.is_empty() {
|
||||
return self.ground_level;
|
||||
}
|
||||
let x: usize = ((x_ratio * (data.width - 1) as f64).round() as usize).min(data.width - 1);
|
||||
let z: usize = ((z_ratio * (data.height - 1) as f64).round() as usize).min(data.height - 1);
|
||||
|
||||
// Additional safety check for row length
|
||||
if z >= data.heights.len() || x >= data.heights[z].len() {
|
||||
return self.ground_level;
|
||||
}
|
||||
data.heights[z][x]
|
||||
}
|
||||
|
||||
@@ -138,6 +151,80 @@ impl Ground {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_ground_level_with_zero_dimensions() {
|
||||
// Test that zero-dimension elevation data doesn't cause panic
|
||||
let elevation_data = ElevationData {
|
||||
heights: vec![],
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
|
||||
let ground = Ground {
|
||||
elevation_enabled: true,
|
||||
ground_level: 64,
|
||||
elevation_data: Some(elevation_data),
|
||||
};
|
||||
|
||||
// This should not panic and should return ground_level
|
||||
let level = ground.level(XZPoint::new(10, 10));
|
||||
assert_eq!(level, 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ground_level_with_one_dimension_zero() {
|
||||
// Test that partial zero dimensions don't cause panic
|
||||
let elevation_data = ElevationData {
|
||||
heights: vec![vec![100]],
|
||||
width: 0,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
let ground = Ground {
|
||||
elevation_enabled: true,
|
||||
ground_level: 64,
|
||||
elevation_data: Some(elevation_data),
|
||||
};
|
||||
|
||||
// This should not panic and should return ground_level
|
||||
let level = ground.level(XZPoint::new(5, 5));
|
||||
assert_eq!(level, 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ground_level_normal_case() {
|
||||
// Test that normal elevation data works correctly
|
||||
let elevation_data = ElevationData {
|
||||
heights: vec![vec![80, 85], vec![90, 95]],
|
||||
width: 2,
|
||||
height: 2,
|
||||
};
|
||||
|
||||
let ground = Ground {
|
||||
elevation_enabled: true,
|
||||
ground_level: 64,
|
||||
elevation_data: Some(elevation_data),
|
||||
};
|
||||
|
||||
// This should work normally
|
||||
let level = ground.level(XZPoint::new(0, 0));
|
||||
assert!(level >= 64); // Should be one of the elevation values
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ground_level_disabled() {
|
||||
// Test that disabled elevation returns ground_level
|
||||
let ground = Ground::new_flat(70);
|
||||
|
||||
let level = ground.level(XZPoint::new(100, 100));
|
||||
assert_eq!(level, 70);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_ground_data(args: &Args) -> Ground {
|
||||
if args.terrain {
|
||||
println!("{} Fetching elevation...", "[3/7]".bold());
|
||||
|
||||
Reference in New Issue
Block a user