use nexrad_model::data::{MomentData, Product, Radial, RadialStatus};
use nexrad_render::{render_radials, RenderOptions};
fn create_test_radial(azimuth_degrees: f32, reflectivity_value: u8) -> Radial {
let gate_count = 100;
let first_gate_range_m = 2000; let gate_interval_m = 250; let scale = 2.0;
let offset = 66.0;
let values = vec![reflectivity_value; gate_count as usize];
let moment_data = MomentData::from_fixed_point(
gate_count,
first_gate_range_m,
gate_interval_m,
8, scale,
offset,
values,
);
Radial::new(
0, 0, azimuth_degrees, 1.0, RadialStatus::IntermediateRadialData,
1, 0.5, Some(moment_data), None, None, None, None, None, None, )
}
fn create_partial_sweep(
start_az: f32,
end_az: f32,
spacing: f32,
reflectivity_value: u8,
) -> Vec<Radial> {
let mut radials = Vec::new();
let mut az = start_az;
while az < end_az {
radials.push(create_test_radial(az, reflectivity_value));
az += spacing;
}
radials
}
fn get_pixel(image: &nexrad_render::RgbaImage, x: u32, y: u32) -> [u8; 4] {
let pixel = image.get_pixel(x, y);
[pixel[0], pixel[1], pixel[2], pixel[3]]
}
fn pixel_to_azimuth(x: u32, y: u32, width: u32, height: u32) -> f32 {
let center_x = width as f32 / 2.0;
let center_y = height as f32 / 2.0;
let dx = x as f32 - center_x;
let dy = y as f32 - center_y;
let azimuth_rad = dx.atan2(-dy);
(azimuth_rad.to_degrees() + 360.0) % 360.0
}
#[test]
fn test_partial_sweep_leaves_gaps_as_background() {
let radials = create_partial_sweep(0.0, 90.0, 1.0, 100);
let background = [0, 0, 0, 255]; let options = RenderOptions::new(200, 200).with_background(background);
let image = render_radials(
&radials,
Product::Reflectivity,
&nexrad_render::nws_reflectivity_scale(),
&options,
)
.unwrap();
let covered_pixel = get_pixel(&image, 130, 70);
let covered_azimuth = pixel_to_azimuth(130, 70, 200, 200);
assert!(
covered_azimuth >= 0.0 && covered_azimuth <= 90.0,
"Test setup error: covered pixel azimuth {} should be in [0, 90]",
covered_azimuth
);
assert_ne!(
covered_pixel, background,
"Pixel in covered azimuth range should have radar data, not background"
);
let uncovered_pixel = get_pixel(&image, 100, 130);
let uncovered_azimuth = pixel_to_azimuth(100, 130, 200, 200);
assert!(
uncovered_azimuth >= 135.0 && uncovered_azimuth <= 225.0,
"Test setup error: uncovered pixel azimuth {} should be around 180°",
uncovered_azimuth
);
assert_eq!(
uncovered_pixel, background,
"Pixel at azimuth {:.1}° should be background since no radials cover 90°-360°. \
Got {:?} instead of {:?}. This indicates the bug where partial sweeps \
incorrectly fill uncovered regions.",
uncovered_azimuth, uncovered_pixel, background
);
}
#[test]
fn test_full_sweep_covers_all_azimuths() {
let radials = create_partial_sweep(0.0, 360.0, 1.0, 100);
let background = [0, 0, 0, 255];
let options = RenderOptions::new(200, 200).with_background(background);
let image = render_radials(
&radials,
Product::Reflectivity,
&nexrad_render::nws_reflectivity_scale(),
&options,
)
.unwrap();
let test_points = [
(130, 70), (130, 130), (70, 130), (70, 70), ];
for (x, y) in test_points {
let pixel = get_pixel(&image, x, y);
let azimuth = pixel_to_azimuth(x, y, 200, 200);
assert_ne!(
pixel, background,
"Full sweep: pixel at azimuth {:.1}° should have data",
azimuth
);
}
}
#[test]
fn test_partial_sweep_gap_detection_multiple_sectors() {
let radials = create_partial_sweep(45.0, 135.0, 1.0, 100);
let background = [128, 128, 128, 255]; let options = RenderOptions::new(200, 200).with_background(background);
let image = render_radials(
&radials,
Product::Reflectivity,
&nexrad_render::nws_reflectivity_scale(),
&options,
)
.unwrap();
let covered_pixel = get_pixel(&image, 130, 100);
assert_ne!(
covered_pixel, background,
"Pixel in covered azimuth (east) should have radar data"
);
let uncovered_pixel = get_pixel(&image, 70, 100);
assert_eq!(
uncovered_pixel, background,
"Pixel in uncovered azimuth (west) should be background"
);
let north_pixel = get_pixel(&image, 100, 70);
assert_eq!(
north_pixel, background,
"Pixel in uncovered azimuth (north) should be background"
);
}