#![forbid(unsafe_code)]
use std::ops::{Deref, DerefMut};
use crate::core::tds::{
SimplexKey, Tds, TdsMutationError, TopologyOwner, TopologyOwnerId, VertexKey,
};
use crate::topology::traits::topological_space::GlobalTopology;
use crate::triangulation::validation::{
TopologyConstructionProvenance, TopologyGuarantee, ValidationPolicy,
};
#[derive(Clone, Debug)]
pub struct Triangulation<K, U, V, const D: usize> {
pub(crate) kernel: K,
pub(crate) tds: Tds<U, V, D>,
pub(crate) global_topology: GlobalTopology<D>,
pub(crate) validation_policy: ValidationPolicy,
pub(crate) topology_guarantee: TopologyGuarantee,
pub(crate) topology_construction_provenance: TopologyConstructionProvenance,
}
impl<K, U, V, const D: usize> TopologyOwner for Triangulation<K, U, V, D> {
#[inline]
fn topology_owner_id(&self) -> TopologyOwnerId {
self.tds.topology_owner_id()
}
#[inline]
fn topology_generation(&self) -> u64 {
self.tds.generation()
}
}
impl<K, U, V, const D: usize> Triangulation<K, U, V, D> {
#[inline]
#[must_use]
pub(crate) const fn tds(&self) -> &Tds<U, V, D> {
&self.tds
}
#[must_use]
pub fn into_tds(self) -> Tds<U, V, D> {
self.tds
}
#[inline]
pub fn set_vertex_data(
&mut self,
key: VertexKey,
data: Option<U>,
) -> Result<Option<U>, TdsMutationError> {
self.tds.set_vertex_data(key, data)
}
#[inline]
pub fn set_simplex_data(
&mut self,
key: SimplexKey,
data: Option<V>,
) -> Result<Option<V>, TdsMutationError> {
self.tds.set_simplex_data(key, data)
}
}
#[derive(Clone, Debug)]
#[repr(transparent)]
pub(in crate::triangulation) struct UnverifiedTriangulation<K, U, V, const D: usize> {
pub(in crate::triangulation) storage: Triangulation<K, U, V, D>,
}
impl<K, U, V, const D: usize> UnverifiedTriangulation<K, U, V, D> {
pub(in crate::triangulation) const fn with_topology_context(
tds: Tds<U, V, D>,
kernel: K,
topology_guarantee: TopologyGuarantee,
global_topology: GlobalTopology<D>,
topology_construction_provenance: TopologyConstructionProvenance,
) -> Self {
Self {
storage: Triangulation {
kernel,
tds,
global_topology,
validation_policy: topology_guarantee.default_validation_policy(),
topology_guarantee,
topology_construction_provenance,
},
}
}
pub(in crate::triangulation) fn into_verified(self) -> Triangulation<K, U, V, D> {
self.storage
}
pub(in crate::triangulation) fn into_tds(self) -> Tds<U, V, D> {
self.storage.tds
}
}
impl<K, U, V, const D: usize> Deref for UnverifiedTriangulation<K, U, V, D> {
type Target = Triangulation<K, U, V, D>;
fn deref(&self) -> &Self::Target {
&self.storage
}
}
impl<K, U, V, const D: usize> DerefMut for UnverifiedTriangulation<K, U, V, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.storage
}
}
#[cfg(test)]
pub mod test_support {
use super::*;
use crate::geometry::kernel::Kernel;
impl<K, U, V, const D: usize> Triangulation<K, U, V, D>
where
K: Kernel<D>,
{
#[must_use]
pub(crate) fn new_empty(kernel: K) -> Self {
Self {
kernel,
tds: Tds::empty(),
global_topology: GlobalTopology::DEFAULT,
validation_policy: TopologyGuarantee::DEFAULT.default_validation_policy(),
topology_guarantee: TopologyGuarantee::DEFAULT,
topology_construction_provenance: TopologyConstructionProvenance::Unproven,
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::tds::TdsError;
use crate::geometry::kernel::FastKernel;
use crate::vertex;
use slotmap::KeyData;
use std::assert_matches;
struct NotAKernel;
impl<K, U, V, const D: usize> Triangulation<K, U, V, D> {
#[inline]
pub(crate) const fn new_with_tds(kernel: K, tds: Tds<U, V, D>) -> Self {
Self {
kernel,
tds,
global_topology: GlobalTopology::DEFAULT,
validation_policy: TopologyGuarantee::DEFAULT.default_validation_policy(),
topology_guarantee: TopologyGuarantee::DEFAULT,
topology_construction_provenance: TopologyConstructionProvenance::Unproven,
}
}
}
#[test]
fn new_empty_sets_default_topology_and_validation_policy() {
let tri: Triangulation<FastKernel<f64>, (), (), 3> =
Triangulation::new_empty(FastKernel::new());
assert_eq!(tri.tds.number_of_vertices(), 0);
assert_eq!(tri.tds.number_of_simplices(), 0);
assert_eq!(tri.global_topology, GlobalTopology::DEFAULT);
assert_eq!(tri.topology_guarantee, TopologyGuarantee::DEFAULT);
assert_eq!(
tri.validation_policy,
TopologyGuarantee::DEFAULT.default_validation_policy()
);
}
#[test]
fn explicit_empty_context_sets_requested_topology_and_policy() {
let tri: Triangulation<FastKernel<f64>, (), (), 3> = Triangulation {
kernel: FastKernel::new(),
tds: Tds::empty(),
global_topology: GlobalTopology::Spherical,
validation_policy: TopologyGuarantee::Pseudomanifold.default_validation_policy(),
topology_guarantee: TopologyGuarantee::Pseudomanifold,
topology_construction_provenance: TopologyConstructionProvenance::Unproven,
};
assert_eq!(tri.global_topology, GlobalTopology::Spherical);
assert_eq!(tri.topology_guarantee, TopologyGuarantee::Pseudomanifold);
assert_eq!(
tri.validation_policy,
TopologyGuarantee::Pseudomanifold.default_validation_policy()
);
}
#[test]
fn topology_owner_and_demotion_preserve_canonical_tds() {
let mut tri: Triangulation<FastKernel<f64>, (), (), 2> =
Triangulation::new_empty(FastKernel::new());
let owner_id = tri.topology_owner_id();
let initial_generation = tri.topology_generation();
tri.tds
.insert_vertex_with_mapping(vertex!([0.0, 0.0]).unwrap())
.unwrap();
assert_eq!(tri.tds().topology_owner_id(), owner_id);
assert_eq!(tri.topology_generation(), tri.tds().generation());
assert!(tri.topology_generation() > initial_generation);
let tds = tri.into_tds();
assert_eq!(tds.topology_owner_id(), owner_id);
assert_eq!(tds.number_of_vertices(), 1);
}
#[test]
fn basic_storage_methods_do_not_require_a_kernel() {
let mut tri: Triangulation<NotAKernel, String, String, 2> =
Triangulation::new_with_tds(NotAKernel, Tds::empty());
assert_eq!(tri.tds().number_of_vertices(), 0);
let stale_vertex = VertexKey::from(KeyData::from_ffi(0xDEAD_BEEF));
let stale_simplex = SimplexKey::from(KeyData::from_ffi(0xFEED_FACE));
assert!(
tri.set_vertex_data(stale_vertex, Some("vertex".to_owned()))
.is_err()
);
assert!(
tri.set_simplex_data(stale_simplex, Some("simplex".to_owned()))
.is_err()
);
let tds = tri.into_tds();
assert_eq!(tds.number_of_simplices(), 0);
}
#[test]
fn set_vertex_data_returns_error_for_invalid_key() {
let mut tri: Triangulation<FastKernel<f64>, i32, (), 2> =
Triangulation::new_empty(FastKernel::new());
let stale = VertexKey::from(KeyData::from_ffi(0xDEAD_BEEF));
let err = tri.set_vertex_data(stale, Some(42)).unwrap_err();
assert_matches!(err.as_tds_error(), TdsError::VertexNotFound { .. });
assert_eq!(tri.tds.number_of_vertices(), 0);
}
#[test]
fn set_simplex_data_returns_error_for_invalid_key() {
let mut tri: Triangulation<FastKernel<f64>, (), i32, 2> =
Triangulation::new_empty(FastKernel::new());
let stale = SimplexKey::from(KeyData::from_ffi(0xDEAD_BEEF));
let err = tri.set_simplex_data(stale, Some(42)).unwrap_err();
assert_matches!(err.as_tds_error(), TdsError::SimplexNotFound { .. });
assert_eq!(tri.tds.number_of_simplices(), 0);
}
}