use std::collections::HashMap;
use nalgebra::Point2;
use super::quads::Quad;
use super::TopologicalParams;
fn edge_len(positions: &[Point2<f32>], u: usize, v: usize) -> f32 {
let pu = positions[u];
let pv = positions[v];
((pv.x - pu.x).powi(2) + (pv.y - pu.y).powi(2)).sqrt()
}
fn passes_geometric(quad: &Quad, positions: &[Point2<f32>], params: &TopologicalParams) -> bool {
let v = quad.vertices;
let l01 = edge_len(positions, v[0], v[1]);
let l12 = edge_len(positions, v[1], v[2]);
let l23 = edge_len(positions, v[2], v[3]);
let l30 = edge_len(positions, v[3], v[0]);
let r1 = l01.max(l23) / l01.min(l23).max(1e-6);
let r2 = l12.max(l30) / l12.min(l30).max(1e-6);
r1.max(r2) <= params.edge_ratio_max
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(
level = "debug",
skip_all,
fields(num_quads_in = quads.len()),
)
)]
pub(crate) fn filter_quads(
quads: &[Quad],
positions: &[Point2<f32>],
params: &TopologicalParams,
) -> Vec<Quad> {
let mut degree: HashMap<usize, u32> = HashMap::new();
for q in quads {
for (u, v) in q.perimeter_edges() {
*degree.entry(u).or_default() += 1;
*degree.entry(v).or_default() += 1;
}
}
quads
.iter()
.copied()
.filter(|q| {
let illegal = q
.vertices
.iter()
.filter(|v| degree.get(v).copied().unwrap_or(0) > 8)
.count();
illegal < 2
})
.filter(|q| passes_geometric(q, positions, params))
.collect()
}