use honeycomb_core::cmap::{CMap2, DartIdType, FaceIdType, OrbitPolicy};
use honeycomb_core::geometry::{CoordsFloat, Vertex2};
use honeycomb_core::stm::{Transaction, TransactionClosureResult, abort, try_or_coerce};
use smallvec::SmallVec;
use crate::triangulation::{TriangulateError, check_requirements};
#[allow(clippy::missing_panics_doc)]
pub fn process_cell<T: CoordsFloat>(
t: &mut Transaction,
cmap: &CMap2<T>,
face_id: FaceIdType,
new_darts: &[DartIdType],
) -> TransactionClosureResult<(), TriangulateError> {
let mut darts: SmallVec<DartIdType, 16> = SmallVec::new();
let mut vertices: SmallVec<Vertex2<T>, 16> = SmallVec::new();
for d in cmap.orbit_tx(t, OrbitPolicy::FaceLinear, face_id as DartIdType) {
darts.push(d?);
}
for &d in &darts {
let vid = cmap.vertex_id_tx(t, d)?;
let v = if let Some(val) = cmap.read_vertex_tx(t, vid)? {
val
} else {
abort(TriangulateError::UndefinedFace(
"one or more undefined vertices",
))?
};
vertices.push(v);
}
let n = darts.len();
if let Err(e) = check_requirements(n, new_darts.len()) {
abort(e)?;
}
let star = darts
.iter()
.zip(vertices.iter())
.enumerate()
.find_map(|(id, (d0, v0))| {
let mut tmp = vertices
.windows(2)
.enumerate()
.filter(|(i_seg, _)| !((n + i_seg) % n == id || (n + i_seg - 1) % n == id))
.map(|(_, val)| {
let [v1, v2] = val else { unreachable!() };
Vertex2::cross_product_from_vertices(v0, v1, v2)
});
let signum = tmp.next().map(T::signum).unwrap();
for v in tmp {
if v.signum() != signum || v.abs() < T::epsilon() {
return None;
}
}
Some(d0)
});
if let Some(sdart) = star {
let b0_sdart = cmap.beta_tx::<0>(t, *sdart)?;
let vid = cmap.vertex_id_tx(t, *sdart)?;
let v0 = cmap.read_vertex_tx(t, vid)?.unwrap();
try_or_coerce!(cmap.unsew_tx::<1>(t, b0_sdart), TriangulateError);
let mut d0 = *sdart;
for sl in new_darts.chunks_exact(2) {
let [d1, d2] = sl else { unreachable!() };
let b1_d0 = cmap.beta_tx::<1>(t, d0)?;
let b1b1_d0 = cmap.beta_tx::<1>(t, b1_d0)?;
try_or_coerce!(cmap.unsew_tx::<1>(t, b1_d0), TriangulateError);
try_or_coerce!(cmap.sew_tx::<2>(t, *d1, *d2), TriangulateError);
try_or_coerce!(cmap.sew_tx::<1>(t, *d2, b1b1_d0), TriangulateError);
try_or_coerce!(cmap.sew_tx::<1>(t, b1_d0, *d1), TriangulateError);
try_or_coerce!(cmap.sew_tx::<1>(t, *d1, d0), TriangulateError);
d0 = *d2;
}
let b1_d0 = cmap.beta_tx::<1>(t, d0)?;
let b1b1_d0 = cmap.beta_tx::<1>(t, b1_d0)?;
try_or_coerce!(cmap.sew_tx::<1>(t, b1b1_d0, d0), TriangulateError);
let vid = cmap.vertex_id_tx(t, *sdart)?;
cmap.write_vertex_tx(t, vid, v0)?;
} else {
abort(TriangulateError::NonFannable)?;
}
Ok(())
}
#[allow(clippy::missing_panics_doc)]
pub fn process_convex_cell<T: CoordsFloat>(
t: &mut Transaction,
cmap: &CMap2<T>,
face_id: FaceIdType,
new_darts: &[DartIdType],
) -> TransactionClosureResult<(), TriangulateError> {
let mut darts: SmallVec<DartIdType, 16> = SmallVec::new();
for d in cmap.orbit_tx(t, OrbitPolicy::FaceLinear, face_id as DartIdType) {
darts.push(d?);
}
let n = darts.len();
if let Err(e) = check_requirements(n, new_darts.len()) {
abort(e)?;
}
let sdart = face_id as DartIdType;
let b0_sdart = cmap.beta_tx::<0>(t, sdart)?;
let vid = cmap.vertex_id_tx(t, sdart)?;
let v0 = cmap.read_vertex_tx(t, vid)?.unwrap();
try_or_coerce!(cmap.unsew_tx::<1>(t, b0_sdart), TriangulateError);
let mut d0 = sdart;
for sl in new_darts.chunks_exact(2) {
let [d1, d2] = sl else { unreachable!() };
let b1_d0 = cmap.beta_tx::<1>(t, d0)?;
let b1b1_d0 = cmap.beta_tx::<1>(t, b1_d0)?;
try_or_coerce!(cmap.unsew_tx::<1>(t, b1_d0), TriangulateError);
try_or_coerce!(cmap.sew_tx::<2>(t, *d1, *d2), TriangulateError);
try_or_coerce!(cmap.sew_tx::<1>(t, *d2, b1b1_d0), TriangulateError);
try_or_coerce!(cmap.sew_tx::<1>(t, b1_d0, *d1), TriangulateError);
try_or_coerce!(cmap.sew_tx::<1>(t, *d1, d0), TriangulateError);
d0 = *d2;
}
let b1_d0 = cmap.beta_tx::<1>(t, d0)?;
let b1b1_d0 = cmap.beta_tx::<1>(t, b1_d0)?;
try_or_coerce!(cmap.sew_tx::<1>(t, b1b1_d0, d0), TriangulateError);
let vid = cmap.vertex_id_tx(t, sdart)?;
cmap.write_vertex_tx(t, vid, v0)?;
Ok(())
}