use alloc::vec::Vec;
use super::*;
use crate::fields::{ReferenceField, Sphere, Torus};
use crate::marching_cubes::MarchingCubes;
use crate::transvoxel::table::{EDGE_SAMPLES, is_half_resolution};
use crate::{MeshBuffer, RuntimeShape3};
#[test]
fn the_half_resolution_crossings_are_the_coarse_neighbours_vertices() {
#![allow(clippy::float_cmp)]
let field = Sphere::<f64>::canonical();
let (lo, hi) = field.domain();
let coarse_cells = 16u32;
let coarse_h = (hi[0] - lo[0]) / f64::from(coarse_cells);
let fine_h = coarse_h / 2.0;
let shape = RuntimeShape3::new([coarse_cells + 1; 3]).expect("valid shape");
let mut coarse = MeshBuffer::<f64>::new();
MarchingCubes::<f64>::new()
.extract(&field, &shape, lo, coarse_h, &mut coarse)
.expect("extraction");
assert!(coarse.triangle_count() > 0);
let mut checked = 0usize;
let mut cut = 0usize;
for iv in 0..coarse_cells {
for iu in 0..coarse_cells {
let base = [
i64::from(coarse_cells), 2 * i64::from(iu),
2 * i64::from(iv),
];
let cell = TransitionCell::sample(&field, lo, fine_h, base, 1, 2, 0.0);
for (edge, position) in cell.crossings() {
if !is_half_resolution(edge) {
continue;
}
cut += 1;
let found = coarse.positions.contains(&position);
assert!(
found,
"edge {edge} joins samples {:?} and its crossing {position:?} is not a \
vertex of the coarse mesh",
EDGE_SAMPLES[edge as usize]
);
}
checked += 1;
}
}
std::println!(
"{checked} transition faces walked, {cut} half-resolution crossings all matched a \
coarse vertex exactly"
);
assert!(
cut > 0,
"no half-resolution edge was ever cut — the fixture is not on the surface"
);
}
#[test]
fn the_identity_survives_a_non_power_of_two_spacing() {
#![allow(clippy::float_cmp)]
let field = Torus::<f64>::canonical();
let (lo, hi) = field.domain();
let coarse_cells = 14u32;
let coarse_h = (hi[0] - lo[0]) / f64::from(coarse_cells);
let fine_h = coarse_h / 2.0;
assert!(
coarse_h.to_bits() % 2 != 0 || (coarse_h.log2().fract() != 0.0),
"the point of this test is a spacing that is not a power of two"
);
let shape = RuntimeShape3::new([coarse_cells + 1; 3]).expect("valid shape");
let mut coarse = MeshBuffer::<f64>::new();
MarchingCubes::<f64>::new()
.extract(&field, &shape, lo, coarse_h, &mut coarse)
.expect("extraction");
let mut cut = 0usize;
for iv in 0..coarse_cells {
for iu in 0..coarse_cells {
let base = [
i64::from(coarse_cells), 2 * i64::from(iu),
2 * i64::from(iv),
];
let cell = TransitionCell::sample(&field, lo, fine_h, base, 1, 2, 0.0);
for (edge, position) in cell.crossings() {
if !is_half_resolution(edge) {
continue;
}
cut += 1;
assert!(
coarse.positions.contains(&position),
"h = {coarse_h}: edge {edge} crossing {position:?} is not a coarse vertex"
);
}
}
}
std::println!("h = {coarse_h} (not a power of two): {cut} crossings all matched exactly");
assert!(cut > 0, "no half-resolution edge was cut");
}
#[test]
fn the_corner_samples_are_the_coarse_grid_and_the_rest_are_not() {
#![allow(clippy::float_cmp)]
let field = Sphere::<f64>::canonical();
let step = 0.125;
let grid_origin = [-2.0, -2.0, -2.0];
let base = [4i64, 6, 2];
let cell = TransitionCell::sample(&field, grid_origin, step, base, 1, 2, 0.0);
let at = |index: [i64; 3]| {
[
grid_origin[0] + step * index[0] as f64,
grid_origin[1] + step * index[1] as f64,
grid_origin[2] + step * index[2] as f64,
]
};
for (s, p) in cell.position.iter().enumerate() {
let expected = at([base[0], base[1] + (s % 3) as i64, base[2] + (s / 3) as i64]);
assert_eq!(*p, expected, "sample {s}");
}
for corner in [0usize, 2, 6, 8] {
assert_eq!((corner % 3) % 2, 0);
assert_eq!((corner / 3) % 2, 0);
}
}
#[test]
fn a_crossing_exists_exactly_where_the_signs_differ() {
let field = Sphere::<f64>::canonical();
let mut seen_cut = 0usize;
for i in 0..12i64 {
let cell = TransitionCell::sample(&field, [-2.0; 3], 0.125, [8 + i, 12, 18], 0, 1, 0.0);
for edge in 0..16u8 {
let crossing = cell.crossing(edge);
assert_eq!(crossing.is_some(), cell.is_cut(edge), "edge {edge}");
if let Some(p) = crossing {
seen_cut += 1;
let [a, b] = EDGE_SAMPLES[edge as usize];
let (lo, hi) = (cell.position[a as usize], cell.position[b as usize]);
for axis in 0..3 {
let (min, max) = if lo[axis] <= hi[axis] {
(lo[axis], hi[axis])
} else {
(hi[axis], lo[axis])
};
assert!(
p[axis] >= min && p[axis] <= max,
"edge {edge} axis {axis}: {} outside [{min}, {max}]",
p[axis]
);
}
}
}
}
assert!(seen_cut > 0, "no edge was ever cut");
}
#[test]
fn the_case_index_matches_the_tables_convention() {
let field = Sphere::<f64>::canonical();
let cell = TransitionCell::sample(&field, [-2.0; 3], 0.25, [6, 6, 8], 0, 1, 0.0);
let case = cell.case();
for s in 0..SAMPLE_COUNT {
assert_eq!(
crate::transvoxel::table::sample_inside(case, s as u8),
crate::cube::is_inside(cell.value[s]),
"sample {s}"
);
}
let table_cut = crate::transvoxel::table::cut_edges(case);
let cell_cut: u16 = (0..16u8).filter(|e| cell.is_cut(*e)).map(|e| 1 << e).sum();
assert_eq!(table_cut, cell_cut, "case {case:#011b}");
}
#[test]
fn a_cell_the_surface_misses_has_no_centroid() {
let field = Sphere::<f64>::canonical();
let cell = TransitionCell::sample(&field, [-2.0; 3], 0.05, [72, 72, 72], 0, 1, 0.0);
assert!(cell.crossings().next().is_none());
assert_eq!(cell.centroid(), None);
let on_surface = TransitionCell::sample(&field, [-2.0; 3], 0.125, [8, 16, 16], 1, 2, 0.0);
let crossings: Vec<_> = on_surface.crossings().collect();
if !crossings.is_empty() {
assert!(on_surface.centroid().is_some());
}
}
#[test]
fn a_zero_width_patch_is_edge_on_to_the_surface_and_cannot_be_wound() {
#![allow(clippy::float_cmp)]
let field = Sphere::<f64>::canonical();
let (lo, _hi) = field.domain();
let fine_h = 0.125;
let mut worst_alignment = 0.0f64;
let mut faces = 0usize;
for iv in 0..16i64 {
for iu in 0..16i64 {
let cell = TransitionCell::sample(&field, lo, fine_h, [16, 2 * iu, 2 * iv], 1, 2, 0.0);
let mut patch = MeshBuffer::<f64>::new();
cell.emit(&field, 0, &mut patch);
if patch.triangle_count() == 0 {
continue;
}
for p in &patch.positions {
assert_eq!(
p[0], cell.position[0][0],
"a patch vertex left the face plane"
);
}
for tri in patch.indices.as_chunks::<3>().0 {
let a = patch.positions[tri[0] as usize];
let b = patch.positions[tri[1] as usize];
let c = patch.positions[tri[2] as usize];
let n = crate::vec3::cross(crate::vec3::sub(b, a), crate::vec3::sub(c, a));
let len2 = crate::vec3::length_squared(n);
if len2 == 0.0 {
continue;
}
faces += 1;
let centre = [
(a[0] + b[0] + c[0]) / 3.0,
(a[1] + b[1] + c[1]) / 3.0,
(a[2] + b[2] + c[2]) / 3.0,
];
let g = field.gradient(centre);
let alignment =
crate::vec3::dot(n, g).abs() / (len2.sqrt() * crate::vec3::length(g));
worst_alignment = worst_alignment.max(alignment);
}
}
}
std::println!(
"{faces} zero-width patch faces; worst |cos| against the surface normal is \
{worst_alignment:.3e}"
);
assert!(faces > 0, "no transition patch was produced");
assert!(
worst_alignment < 1e-12,
"a zero-width patch should be perpendicular to the surface, got |cos| = {worst_alignment:.3e}"
);
}
#[test]
fn every_crossing_reaches_a_triangle() {
let field = Sphere::<f64>::canonical();
let (lo, _hi) = field.domain();
let mut cells = 0usize;
for iv in 0..16i64 {
for iu in 0..16i64 {
let cell = TransitionCell::sample(&field, lo, 0.125, [16, 2 * iu, 2 * iv], 1, 2, 0.0);
let crossings: Vec<[f64; 3]> = cell.crossings().map(|(_, p)| p).collect();
if crossings.is_empty() {
continue;
}
cells += 1;
let mut patch = MeshBuffer::<f64>::new();
cell.emit(&field, 0, &mut patch);
assert!(
patch.triangle_count() > 0,
"a cell with {} crossings produced no triangles",
crossings.len()
);
for crossing in &crossings {
assert!(
patch.positions.contains(crossing),
"crossing {crossing:?} never reached a vertex"
);
}
let extra = patch
.positions
.iter()
.filter(|p| !crossings.contains(p))
.count();
assert!(
extra > 0 && extra <= 4,
"expected one centroid per cycle, got {extra}"
);
}
}
assert!(cells > 0, "no transition cell was cut");
std::println!("{cells} transition cells triangulated, every crossing used");
}
#[test]
fn the_width_displaces_only_the_half_resolution_face() {
#![allow(clippy::float_cmp)]
let field = Sphere::<f64>::canonical();
let (lo, _hi) = field.domain();
let width = 0.0625;
let mut fine_checked = 0usize;
let mut coarse_checked = 0usize;
for iv in 0..16i64 {
for iu in 0..16i64 {
let base = [16, 2 * iu, 2 * iv];
let flat = TransitionCell::sample(&field, lo, 0.125, base, 1, 2, 0.0);
let thick = TransitionCell::sample(&field, lo, 0.125, base, 1, 2, width);
assert_eq!(flat.case(), thick.case());
for edge in 0..16u8 {
let (Some(a), Some(b)) = (flat.crossing(edge), thick.crossing(edge)) else {
continue;
};
if is_half_resolution(edge) {
coarse_checked += 1;
assert_eq!(
b[0],
a[0] + width,
"edge {edge} moved wrong along the normal"
);
assert_eq!([b[1], b[2]], [a[1], a[2]], "edge {edge} moved in-plane");
} else {
fine_checked += 1;
assert_eq!(a, b, "edge {edge} is on the fine face and must not move");
}
}
}
}
std::println!(
"{fine_checked} fine crossings unmoved, {coarse_checked} coarse crossings displaced by \
exactly the width"
);
assert!(fine_checked > 0 && coarse_checked > 0);
}
#[test]
fn a_patch_with_width_is_wound_away_from_the_solid() {
let field = Sphere::<f64>::canonical();
let (lo, _hi) = field.domain();
let fine_h = 0.125;
let width = fine_h;
let mut agree = 0usize;
let mut disagree = 0usize;
let mut worst_alignment = 0.0f64;
for iv in 0..16i64 {
for iu in 0..16i64 {
let cell =
TransitionCell::sample(&field, lo, fine_h, [16, 2 * iu, 2 * iv], 1, 2, width);
let mut patch = MeshBuffer::<f64>::new();
cell.emit(&field, 0, &mut patch);
if patch.triangle_count() == 0 {
continue;
}
for tri in patch.indices.as_chunks::<3>().0 {
let a = patch.positions[tri[0] as usize];
let b = patch.positions[tri[1] as usize];
let c = patch.positions[tri[2] as usize];
let n = crate::vec3::cross(crate::vec3::sub(b, a), crate::vec3::sub(c, a));
let len2 = crate::vec3::length_squared(n);
if len2 == 0.0 {
continue;
}
let centre = [
(a[0] + b[0] + c[0]) / 3.0,
(a[1] + b[1] + c[1]) / 3.0,
(a[2] + b[2] + c[2]) / 3.0,
];
let g = field.gradient(centre);
let cos = crate::vec3::dot(n, g) / (len2.sqrt() * crate::vec3::length(g));
worst_alignment = worst_alignment.max(cos.abs());
if cos > 0.0 {
agree += 1;
} else {
disagree += 1;
}
}
}
}
std::println!(
"width {width}: {agree} faces outward, {disagree} inward; best |cos| against the \
surface normal {worst_alignment:.3}"
);
assert!(agree + disagree > 0, "no patch was produced");
assert!(
worst_alignment > 0.1,
"the patch is still edge-on: best |cos| {worst_alignment:.3e}"
);
assert_eq!(
disagree,
0,
"{disagree} of {} faces point into the solid",
agree + disagree
);
}
fn gaps_in_the_seam_plane(mesh: &MeshBuffer<f64>, seam_x: f64, h: f64) -> usize {
#![allow(clippy::float_cmp)]
let cfg = crate::validate::ValidateConfig::from_cell_size(h).expect("valid cell size");
let (_report, features) =
crate::validate::validate_features(&mesh.positions, &mesh.indices, &cfg);
features
.boundary_edges
.iter()
.filter(|[a, b]| {
mesh.positions[*a as usize][0] == seam_x && mesh.positions[*b as usize][0] == seam_x
})
.count()
}
#[test]
fn transition_cells_close_the_gap_between_two_resolutions() {
#![allow(clippy::float_cmp)]
let field = Sphere::<f64>::canonical();
let fine_h = 0.125;
let coarse_h = fine_h + fine_h;
let seam_x = 0.0;
let grid_origin = [-2.0, -2.0, -2.0];
let fine_shape = RuntimeShape3::new([17, 33, 33]).expect("valid shape");
let mut fine = MeshBuffer::<f64>::new();
MarchingCubes::<f64>::new()
.extract(&field, &fine_shape, grid_origin, fine_h, &mut fine)
.expect("extraction");
let coarse_shape = RuntimeShape3::new([9, 17, 17]).expect("valid shape");
let mut coarse = MeshBuffer::<f64>::new();
MarchingCubes::<f64>::new()
.extract(
&field,
&coarse_shape,
[seam_x, -2.0, -2.0],
coarse_h,
&mut coarse,
)
.expect("extraction");
assert!(fine.triangle_count() > 0 && coarse.triangle_count() > 0);
let mut plain = MeshBuffer::<f64>::new();
plain
.append(&fine)
.expect("the meshes fit the u32 index space");
plain
.append(&coarse)
.expect("the meshes fit the u32 index space");
crate::weld::Welder::<f64>::new()
.weld(&mut plain, crate::weld::epsilon_for(fine_h))
.expect("weld");
let before = gaps_in_the_seam_plane(&plain, seam_x, fine_h);
let mut stitched = MeshBuffer::<f64>::new();
stitched
.append(&fine)
.expect("the meshes fit the u32 index space");
stitched
.append(&coarse)
.expect("the meshes fit the u32 index space");
let mut patches = 0usize;
for jz in 0..16i64 {
for jy in 0..16i64 {
let cell = TransitionCell::sample(
&field,
grid_origin,
fine_h,
[16, 2 * jy, 2 * jz],
1,
2,
0.0,
);
let mut patch = MeshBuffer::<f64>::new();
cell.emit(&field, 0, &mut patch);
if patch.triangle_count() > 0 {
patches += 1;
stitched
.append(&patch)
.expect("the meshes fit the u32 index space");
}
}
}
crate::weld::Welder::<f64>::new()
.weld(&mut stitched, crate::weld::epsilon_for(fine_h))
.expect("weld");
let after = gaps_in_the_seam_plane(&stitched, seam_x, fine_h);
std::println!(
"seam-plane boundary edges: {before} without transition cells, {after} with \
({patches} patches emitted)"
);
assert!(
patches > 0,
"no transition cell was cut — the fixture misses the surface"
);
assert!(
before > 0,
"the two resolutions already agreed, so this proves nothing"
);
assert_eq!(
after, 0,
"the seam still has {after} unmatched boundary edges"
);
}
#[test]
fn a_mirrored_patch_is_wound_away_from_the_solid() {
let field = Sphere::<f64>::canonical();
let (lo, _hi) = field.domain();
let fine_h = 0.125;
for (u, v, width) in [(1usize, 2usize, -fine_h), (2, 1, fine_h)] {
let mut agree = 0usize;
let mut disagree = 0usize;
for ib in 0..16i64 {
for ia in 0..16i64 {
let cell =
TransitionCell::sample(&field, lo, fine_h, [16, 2 * ia, 2 * ib], u, v, width);
let mut patch = MeshBuffer::<f64>::new();
cell.emit(&field, 0, &mut patch);
for tri in patch.indices.as_chunks::<3>().0 {
let a = patch.positions[tri[0] as usize];
let b = patch.positions[tri[1] as usize];
let c = patch.positions[tri[2] as usize];
let n = crate::vec3::cross(crate::vec3::sub(b, a), crate::vec3::sub(c, a));
if crate::vec3::length_squared(n) == 0.0 {
continue;
}
let centre = [
(a[0] + b[0] + c[0]) / 3.0,
(a[1] + b[1] + c[1]) / 3.0,
(a[2] + b[2] + c[2]) / 3.0,
];
if crate::vec3::dot(n, field.gradient(centre)) > 0.0 {
agree += 1;
} else {
disagree += 1;
}
}
}
}
std::println!("u={u} v={v} width={width}: {agree} faces outward, {disagree} inward");
assert!(agree + disagree > 0, "no patch was produced");
assert_eq!(
disagree,
0,
"u={u} v={v} width={width}: {disagree} of {} faces point into the solid",
agree + disagree
);
}
}