use super::*;
use vector_traits::glam::{Vec3, Vec3A};
fn always_valid(_n1: Vec3A, _l1: f32, _n2: Vec3A, _l2: f32) -> bool {
true
}
fn always_invalid(_n1: Vec3A, _l1: f32, _n2: Vec3A, _l2: f32) -> bool {
false
}
fn create_fan_vertices(count: usize) -> impl ExactSizeIterator<Item = Vec3A> {
let v: Vec<_> = (0..count)
.map(|i| {
let angle = (i as f32) * std::f32::consts::PI * 2.0 / (count as f32);
Vec3A::new(angle.cos(), angle.sin(), 0.0_f32)
})
.collect();
v.into_iter().enumerate().map(|(i, v)| {
let va: [f32; 3] = v.into();
println!("giving V{i}: {:?}", va);
v
})
}
#[test]
fn test_skip_leading_basic() {
let vertices = create_fan_vertices(5); let center = Vec3A::ZERO;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices,
center,
1, 0, always_valid,
);
assert!(result);
}
#[test]
fn test_skip_trailing_basic() {
let vertices = create_fan_vertices(5); let center = Vec3A::ZERO;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices,
center,
1, 1, always_valid,
);
assert!(result);
}
#[test]
fn test_skip_both_ends() {
let vertices = create_fan_vertices(6); let center = Vec3A::ZERO;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices,
center,
2, 2, always_valid,
);
assert!(result);
}
#[test]
fn test_skip_leaves_no_pairs() {
let vertices = create_fan_vertices(4); let center = Vec3A::ZERO;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices,
center,
2, 1, always_invalid, );
assert!(result);
}
#[test]
fn test_skip_excessive() {
let vertices = create_fan_vertices(4); let center = Vec3A::ZERO;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices,
center,
10, 10, always_invalid,
);
assert!(result); }
#[test]
fn test_minimum_valid_fan() {
let vertices = [
Vec3A::new(1.0, 0.0, 0.0),
Vec3A::new(0.0, 1.0, 0.0),
Vec3A::new(-1.0, 0.0, 0.0),
];
let center = Vec3A::ZERO;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.iter().copied(),
center,
1, 0, always_valid,
);
assert!(result);
}
#[test]
fn test_validator_receives_correct_normals() {
let vertices: Vec<Vec3A> = vec![
[1.0, 0.0, 0.0].into(),
[0.0, 1.0, 0.0].into(),
[-1.0, 0.0, 0.0].into(),
[0.0, -1.0, 0.0].into(),
];
let center = Vec3A::ZERO;
let mut call_count = 0;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.into_iter(),
center,
1,
0,
|n1, len1, n2, len2| {
call_count += 1;
assert!(
n1.z < 0.0,
"First normal should point down n1:{:?} n2:{:?}",
n1,
n2
);
assert!(
n2.z < 0.0,
"Second normal should point down n1:{:?} n2:{:?}",
n1,
n2
);
assert!(len1 > 0.0, "First length should be positive");
assert!(len2 > 0.0, "Second length should be positive");
true
},
);
assert!(result);
assert_eq!(call_count, 2, "call_count:{call_count} expected 2"); }
#[test]
fn test_valence_4_sub_h1() {
let vertices: Vec<Vec3A> = vec![
[1.0, 0.0, 0.0].into(),
[0.0, 1.0, 0.0].into(),
[-1.0, 0.0, 0.0].into(),
[0.0, -1.0, 0.0].into(),
];
let center = Vec3A::ZERO;
let mut call_count = 0;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.into_iter(),
center,
1,
0,
|_, _, _, _| {
call_count += 1;
true
},
)
);
assert_eq!(call_count, 2, "call_count:{call_count} expected 2"); }
#[test]
fn test_valence_4_sub_h1_t1() {
let vertices: Vec<Vec3A> = vec![
[1.0, 0.0, 0.0].into(),
[0.0, 1.0, 0.0].into(),
[-1.0, 0.0, 0.0].into(),
[0.0, -1.0, 0.0].into(),
];
let center = Vec3A::ZERO;
let mut call_count = 0;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.into_iter(),
center,
1,
1,
|_, _, _, _| {
call_count += 1;
true
},
)
);
assert_eq!(call_count, 1, "call_count:{call_count} expected 1"); }
#[test]
fn test_valence_4_sub_h2_t1() {
let vertices: Vec<Vec3A> = vec![
[1.0, 0.0, 0.0].into(),
[0.0, 1.0, 0.0].into(),
[-1.0, 0.0, 0.0].into(),
[0.0, -1.0, 0.0].into(),
];
let center = Vec3A::ZERO;
let mut call_count = 0;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.into_iter(),
center,
2,
1,
|_, _, _, _| {
call_count += 1;
true
},
)
);
assert_eq!(call_count, 0, "call_count:{call_count} expected 0"); }
#[test]
fn test_valence_3_sub_h1() {
let vertices: Vec<Vec3A> = vec![
[1.0, 0.0, 0.0].into(),
[0.0, 1.0, 0.0].into(),
[-1.0, 0.0, 0.0].into(),
];
let center = Vec3A::ZERO;
let mut call_count = 0;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.into_iter(),
center,
1,
0,
|_, _, _, _| {
call_count += 1;
true
},
)
);
assert_eq!(call_count, 1, "call_count:{call_count} expected 1"); }
#[test]
fn test_validator_failure_propagates() {
let vertices = create_fan_vertices(5);
let center = Vec3A::ZERO;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices,
center,
1,
0,
always_invalid,
);
assert!(!result);
}
#[test]
fn test_validator_early_exit() {
let vertices = create_fan_vertices(10); let center = Vec3A::ZERO;
let mut call_count = 0;
let result = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices,
center,
1,
0,
|_, _, _, _| {
call_count += 1;
call_count < 3 },
);
assert!(!result);
assert_eq!(call_count, 3); }
#[test]
fn test_skip_trailing_boundary() {
let vertices = create_fan_vertices(6); assert_eq!(vertices.len(), 6);
let center = Vec3A::ZERO;
let mut pair_count = 0;
let _ = IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.into_iter(),
center,
1, 3, |_, _, _, _| {
pair_count += 1;
true
},
);
assert_eq!(pair_count, 1);
}
fn test_skip_mechanics(
vertex_count: usize,
skip_leading: usize,
skip_trailing: usize,
expected_pairs: usize,
) {
let vertices = create_fan_vertices(vertex_count);
assert_eq!(vertices.len(), vertex_count);
let center = Vec3A::ZERO;
let mut actual_pairs = 0;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.into_iter(),
center,
skip_leading,
skip_trailing,
|_, _, _, _| {
actual_pairs += 1;
true
},
)
);
assert_eq!(
actual_pairs,
expected_pairs,
"vertex_count={vertex_count}, skip_leading={skip_leading}, skip_trailing={skip_trailing}, \
total_triangles={vertex_count}, checked_triangles={}, expected_pairs={expected_pairs} but instead got {actual_pairs} pairs",
vertex_count
.saturating_sub(skip_leading)
.saturating_sub(skip_trailing),
);
}
#[test]
fn test_skip_mechanics_permutations() {
let test_cases = vec![
(4, 1, 0, 2), (4, 1, 1, 1), (4, 2, 0, 1), (4, 1, 2, 0), (4, 2, 1, 0), (5, 1, 0, 3), (5, 1, 1, 2), (5, 2, 1, 1), (5, 1, 3, 0), (5, 3, 1, 0), (6, 1, 0, 4), (6, 1, 3, 1), (6, 2, 2, 1), (6, 1, 4, 0), (6, 3, 2, 0), (7, 1, 0, 5), (7, 1, 2, 3), (7, 2, 2, 2), (7, 3, 2, 1), (7, 1, 5, 0), (4, 3, 0, 0), (4, 1, 3, 0), (5, 2, 2, 0), (3, 1, 0, 1), (3, 1, 1, 0), (3, 2, 0, 0), ];
for (vertex_count, skip_leading, skip_trailing, expected_pairs) in test_cases {
println!();
println!(
"evaluating vertex_count:{vertex_count}, skip_leading:{skip_leading}, skip_trailing:{skip_trailing} expected:{expected_pairs}):"
);
test_skip_mechanics(vertex_count, skip_leading, skip_trailing, expected_pairs);
}
}
#[test]
fn test_skip_excessive_cases() {
let test_cases = vec![
(4, 4, 0, 0), (4, 2, 2, 0), (4, 3, 1, 0), (5, 5, 0, 0), (5, 3, 3, 0), (6, 10, 0, 0), (6, 1, 10, 0), ];
for (vertex_count, skip_leading, skip_trailing, expected_pairs) in test_cases {
test_skip_mechanics(vertex_count, skip_leading, skip_trailing, expected_pairs);
}
}
#[test]
fn test_skip_symmetry() {
let center = Vec3A::ZERO;
let mut pairs_skip_start = 0;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
create_fan_vertices(8),
center,
2,
0,
|_, _, _, _| {
pairs_skip_start += 1;
true
},
)
);
assert_eq!(pairs_skip_start, 5);
let mut pairs_skip_end = 0;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
create_fan_vertices(8),
center,
1,
2,
|_, _, _, _| {
pairs_skip_end += 1;
true
},
)
);
assert_eq!(pairs_skip_end, 4);
let mut pairs_skip_both = 0;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
create_fan_vertices(8),
center,
2,
2,
|_, _, _, _| {
pairs_skip_both += 1;
true
},
)
);
assert_eq!(pairs_skip_both, 3);
}
#[test]
fn test_normal_magnitude_calculation() {
let vertices = [
Vec3A::new(2.0, 0.0, 0.0), Vec3A::new(0.0, 2.0, 0.0), Vec3A::new(-2.0, 0.0, 0.0), ];
let center = Vec3A::ZERO;
assert!(
IsotropicRemeshAlgo::<f32, Vec3>::validate_consecutive_triangles(
vertices.iter().copied(),
center,
1,
0,
|_n1, len1, _n2, len2| {
assert!((len1.sqrt() - 4.0).abs() < 0.001);
assert!((len2.sqrt() - 4.0).abs() < 0.001);
true
},
)
);
}