use super::contours;
fn segments(line: &super::Contour) -> Vec<((f64, f64), (f64, f64))> {
assert!(line.x.len().is_multiple_of(3), "two endpoints plus a joint");
line.x
.chunks(3)
.zip(line.y.chunks(3))
.map(|(x, y)| {
assert!(x[2].is_nan() && y[2].is_nan());
((x[0], y[0]), (x[1], y[1]))
})
.collect()
}
#[test]
fn a_vertical_gradient_yields_one_straight_line_at_the_interpolated_row() {
let values: Vec<f64> = (0..12).map(|i| (i / 3) as f64).collect();
let lines = contours(&values, 3, &[1.5]);
let segs = segments(&lines[0]);
assert_eq!(segs.len(), 2, "one segment per block column");
for ((_, y0), (_, y1)) in segs {
assert_eq!(y0, 1.5);
assert_eq!(y1, 1.5);
}
}
#[test]
fn a_peak_produces_a_closed_ring() {
let mut values = vec![0.0; 25];
values[2 * 5 + 2] = 4.0;
let lines = contours(&values, 5, &[1.0]);
let segs = segments(&lines[0]);
assert!(!segs.is_empty());
let mut counts = std::collections::HashMap::new();
for (a, b) in segs {
for point in [a, b] {
*counts.entry(format!("{point:?}")).or_insert(0) += 1;
}
}
assert!(counts.values().all(|&count| count == 2), "ring is closed");
}
#[test]
fn levels_outside_the_data_range_trace_nothing() {
let values: Vec<f64> = (0..16).map(f64::from).collect();
for line in contours(&values, 4, &[-1.0, 99.0]) {
assert!(line.x.is_empty());
}
}
#[test]
fn nan_values_leave_a_gap() {
let values: Vec<f64> = (0..12).map(|i| (i / 3) as f64).collect();
let full = segments(&contours(&values, 3, &[1.5])[0]).len();
let mut holed = values;
holed[2 * 3 + 1] = f64::NAN; let after = segments(&contours(&holed, 3, &[1.5])[0]).len();
assert!(after < full);
}
#[test]
fn a_saddle_resolves_by_the_center_average() {
let values = [1.0, 0.0, 0.0, 1.0];
let segs = segments(&contours(&values, 2, &[0.6])[0]);
assert_eq!(segs.len(), 2);
let segs = segments(&contours(&values, 2, &[0.4])[0]);
assert_eq!(segs.len(), 2);
}