use super::interner::{Interner, Vid};
use super::retriangulate::{project2d, Canonical};
use super::DropAxis;
pub(crate) fn drop_out_of_plane(
canon: &mut Canonical,
tri: &[[f64; 3]; 3],
interner: &Interner,
axis: DropAxis,
) {
let proj = |v: Vid| super::fixed::point_to_f64(interner.get(v)).map(|p| project2d(p, axis));
canon.segments.retain(|&(lo, hi)| match (proj(lo), proj(hi)) {
(Some(a), Some(b)) => a[0] != b[0] || a[1] != b[1],
_ => true,
});
let u = [tri[1][0] - tri[0][0], tri[1][1] - tri[0][1], tri[1][2] - tri[0][2]];
let v = [tri[2][0] - tri[0][0], tri[2][1] - tri[0][1], tri[2][2] - tri[0][2]];
let n = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];
let nl = (n[0] * n[0] + n[1] * n[1] + n[2] * n[2]).sqrt();
if nl <= 0.0 {
return;
}
let n = [n[0] / nl, n[1] / nl, n[2] / nl];
let p0 = tri[0];
let extent = tri.iter().flat_map(|c| c.iter()).fold(0.0_f64, |m, &x| m.max(x.abs()));
let tol = 1.0e-3_f64.max(extent * (1.0 / 4_194_304.0));
let on_plane = |vid: Vid| {
super::fixed::point_to_f64(interner.get(vid)).is_none_or(|p| {
((p[0] - p0[0]) * n[0] + (p[1] - p0[1]) * n[1] + (p[2] - p0[2]) * n[2]).abs() <= tol
})
};
canon.segments.retain(|&(lo, hi)| on_plane(lo) && on_plane(hi));
canon.points.retain(|&vid| on_plane(vid));
}