use delaunay::core::triangulation::TriangulationConstructionError;
use delaunay::prelude::triangulation::*;
use delaunay::triangulation::delaunay::{
ConstructionOptions, DedupPolicy, DelaunayTriangulationConstructionError,
InsertionOrderStrategy,
};
fn init_tracing() {
static INIT: std::sync::Once = std::sync::Once::new();
INIT.call_once(|| {
let filter = tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("warn"));
let _ = tracing_subscriber::fmt()
.with_env_filter(filter)
.with_test_writer()
.try_init();
});
}
fn simplex_vertices<const D: usize>() -> Vec<Vertex<f64, (), D>> {
let mut verts = Vec::with_capacity(D + 1);
verts.push(vertex!([0.0; D]));
for i in 0..D {
let mut coords = [0.0; D];
coords[i] = 1.0;
verts.push(vertex!(coords));
}
verts
}
#[expect(
clippy::cast_precision_loss,
reason = "D ≤ 5 in practice; no precision loss"
)]
fn simplex_with_interior_and_duplicates<const D: usize>() -> (Vec<Vertex<f64, (), D>>, usize) {
let mut verts = simplex_vertices::<D>();
let interior = [0.25 / (D as f64); D];
verts.push(vertex!(interior));
let distinct = verts.len();
verts.push(vertex!([0.0; D]));
verts.push(vertex!(interior));
(verts, distinct)
}
fn all_identical_vertices<const D: usize>(count: usize) -> Vec<Vertex<f64, (), D>> {
(0..count).map(|_| vertex!([1.0; D])).collect()
}
#[expect(
clippy::cast_precision_loss,
reason = "D ≤ 5 in practice; no precision loss"
)]
fn simplex_with_one_duplicate<const D: usize>() -> (Vec<Vertex<f64, (), D>>, usize) {
let mut verts = simplex_vertices::<D>();
let interior = [0.5 / (D as f64); D];
verts.push(vertex!(interior));
let distinct = verts.len();
verts.push(vertex!([0.0; D]));
(verts, distinct)
}
macro_rules! gen_dedup_batch_tests {
($dim:literal) => {
pastey::paste! {
#[test]
fn [<test_batch_construction_deduplicates_exact_duplicates_ $dim d>]() {
init_tracing();
let (vertices, distinct) = simplex_with_interior_and_duplicates::<$dim>();
assert!(vertices.len() > distinct);
let dt: DelaunayTriangulation<_, (), (), $dim> =
DelaunayTriangulation::new_with_topology_guarantee(
&vertices,
TopologyGuarantee::PLManifold,
)
.expect(concat!(
stringify!($dim), "D construction with duplicates should succeed"
));
assert_eq!(
dt.number_of_vertices(),
distinct,
"{}D: duplicates should be removed by Hilbert-sort dedup",
$dim
);
assert!(dt.number_of_cells() > 0);
let validation = dt.validate();
assert!(
validation.is_ok(),
"{}D: triangulation should pass validation: {validation:?}",
$dim
);
}
#[test]
fn [<test_batch_construction_all_duplicates_fails_ $dim d>]() {
init_tracing();
let vertices = all_identical_vertices::<$dim>($dim + 2);
let result: Result<DelaunayTriangulation<_, (), (), $dim>, _> =
DelaunayTriangulation::new(&vertices);
assert!(
matches!(
result,
Err(DelaunayTriangulationConstructionError::Triangulation(
TriangulationConstructionError::InsufficientVertices { .. }
))
),
"{}D: all-duplicate input should fail with InsufficientVertices",
$dim
);
}
#[test]
fn [<test_explicit_dedup_exact_input_order_ $dim d>]() {
init_tracing();
let (vertices, distinct) = simplex_with_one_duplicate::<$dim>();
let opts = ConstructionOptions::default()
.with_insertion_order(InsertionOrderStrategy::Input)
.with_dedup_policy(DedupPolicy::Exact);
let dt: DelaunayTriangulation<_, (), (), $dim> =
DelaunayTriangulation::new_with_options(&vertices, opts)
.expect(concat!(
stringify!($dim),
"D: DedupPolicy::Exact + Input should succeed"
));
assert_eq!(
dt.number_of_vertices(),
distinct,
"{}D: DedupPolicy::Exact should remove duplicate",
$dim
);
assert!(dt.validate().is_ok());
}
#[test]
fn [<test_batch_construction_many_duplicates_ $dim d>]() {
init_tracing();
let (base, distinct_count_raw) = simplex_with_interior_and_duplicates::<$dim>();
let distinct: Vec<Vertex<f64, (), $dim>> =
base.into_iter().take(distinct_count_raw).collect();
let distinct_count = distinct.len();
let vertices: Vec<Vertex<f64, (), $dim>> = distinct
.iter()
.cycle()
.take(distinct_count * 5)
.copied()
.collect();
assert_eq!(vertices.len(), distinct_count * 5);
let dt: DelaunayTriangulation<_, (), (), $dim> =
DelaunayTriangulation::new(&vertices)
.expect(concat!(
stringify!($dim),
"D: many-duplicate construction should succeed"
));
assert_eq!(
dt.number_of_vertices(),
distinct_count,
"{}D: should collapse {} inputs to {} distinct vertices",
$dim,
distinct_count * 5,
distinct_count
);
assert!(dt.validate().is_ok());
}
}
};
}
gen_dedup_batch_tests!(2);
gen_dedup_batch_tests!(3);
gen_dedup_batch_tests!(4);
gen_dedup_batch_tests!(5);
#[test]
fn test_hilbert_dedup_quantized_collision_2d() {
init_tracing();
let mut vertices = simplex_vertices::<2>();
vertices.push(vertex!([0.5, 0.5]));
vertices.push(vertex!([0.5 + 1e-10, 0.5])); let total = vertices.len();
let dt: DelaunayTriangulation<_, (), (), 2> = DelaunayTriangulation::new(&vertices)
.expect("2D construction with quantized-collision should succeed");
assert!(
dt.number_of_vertices() < total,
"expected Hilbert dedup to collapse quantized-collision pair (got {} of {total})",
dt.number_of_vertices(),
);
assert!(dt.validate().is_ok());
}