#![forbid(unsafe_code)]
use super::{
BistellarFlipKind, FlipDirection, FlipError, Hash, Key, MAX_PRACTICAL_DIMENSION_SIZE,
SimplexKey, SimplexKeyBuffer, SmallBuffer, Tds, TriangleHandleError, VertexKey,
};
#[derive(Debug, Clone)]
pub struct FlipInfo<const D: usize> {
pub kind: BistellarFlipKind,
pub direction: FlipDirection,
pub removed_simplices: SimplexKeyBuffer,
pub new_simplices: SimplexKeyBuffer,
pub removed_face_vertices: SmallBuffer<VertexKey, MAX_PRACTICAL_DIMENSION_SIZE>,
pub inserted_face_vertices: SmallBuffer<VertexKey, MAX_PRACTICAL_DIMENSION_SIZE>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[must_use]
#[non_exhaustive]
pub struct FlipFeasibility<const D: usize> {
pub kind: BistellarFlipKind,
pub direction: FlipDirection,
pub removed_simplices: SimplexKeyBuffer,
pub removed_face_vertices: SmallBuffer<VertexKey, MAX_PRACTICAL_DIMENSION_SIZE>,
pub inserted_face_vertices: Option<SmallBuffer<VertexKey, MAX_PRACTICAL_DIMENSION_SIZE>>,
}
#[derive(Debug, Clone)]
pub(crate) struct FlipContext<const D: usize, const K: usize> {
pub removed_face_vertices: SmallBuffer<VertexKey, MAX_PRACTICAL_DIMENSION_SIZE>,
pub inserted_face_vertices: SmallBuffer<VertexKey, MAX_PRACTICAL_DIMENSION_SIZE>,
pub removed_simplices: SimplexKeyBuffer,
pub direction: FlipDirection,
}
#[derive(Debug, Clone)]
pub(crate) struct FlipContextDyn<const D: usize> {
pub removed_face_vertices: SmallBuffer<VertexKey, MAX_PRACTICAL_DIMENSION_SIZE>,
pub inserted_face_vertices: SmallBuffer<VertexKey, MAX_PRACTICAL_DIMENSION_SIZE>,
pub removed_simplices: SimplexKeyBuffer,
pub direction: FlipDirection,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TriangleHandle {
v0: VertexKey,
v1: VertexKey,
v2: VertexKey,
}
impl TriangleHandle {
pub fn try_new(a: VertexKey, b: VertexKey, c: VertexKey) -> Result<Self, TriangleHandleError> {
if a == b || a == c || b == c {
return Err(TriangleHandleError::DuplicateVertices {
vertices: [a, b, c],
});
}
Ok(Self::from_validated_vertices(a, b, c))
}
#[must_use]
pub(crate) fn from_validated_vertices(a: VertexKey, b: VertexKey, c: VertexKey) -> Self {
let mut verts = [a, b, c];
verts.sort_unstable_by_key(|v| v.data().as_ffi());
Self {
v0: verts[0],
v1: verts[1],
v2: verts[2],
}
}
#[must_use]
pub const fn vertices(self) -> [VertexKey; 3] {
[self.v0, self.v1, self.v2]
}
}
impl TryFrom<[VertexKey; 3]> for TriangleHandle {
type Error = TriangleHandleError;
fn try_from([a, b, c]: [VertexKey; 3]) -> Result<Self, Self::Error> {
Self::try_new(a, b, c)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RidgeHandle {
simplex_key: SimplexKey,
omit_a: u8,
omit_b: u8,
}
impl RidgeHandle {
pub fn try_new<U, V, const D: usize>(
tds: &Tds<U, V, D>,
simplex_key: SimplexKey,
omit_a: u8,
omit_b: u8,
) -> Result<Self, FlipError> {
if D < 3 {
return Err(FlipError::UnsupportedDimension { dimension: D });
}
let simplex = tds
.simplex(simplex_key)
.ok_or(FlipError::MissingSimplex { simplex_key })?;
let vertex_count = simplex.number_of_vertices();
let first_omit_index = usize::from(omit_a);
let second_omit_index = usize::from(omit_b);
if first_omit_index >= vertex_count || second_omit_index >= vertex_count || omit_a == omit_b
{
return Err(FlipError::InvalidRidgeIndex {
simplex_key,
omit_a,
omit_b,
vertex_count,
});
}
Ok(Self::from_validated(simplex_key, omit_a, omit_b))
}
#[inline]
pub(crate) const fn from_validated(simplex_key: SimplexKey, omit_a: u8, omit_b: u8) -> Self {
if omit_a <= omit_b {
Self {
simplex_key,
omit_a,
omit_b,
}
} else {
Self {
simplex_key,
omit_a: omit_b,
omit_b: omit_a,
}
}
}
#[must_use]
pub const fn simplex_key(&self) -> SimplexKey {
self.simplex_key
}
#[must_use]
pub const fn omit_a(&self) -> u8 {
self.omit_a
}
#[must_use]
pub const fn omit_b(&self) -> u8 {
self.omit_b
}
}
#[cfg(test)]
mod tests {
use super::super::*;
use super::*;
use slotmap::KeyData;
use std::assert_matches;
#[test]
fn triangle_handle_rejects_duplicate_vertices() {
let a = VertexKey::from(KeyData::from_ffi(1));
let b = VertexKey::from(KeyData::from_ffi(2));
assert_matches!(
TriangleHandle::try_new(a, b, a),
Err(TriangleHandleError::DuplicateVertices { vertices })
if vertices == [a, b, a]
);
}
#[test]
fn triangle_handle_try_from_canonicalizes_vertex_order() {
let a = VertexKey::from(KeyData::from_ffi(10));
let b = VertexKey::from(KeyData::from_ffi(20));
let c = VertexKey::from(KeyData::from_ffi(30));
let handle = TriangleHandle::try_from([c, a, b]).unwrap();
assert_eq!(handle.vertices(), [a, b, c]);
}
#[test]
fn ridge_handle_rejects_dimensions_below_three_before_simplex_lookup() {
let tds: Tds<(), (), 2> = Tds::empty();
let missing_simplex = SimplexKey::from(KeyData::from_ffi(40));
assert_matches!(
RidgeHandle::try_new(&tds, missing_simplex, 0, 1),
Err(FlipError::UnsupportedDimension { dimension: 2 })
);
}
#[test]
fn ridge_handle_canonicalizes_omitted_indices() {
let simplex_key = SimplexKey::from(KeyData::from_ffi(50));
let canonical = RidgeHandle::from_validated(simplex_key, 1, 3);
let reversed = RidgeHandle::from_validated(simplex_key, 3, 1);
assert_eq!(reversed, canonical);
assert_eq!(reversed.simplex_key(), simplex_key);
assert_eq!((reversed.omit_a(), reversed.omit_b()), (1, 3));
}
}