#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(any(doc, doctest), doc = include_str!("../README.md"))]
#![expect(
clippy::multiple_crate_versions,
reason = "transitive dependency versions are controlled by upstream crates"
)]
#![forbid(unsafe_code)]
#[expect(
clippy::redundant_pub_crate,
reason = "`pub(crate)` keeps internal cross-module intent visible while `core` is private"
)]
mod core {
pub mod algorithms {
pub mod flips;
pub mod incremental_insertion;
pub mod locate;
pub(crate) mod pl_manifold_repair;
}
pub mod adjacency;
pub mod boundary;
pub mod simplex;
pub mod collections {
mod aliases;
mod buffers;
mod helpers;
mod key_maps;
mod secondary_maps;
mod triangulation_maps;
pub(crate) mod spatial_hash_grid;
pub(crate) use aliases::StorageMap;
pub use aliases::{
Entry, FacetIndex, FastBuildHasher, FastHashMap, FastHashSet, FastHasher,
MAX_PRACTICAL_DIMENSION_SIZE, SecureHashMap, SecureHashSet, SmallBuffer, Uuid,
};
pub use buffers::*;
pub use helpers::*;
pub use key_maps::*;
pub use secondary_maps::*;
pub use triangulation_maps::*;
}
pub mod construction;
pub mod edge;
pub mod facet;
pub mod insertion;
pub mod operations;
pub mod orientation;
pub mod query;
pub mod repair;
pub mod tds;
pub mod triangulation;
pub mod validation;
pub mod util {
pub(crate) mod canonical_points;
pub mod deduplication;
pub mod delaunay_validation;
pub mod facet_keys;
pub mod facet_utils;
pub mod hashing;
pub mod hilbert;
pub mod jaccard;
pub mod measurement;
pub mod uuid;
pub use deduplication::*;
pub use delaunay_validation::*;
pub use facet_keys::*;
pub use facet_utils::*;
pub use hashing::*;
pub use hilbert::*;
pub use jaccard::*;
pub use measurement::*;
pub use uuid::*;
}
pub mod vertex;
pub mod traits {
pub mod boundary_analysis;
pub mod data_type;
pub mod facet_cache;
pub use boundary_analysis::*;
pub use data_type::*;
}
}
pub mod geometry {
pub mod algorithms {
pub mod convex_hull;
pub use convex_hull::*;
}
#[macro_use]
pub mod matrix;
pub mod kernel;
pub mod point;
pub mod predicates;
pub mod quality;
pub mod robust_predicates;
pub mod sos;
pub mod util {
use crate::geometry::matrix::{MatrixError, StackMatrixDispatchError};
use crate::geometry::traits::coordinate::CoordinateConversionError;
use la_stack::LaError;
#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)]
#[non_exhaustive]
pub enum ValueConversionError {
#[error("Cannot convert {value} from {from_type} to {to_type}: {details}")]
ConversionFailed {
value: String,
from_type: &'static str,
to_type: &'static str,
details: String,
},
}
#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)]
#[non_exhaustive]
pub enum RandomPointGenerationError {
#[error("Invalid coordinate range: minimum {min} must be less than maximum {max}")]
InvalidRange {
min: String,
max: String,
},
#[error("Failed to generate random value in range [{min}, {max}]: {details}")]
RandomGenerationFailed {
min: String,
max: String,
details: String,
},
#[error("Invalid number of points: {n_points} (must be non-negative)")]
InvalidPointCount {
n_points: isize,
},
}
#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)]
#[non_exhaustive]
pub enum CircumcenterError {
#[error("Empty point set")]
EmptyPointSet,
#[error(
"Points do not form a valid simplex: expected {expected} points for dimension {dimension}, got {actual}"
)]
InvalidSimplex {
actual: usize,
expected: usize,
dimension: usize,
},
#[error("Matrix inversion failed: {details}")]
MatrixInversionFailed {
details: String,
},
#[error("Unsupported stack matrix dimension {requested} (maximum supported is {max})")]
UnsupportedMatrixDimension {
requested: usize,
max: usize,
},
#[error(
"Active matrix block size {active} does not match concrete matrix dimension {matrix_dimension}"
)]
MatrixDimensionMismatch {
active: usize,
matrix_dimension: usize,
},
#[error("Linear algebra failure: {source}")]
LinearAlgebraFailure {
#[from]
source: LaError,
},
#[error("Matrix error: {source}")]
MatrixError {
#[from]
source: MatrixError,
},
#[error("Array conversion failed: {details}")]
ArrayConversionFailed {
details: String,
},
#[error("Coordinate conversion error: {source}")]
CoordinateConversion {
#[from]
source: CoordinateConversionError,
},
#[error("Value conversion error: {source}")]
ValueConversion {
#[from]
source: ValueConversionError,
},
}
impl From<StackMatrixDispatchError> for CircumcenterError {
fn from(source: StackMatrixDispatchError) -> Self {
match source {
StackMatrixDispatchError::UnsupportedDim { k, max } => {
Self::UnsupportedMatrixDimension { requested: k, max }
}
StackMatrixDispatchError::ActiveBlockDimensionMismatch { k, dim } => {
Self::MatrixDimensionMismatch {
active: k,
matrix_dimension: dim,
}
}
StackMatrixDispatchError::La { source } => {
Self::LinearAlgebraFailure { source }
}
StackMatrixDispatchError::Matrix { source } => Self::MatrixError { source },
}
}
}
#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)]
#[non_exhaustive]
pub enum SurfaceMeasureError {
#[error("Failed to retrieve facet vertices: {0}")]
FacetError(#[from] crate::tds::FacetError),
#[error("Geometry computation failed: {0}")]
GeometryError(#[from] CircumcenterError),
}
pub mod circumsphere;
pub mod conversions;
pub mod measures;
pub mod norms;
pub mod point_generation;
pub mod triangulation_generation;
pub use circumsphere::*;
pub use conversions::*;
pub use measures::*;
pub use norms::*;
pub use point_generation::*;
pub use triangulation_generation::*;
}
pub mod traits {
pub mod coordinate;
pub use coordinate::*;
}
pub use algorithms::*;
pub use matrix::*;
pub use point::*;
pub use predicates::*;
pub use quality::*;
pub use traits::*;
pub use util::*;
}
#[path = "delaunay/builder.rs"]
pub mod builder;
#[path = "delaunay/construction.rs"]
pub mod construction;
#[path = "delaunay/query.rs"]
pub(crate) mod delaunay_query;
#[path = "delaunay/delaunayize.rs"]
pub mod delaunayize;
#[path = "delaunay/diagnostics.rs"]
pub mod diagnostics;
#[path = "delaunay/flips.rs"]
pub mod flips;
#[path = "delaunay/insertion.rs"]
pub(crate) mod insertion;
#[path = "delaunay/locality.rs"]
pub(crate) mod locality;
#[path = "delaunay/repair.rs"]
pub mod repair;
#[path = "delaunay/serialization.rs"]
pub(crate) mod serialization;
#[path = "delaunay/triangulation.rs"]
pub(crate) mod triangulation;
#[path = "delaunay/validation.rs"]
pub mod validation;
pub use crate::builder::DelaunayTriangulationBuilder;
pub use crate::construction::{
ConstructionOptions, ConstructionSkipSample, ConstructionSlowInsertionSample,
ConstructionStatistics, DedupPolicy, DelaunayConstructionFailure,
DelaunayConstructionRepairPhase, DelaunayTriangulationConstructionError,
DelaunayTriangulationConstructionErrorWithStatistics, InitialSimplexStrategy,
InsertionOrderStrategy, RetryPolicy,
};
pub use crate::core::algorithms::incremental_insertion::{
CavityFillingError, CavityRepairStage, DelaunayRepairErrorKind, DelaunayRepairErrorSummary,
DelaunayRepairFailureContext, HullExtensionReason, InitialSimplexConstructionError,
InsertionError, InsertionErrorKind, InsertionErrorSourceKind, InsertionErrorSummary,
NeighborRebuildError, NeighborWiringError, TdsConstructionFailure, TdsValidationFailure,
extend_hull, fill_cavity, repair_neighbor_pointers, repair_neighbor_pointers_local,
wire_cavity_neighbors,
};
pub use crate::core::algorithms::pl_manifold_repair::{
PlManifoldRepairError, PlManifoldRepairStats,
};
pub use crate::core::construction::TriangulationConstructionError;
pub use crate::core::insertion::DuplicateDetectionMetrics;
pub use crate::core::operations::{
InsertionOutcome, InsertionResult, InsertionStatistics, RepairDecision, RepairSkipReason,
SuspicionFlags, TopologicalOperation,
};
pub use crate::core::triangulation::Triangulation;
pub use crate::core::util::DeduplicationError;
pub use crate::core::util::{DelaunayValidationError, find_delaunay_violations};
#[cfg(feature = "diagnostics")]
pub use crate::core::util::{
DelaunayViolationDetail, DelaunayViolationReport, debug_print_first_delaunay_violation,
delaunay_violation_report,
};
pub use crate::core::validation::{
TopologyGuarantee, TriangulationValidationError, ValidationConfigurationError, ValidationPolicy,
};
pub use crate::repair::{
DelaunayCheckPolicy, DelaunayRepairHeuristicConfig, DelaunayRepairHeuristicSeeds,
DelaunayRepairOperation, DelaunayRepairOutcome, DelaunayRepairPolicy,
};
pub use crate::triangulation::*;
pub use crate::validation::DelaunayTriangulationValidationError;
pub mod topology {
pub mod traits {
pub(crate) mod global_topology_model;
pub mod topological_space;
pub use topological_space::*;
}
pub mod characteristics {
pub mod euler;
pub mod validation;
pub use euler::*;
pub use validation::*;
}
pub mod manifold;
pub mod spaces {
pub mod euclidean;
pub mod spherical;
pub mod toroidal;
pub use euclidean::EuclideanSpace;
pub use spherical::SphericalSpace;
pub use toroidal::ToroidalSpace;
}
pub use crate::TopologyGuarantee;
pub use characteristics::*;
pub use manifold::{
ManifoldError, validate_closed_boundary, validate_facet_degree, validate_ridge_links,
validate_vertex_links,
};
pub use traits::*;
}
pub mod collections {
pub use crate::core::collections::{
Entry, FacetIndex, FacetIssuesMap, FacetSharingSimplicesBuffer, FacetToSimplicesMap,
FacetVertexMap, FastBuildHasher, FastHashMap, FastHashSet, FastHasher, KeyBasedSimplexMap,
KeyBasedVertexMap, MAX_PRACTICAL_DIMENSION_SIZE, NeighborBuffer, PeriodicOffsetBuffer,
SecureHashMap, SecureHashSet, SimplexKeyBuffer, SimplexKeySet, SimplexNeighborsMap,
SimplexSecondaryMap, SimplexToVertexUuidsMap, SimplexVertexBuffer, SimplexVertexKeyBuffer,
SimplexVertexKeysMap, SimplexVertexUuidBuffer, SimplexVerticesMap, SmallBuffer, Uuid,
UuidToSimplexKeyMap, UuidToVertexKeyMap, VertexKeyBuffer, VertexKeySet, VertexSecondaryMap,
VertexToSimplicesMap, VertexUuidBuffer, VertexUuidSet, fast_hash_map_with_capacity,
fast_hash_set_with_capacity, small_buffer_with_capacity_2, small_buffer_with_capacity_8,
small_buffer_with_capacity_16,
};
pub mod algorithm_buffers {
pub use crate::core::collections::{
BadSimplexBuffer, CLEANUP_OPERATION_BUFFER_SIZE, CavityBoundaryBuffer, FacetInfoBuffer,
GeometricPointBuffer, PointBuffer, SimplexRemovalBuffer, ValidSimplicesBuffer,
ViolationBuffer,
};
}
}
pub mod tds {
pub use crate::core::adjacency::*;
pub use crate::core::collections::{
FacetIndex, FastHashMap, FastHashSet, NeighborBuffer, PeriodicOffsetBuffer,
SimplexKeyBuffer, SmallBuffer, Uuid,
};
pub use crate::core::edge::*;
pub use crate::core::facet::*;
pub use crate::core::simplex::*;
pub use crate::core::tds::*;
pub use crate::core::traits::facet_cache::*;
pub use crate::core::util::{
UuidValidationError, checked_facet_key_from_vertex_keys, facet_view_to_vertices,
facet_views_are_adjacent, format_jaccard_report, jaccard_distance, jaccard_index,
make_uuid, measure_with_result, stable_hash_u64_slice, usize_to_u8, validate_uuid,
verify_facet_index_consistency,
};
pub use crate::core::vertex::*;
}
pub mod algorithms {
#[cfg(any(feature = "diagnostics", all(test, debug_assertions)))]
pub use crate::core::algorithms::locate::verify_conflict_region_completeness;
pub use crate::core::algorithms::locate::{
ConflictError, InternalInconsistencySite, LocateError, LocateFallback,
LocateFallbackReason, LocateResult, LocateStats, extract_cavity_boundary,
find_conflict_region, locate, locate_with_stats,
};
}
pub mod query {
pub use crate::assert_jaccard_gte;
pub use crate::core::query::QueryError;
pub use crate::core::traits::boundary_analysis::BoundaryAnalysis;
pub use crate::core::traits::data_type::{
DataCopy, DataDebug, DataDeserialize, DataIdentity, DataSerde, DataSerialize, DataType,
};
pub use crate::core::util::{
JaccardComputationError, extract_edge_set, extract_facet_identifier_set,
extract_hull_facet_set, extract_vertex_coordinate_set, format_jaccard_report,
jaccard_distance, jaccard_index, measure_with_result,
};
pub use crate::geometry::Point;
pub use crate::geometry::algorithms::convex_hull::{
ConvexHull, ConvexHullConstructionError, ConvexHullValidationError,
};
pub use crate::geometry::kernel::{
AdaptiveKernel, ExactPredicates, FastKernel, Kernel, RobustKernel,
};
pub use crate::geometry::traits::coordinate::Coordinate;
pub use crate::geometry::{insphere, insphere_distance, insphere_lifted};
pub use crate::tds::{
AdjacencyIndex, AdjacencyIndexBuildError, EdgeKey, FacetView, Simplex, SimplexKey, Vertex,
VertexKey,
};
pub use crate::{DelaunayTriangulation, Triangulation};
}
pub mod prelude {
pub use crate::query::{
BoundaryAnalysis, DataCopy, DataDebug, DataDeserialize, DataIdentity, DataSerde,
DataSerialize, DataType, QueryError,
};
pub use crate::tds::*;
pub use crate::{
ConstructionOptions, ConstructionSkipSample, ConstructionSlowInsertionSample,
ConstructionStatistics, DedupPolicy, DelaunayCheckPolicy, DelaunayConstructionFailure,
DelaunayConstructionRepairPhase, DelaunayRepairHeuristicConfig,
DelaunayRepairHeuristicSeeds, DelaunayRepairOperation, DelaunayRepairOutcome,
DelaunayRepairPolicy, DelaunayTriangulation, DelaunayTriangulationBuilder,
DelaunayTriangulationConstructionError,
DelaunayTriangulationConstructionErrorWithStatistics, DelaunayTriangulationValidationError,
DuplicateDetectionMetrics, InitialSimplexStrategy, InsertionOrderStrategy, InsertionResult,
PlManifoldRepairError, PlManifoldRepairStats, RepairDecision, RepairSkipReason,
RetryPolicy, TopologicalOperation, TopologyGuarantee, Triangulation,
TriangulationConstructionError, TriangulationValidationError, ValidationConfigurationError,
ValidationPolicy,
};
pub use self::ordering::{
HilbertError, hilbert_index, hilbert_indices_prequantized, hilbert_quantize,
hilbert_sort_by_stable, hilbert_sort_by_unstable, hilbert_sorted_indices,
};
pub use crate::core::util::{
DeduplicationError, DelaunayValidationError, dedup_vertices_epsilon, dedup_vertices_exact,
filter_vertices_excluding, find_delaunay_violations, try_dedup_vertices_epsilon,
};
pub use crate::query::{
JaccardComputationError, extract_edge_set, extract_facet_identifier_set,
extract_hull_facet_set, extract_vertex_coordinate_set, format_jaccard_report,
jaccard_distance, jaccard_index, measure_with_result,
};
pub use crate::tds::{
UuidValidationError, checked_facet_key_from_vertex_keys, facet_view_to_vertices,
facet_views_are_adjacent, make_uuid, stable_hash_u64_slice, usize_to_u8, validate_uuid,
verify_facet_index_consistency,
};
pub use crate::algorithms::{
ConflictError, InternalInconsistencySite, LocateError, LocateFallback,
LocateFallbackReason, LocateResult, LocateStats, locate, locate_with_stats,
};
pub use crate::{
CavityFillingError, CavityRepairStage, DelaunayRepairErrorKind, DelaunayRepairErrorSummary,
DelaunayRepairFailureContext, HullExtensionReason, InitialSimplexConstructionError,
InsertionError, InsertionErrorKind, InsertionErrorSourceKind, InsertionErrorSummary,
NeighborRebuildError, NeighborWiringError, TdsConstructionFailure, TdsValidationFailure,
};
pub use crate::{InsertionOutcome, InsertionStatistics, SuspicionFlags};
pub use crate::flips::{
DelaunayRepairDiagnostics, DelaunayRepairError, DelaunayRepairStats,
DelaunayRepairVerificationContext, FlipContextError, FlipEdgeAdjacencyError, FlipError,
FlipMutationError, FlipNeighborWiringError, FlipPredicateError, FlipPredicateOperation,
FlipTriangleAdjacencyError, FlipVertexAdjacencyError, RepairQueueOrder,
};
pub use crate::collections::{
FacetToSimplicesMap, FastHashMap, FastHashSet, SecureHashMap, SecureHashSet,
SimplexNeighborsMap, SimplexSecondaryMap, SmallBuffer, VertexSecondaryMap,
VertexToSimplicesMap, fast_hash_map_with_capacity, fast_hash_set_with_capacity,
};
pub use crate::geometry::{
algorithms::*, kernel::*, matrix::*, point::*, predicates::*, quality::*,
robust_predicates::*, traits::coordinate::*, util::*,
};
pub mod construction {
pub use crate::builder::{
DelaunayTriangulationBuilder, ExplicitConstructionError,
ExplicitDelaunayValidationError, ExplicitDelaunayValidationErrorKind,
ExplicitDelaunayValidationSourceKind, ExplicitInsertionError,
ExplicitInsertionErrorKind, ExplicitInvariantError, ExplicitInvariantErrorKind,
ExplicitTdsError, ExplicitTdsErrorKind,
};
pub use crate::construction::{
ConstructionOptions, ConstructionSkipSample, ConstructionSlowInsertionSample,
ConstructionStatistics, DedupPolicy, DelaunayConstructionFailure,
DelaunayConstructionRepairPhase, DelaunayTriangulationConstructionError,
DelaunayTriangulationConstructionErrorWithStatistics, InitialSimplexStrategy,
InsertionOrderStrategy, RetryPolicy,
};
pub use crate::repair::DelaunayRepairPolicy;
pub use crate::tds::{
SimplexValidationError, Vertex, VertexBuilder, VertexBuilderError,
VertexValidationError,
};
pub use crate::topology::traits::{GlobalTopology, TopologyKind, ToroidalConstructionMode};
pub use crate::validation::DelaunayTriangulationValidationError;
pub use crate::{
CavityFillingError, CavityRepairStage, DelaunayTriangulation, TopologyGuarantee,
Triangulation, TriangulationConstructionError,
};
pub use crate::vertex;
}
pub mod triangulation {
pub use crate::collections::{FacetIssuesMap, SimplexKeyBuffer, SmallBuffer};
pub use crate::geometry::kernel::{
AdaptiveKernel, ExactPredicates, FastKernel, Kernel, RobustKernel,
};
pub use crate::geometry::point::Point;
pub use crate::query::{
AdjacencyIndex, AdjacencyIndexBuildError, BoundaryAnalysis, DataCopy, DataDebug,
DataDeserialize, DataIdentity, DataSerde, DataSerialize, DataType, EdgeKey, FacetView,
QueryError,
};
pub use crate::tds::{
FacetHandle, InvariantError, InvariantErrorSummary, InvariantErrorSummaryDetail,
InvariantErrorSummaryKind, NeighborSlot, Simplex, SimplexKey, Tds,
TdsConstructionError, TdsError, TdsErrorKind, TdsMutationError,
TriangulationValidationErrorKind, Vertex, VertexBuilder, VertexBuilderError, VertexKey,
};
pub use crate::{
InsertionError, TopologyGuarantee, Triangulation, TriangulationConstructionError,
TriangulationValidationError, ValidationConfigurationError, ValidationPolicy,
};
pub use crate::vertex;
}
pub mod flips {
pub use crate::DelaunayTriangulation;
pub use crate::collections::{MAX_PRACTICAL_DIMENSION_SIZE, SimplexKeyBuffer, SmallBuffer};
pub use crate::flips::{
BistellarFlipKind, BistellarFlips, FlipContextError, FlipDirection,
FlipEdgeAdjacencyError, FlipError, FlipInfo, FlipMutationError,
FlipNeighborWiringError, FlipPredicateError, FlipPredicateOperation,
FlipTriangleAdjacencyError, FlipVertexAdjacencyError, RidgeHandle, TriangleHandle,
};
pub use crate::flips::{BistellarMove, ConstK};
pub use crate::tds::{EdgeKey, FacetHandle, SimplexKey, VertexKey};
pub use crate::vertex;
}
pub mod insertion {
pub use crate::collections::SimplexKeyBuffer;
pub use crate::tds::FacetHandle;
pub use crate::tds::{SimplexKey, Tds, TdsMutationError, VertexKey};
pub use crate::{
CavityFillingError, CavityRepairStage, DelaunayRepairErrorKind,
DelaunayRepairErrorSummary, DelaunayRepairFailureContext, HullExtensionReason,
InitialSimplexConstructionError, InsertionError, InsertionErrorKind,
InsertionErrorSourceKind, InsertionErrorSummary, NeighborRebuildError,
NeighborWiringError, TdsConstructionFailure, TdsValidationFailure, extend_hull,
fill_cavity, repair_neighbor_pointers, repair_neighbor_pointers_local,
wire_cavity_neighbors,
};
pub use crate::{InsertionOutcome, InsertionResult, InsertionStatistics};
}
pub mod operations {
pub use crate::{
InsertionOutcome, InsertionResult, InsertionStatistics, RepairDecision,
RepairSkipReason, SuspicionFlags, TopologicalOperation,
};
}
pub mod repair {
pub use crate::flips::{
DelaunayRepairDiagnostics, DelaunayRepairError, DelaunayRepairStats,
DelaunayRepairVerificationContext, FlipContextError, FlipEdgeAdjacencyError, FlipError,
FlipMutationError, FlipNeighborWiringError, FlipPredicateError, FlipPredicateOperation,
FlipTriangleAdjacencyError, FlipVertexAdjacencyError, RepairQueueOrder,
verify_delaunay_for_triangulation, verify_delaunay_via_flip_predicates,
};
pub use crate::repair::{
DelaunayCheckPolicy, DelaunayRepairHeuristicConfig, DelaunayRepairHeuristicSeeds,
DelaunayRepairOutcome, DelaunayRepairPolicy,
};
pub use crate::{
DelaunayRepairErrorKind, DelaunayRepairErrorSummary, DelaunayRepairOperation,
DelaunayTriangulation, DelaunayTriangulationValidationError,
};
pub use crate::{DelaunayValidationError, find_delaunay_violations};
pub use crate::{
TopologyGuarantee, Triangulation, ValidationConfigurationError, ValidationPolicy,
};
}
pub mod delaunayize {
pub use crate::delaunayize::*;
pub use crate::{DelaunayTriangulation, DelaunayTriangulationBuilder};
pub use crate::{PlManifoldRepairError, PlManifoldRepairStats};
pub use crate::vertex;
}
pub mod validation {
pub use crate::validation::*;
pub use crate::{
DelaunayTriangulationValidationError, TopologyGuarantee, TriangulationValidationError,
ValidationConfigurationError, ValidationPolicy,
};
}
pub mod collections {
pub use crate::collections::{
Entry, FacetIndex, FacetIssuesMap, FacetSharingSimplicesBuffer, FacetToSimplicesMap,
FastBuildHasher, FastHashMap, FastHashSet, FastHasher, KeyBasedSimplexMap,
KeyBasedVertexMap, MAX_PRACTICAL_DIMENSION_SIZE, NeighborBuffer, PeriodicOffsetBuffer,
SecureHashMap, SecureHashSet, SimplexKeyBuffer, SimplexKeySet, SimplexNeighborsMap,
SimplexSecondaryMap, SimplexToVertexUuidsMap, SimplexVertexBuffer,
SimplexVertexKeyBuffer, SimplexVertexKeysMap, SimplexVertexUuidBuffer,
SimplexVerticesMap, SmallBuffer, Uuid, UuidToSimplexKeyMap, UuidToVertexKeyMap,
VertexKeyBuffer, VertexKeySet, VertexSecondaryMap, VertexToSimplicesMap,
VertexUuidBuffer, VertexUuidSet, fast_hash_map_with_capacity,
fast_hash_set_with_capacity, small_buffer_with_capacity_2,
small_buffer_with_capacity_8, small_buffer_with_capacity_16,
};
pub mod algorithm_buffers {
pub use crate::collections::algorithm_buffers::{
BadSimplexBuffer, CLEANUP_OPERATION_BUFFER_SIZE, CavityBoundaryBuffer,
FacetInfoBuffer, GeometricPointBuffer, PointBuffer, SimplexRemovalBuffer,
ValidSimplicesBuffer, ViolationBuffer,
};
}
}
pub mod tds {
pub use crate::collections::{
FacetIndex, FastHashMap, FastHashSet, NeighborBuffer, PeriodicOffsetBuffer,
SimplexKeyBuffer, SmallBuffer, Uuid,
};
pub use crate::tds::*;
}
pub mod geometry {
pub use crate::geometry::{
kernel::{AdaptiveKernel, ExactPredicates, FastKernel, Kernel, RobustKernel},
matrix::{Matrix, MatrixError, determinant},
point::Point,
predicates::{
InSphere, Orientation, insphere, insphere_distance, insphere_lifted,
simplex_orientation,
},
quality::{
QualityDegeneracyMeasure, QualityError, QualityNumericOperation,
QualitySimplexVerticesError, normalized_volume, radius_ratio,
},
robust_predicates::{
ConsistencyResult, InsphereConsistencyError, robust_insphere, robust_orientation,
},
traits::coordinate::{
Coordinate, CoordinateConversionError, CoordinateIdentity,
CoordinateRepresentation, CoordinateScalar, CoordinateValidationError,
DEFAULT_TOLERANCE_F32, DEFAULT_TOLERANCE_F64, DegenerateSimplexReason, FiniteCheck,
HashCoordinate, OrderedCmp, OrderedEq,
},
util::{
CircumcenterError, SurfaceMeasureError, ValueConversionError, circumcenter,
circumradius, circumradius_with_center, facet_measure, hypot, inradius,
safe_coords_from_f64, safe_coords_to_f64, safe_scalar_from_f64, safe_scalar_to_f64,
safe_usize_to_scalar, simplex_volume, squared_norm, surface_measure,
},
};
}
pub mod algorithms {
pub use crate::algorithms::{
ConflictError, InternalInconsistencySite, LocateError, LocateFallback,
LocateFallbackReason, LocateResult, LocateStats, extract_cavity_boundary,
find_conflict_region, locate, locate_with_stats,
};
}
pub mod diagnostics {
#[cfg(feature = "diagnostics")]
#[cfg_attr(docsrs, doc(cfg(feature = "diagnostics")))]
pub use crate::algorithms::verify_conflict_region_completeness;
pub use crate::diagnostics::{
BatchLocalRepairTrigger, ConstructionTelemetry, LocalRepairSample,
};
pub use crate::tds::NeighborSlot;
#[cfg(feature = "diagnostics")]
#[cfg_attr(docsrs, doc(cfg(feature = "diagnostics")))]
pub use crate::{
DelaunayViolationDetail, DelaunayViolationReport, debug_print_first_delaunay_violation,
delaunay_violation_report,
};
}
pub mod query {
pub use crate::tds::{
AdjacencyIndex, AdjacencyIndexBuildError, EdgeKey, SimplexKey, VertexKey,
};
pub use crate::{DelaunayTriangulation, Triangulation};
pub use crate::geometry::Point;
pub use crate::geometry::kernel::{
AdaptiveKernel, ExactPredicates, FastKernel, Kernel, RobustKernel,
};
pub use crate::geometry::traits::coordinate::Coordinate;
pub use crate::query::{
BoundaryAnalysis, DataCopy, DataDebug, DataDeserialize, DataIdentity, DataSerde,
DataSerialize, DataType, FacetView, QueryError, Simplex, Vertex,
};
pub use crate::geometry::{insphere, insphere_distance, insphere_lifted};
pub use crate::assert_jaccard_gte;
pub use crate::geometry::algorithms::convex_hull::{
ConvexHull, ConvexHullConstructionError, ConvexHullValidationError,
};
pub use crate::query::{
JaccardComputationError, extract_edge_set, extract_facet_identifier_set,
extract_hull_facet_set, extract_vertex_coordinate_set, format_jaccard_report,
jaccard_distance, jaccard_index,
};
pub use crate::query::measure_with_result;
pub use crate::vertex;
}
pub mod generators {
pub use crate::TopologyGuarantee;
pub use crate::construction::InsertionOrderStrategy;
pub use crate::geometry::util::{
RandomPointGenerationError, RandomTriangulationBuilder, generate_grid_points,
generate_poisson_points, generate_random_points, generate_random_points_in_ball,
generate_random_points_in_ball_seeded, generate_random_points_periodic,
generate_random_points_seeded, generate_random_triangulation,
generate_random_triangulation_with_topology_guarantee, scaled_bounds_by_point_count,
};
}
pub mod ordering {
pub use crate::core::util::{
HilbertError, hilbert_index, hilbert_indices_prequantized, hilbert_quantize,
hilbert_sort_by_stable, hilbert_sort_by_unstable, hilbert_sorted_indices,
};
}
pub mod topology {
pub mod validation {
pub use crate::topology::TopologyGuarantee;
pub use crate::topology::characteristics::{euler, validation};
pub use crate::topology::characteristics::{euler::*, validation::*};
pub use crate::topology::manifold::{
ManifoldError, validate_closed_boundary, validate_facet_degree,
validate_ridge_links, validate_ridge_links_for_simplices, validate_vertex_links,
};
pub use crate::topology::traits::*;
}
pub mod spaces {
pub use crate::topology::spaces::*;
pub use crate::topology::traits::{
GlobalTopology, TopologicalSpace, TopologyError, TopologyKind,
ToroidalConstructionMode,
};
}
}
pub use crate::vertex;
}
#[must_use]
pub const fn is_normal<T: Send + Sync + Unpin>() -> bool {
true
}
#[cfg(test)]
mod tests {
use crate::{
DelaunayTriangulation,
core::{
adjacency::AdjacencyIndex, edge::EdgeKey, simplex::Simplex, tds::Tds,
triangulation::Triangulation, vertex::Vertex,
},
geometry::{
Point, algorithms::convex_hull::ConvexHull, kernel::AdaptiveKernel, kernel::FastKernel,
util::CircumcenterError,
},
is_normal,
prelude::delaunayize::{
DelaunayTriangulationConstructionError, DelaunayizeConfig, DelaunayizeError,
DelaunayizeOutcome, PlManifoldRepairError, PlManifoldRepairStats,
SimplexValidationError,
},
prelude::repair::{
DelaunayCheckPolicy, DelaunayRepairError, DelaunayRepairOutcome, DelaunayRepairPolicy,
DelaunayRepairStats, DelaunayTriangulation as RepairDelaunayTriangulation,
FlipContextError, FlipError, RepairQueueOrder, TopologyGuarantee,
verify_delaunay_for_triangulation, verify_delaunay_via_flip_predicates,
},
prelude::*,
vertex,
};
use la_stack::LaError;
#[cfg(feature = "count-allocations")]
use allocation_counter::measure;
#[test]
fn normal_types() {
assert!(is_normal::<Point<f64, 3>>());
assert!(is_normal::<Point<f32, 3>>());
assert!(is_normal::<Vertex<f64, (), 3>>());
assert!(is_normal::<Simplex<f64, (), (), 4>>());
assert!(is_normal::<Tds<f64, (), (), 4>>());
assert!(is_normal::<Triangulation<FastKernel<f64>, (), (), 3>>());
assert!(is_normal::<DelaunayTriangulation<FastKernel<f64>, (), (), 3>>());
assert!(is_normal::<ConvexHull<FastKernel<f64>, (), (), 3>>());
assert!(is_normal::<EdgeKey>());
assert!(is_normal::<AdjacencyIndex>());
assert!(is_normal::<DelaunayizeConfig>());
assert!(is_normal::<DelaunayizeOutcome<f64, (), (), 3>>());
assert!(is_normal::<DelaunayizeError>());
assert!(is_normal::<DelaunayRepairError>());
assert!(is_normal::<DelaunayRepairStats>());
assert!(is_normal::<PlManifoldRepairError>());
assert!(is_normal::<PlManifoldRepairStats<f64, (), (), 3>>());
assert!(is_normal::<SimplexValidationError>());
assert!(is_normal::<DelaunayTriangulationConstructionError>());
}
#[test]
fn circumcenter_error_clones_linear_algebra_source() {
let source = LaError::Overflow { index: Some(2) };
let error = CircumcenterError::LinearAlgebraFailure { source };
assert_eq!(error.clone(), error);
assert!(error.to_string().contains("Linear algebra"));
}
#[test]
fn prelude_collections_exports() {
let mut map: FastHashMap<u64, usize> = FastHashMap::default();
map.insert(123, 456);
assert_eq!(map.get(&123), Some(&456));
let mut set: FastHashSet<u64> = FastHashSet::default();
set.insert(789);
assert!(set.contains(&789));
let mut buffer: SmallBuffer<i32, 8> = SmallBuffer::new();
buffer.push(42);
assert_eq!(buffer.len(), 1);
let map_with_cap = fast_hash_map_with_capacity::<u64, usize>(100);
assert!(map_with_cap.capacity() >= 100);
let set_with_cap = fast_hash_set_with_capacity::<u64>(50);
assert!(set_with_cap.capacity() >= 50);
let _facet_map: FacetToSimplicesMap = FacetToSimplicesMap::default();
let _neighbors: SimplexNeighborsMap = SimplexNeighborsMap::default();
let _vertex_simplices: VertexToSimplicesMap = VertexToSimplicesMap::default();
}
#[test]
fn prelude_repair_exports() {
let vertices = vec![
vertex!([0.0, 0.0]),
vertex!([1.0, 0.0]),
vertex!([0.0, 1.0]),
];
let dt: RepairDelaunayTriangulation<_, (), (), 2> =
RepairDelaunayTriangulation::new(&vertices).unwrap();
let kernel = AdaptiveKernel::<f64>::new();
assert!(verify_delaunay_for_triangulation(dt.as_triangulation()).is_ok());
assert!(verify_delaunay_via_flip_predicates(dt.tds(), &kernel).is_ok());
let stats = DelaunayRepairStats::default();
let outcome = DelaunayRepairOutcome {
stats: stats.clone(),
heuristic: None,
};
assert_eq!(outcome.stats.flips_performed, stats.flips_performed);
let order = RepairQueueOrder::Fifo;
assert!(matches!(order, RepairQueueOrder::Fifo));
assert_eq!(
DelaunayRepairPolicy::default(),
DelaunayRepairPolicy::EveryInsertion
);
assert_eq!(DelaunayCheckPolicy::default(), DelaunayCheckPolicy::EndOnly);
let err = DelaunayRepairError::from(FlipError::DegenerateSimplex);
assert!(matches!(err, DelaunayRepairError::Flip { .. }));
let context_err = FlipContextError::ReplacementPeriodicOffsetCountMismatch {
simplex_count: 1,
offset_count: 0,
};
assert!(matches!(
context_err,
FlipContextError::ReplacementPeriodicOffsetCountMismatch { .. }
));
let topo = TopologyGuarantee::PLManifold;
assert!(matches!(topo, TopologyGuarantee::PLManifold));
}
#[test]
fn prelude_quality_exports() {
let vertices = vec![
vertex!([0.0, 0.0]),
vertex!([1.0, 0.0]),
vertex!([0.0, 1.0]),
];
let dt: DelaunayTriangulation<_, (), (), 2> =
DelaunayTriangulation::new(&vertices).unwrap();
let (simplex_key, _) = dt.simplices().next().unwrap();
let ratio = radius_ratio(dt.as_triangulation(), simplex_key).unwrap();
assert!(ratio > 0.0);
let norm_vol = normalized_volume(dt.as_triangulation(), simplex_key).unwrap();
assert!(norm_vol > 0.0);
}
#[test]
fn test_prelude_kernel_exports() {
let fast_kernel = FastKernel::<f64>::new();
let robust_kernel = RobustKernel::<f64>::new();
let triangle = [
Point::new([0.0, 0.0]),
Point::new([1.0, 0.0]),
Point::new([0.0, 1.0]),
];
let fast_orientation = fast_kernel.orientation(&triangle).unwrap();
assert_ne!(fast_orientation, 0, "Triangle should be non-degenerate");
let robust_orientation = robust_kernel.orientation(&triangle).unwrap();
assert_eq!(
fast_orientation, robust_orientation,
"Both kernels should agree"
);
let collinear = [
Point::new([0.0, 0.0]),
Point::new([1.0, 0.0]),
Point::new([2.0, 0.0]),
];
assert_eq!(
fast_kernel.orientation(&collinear).unwrap(),
0,
"Collinear points should have zero orientation"
);
let inside_point = Point::new([0.25, 0.25]);
let result = fast_kernel.in_sphere(&triangle, &inside_point).unwrap();
assert_eq!(result, 1, "Point should be inside circumcircle");
let outside_point = Point::new([2.0, 2.0]);
let result = fast_kernel.in_sphere(&triangle, &outside_point).unwrap();
assert_eq!(result, -1, "Point should be outside circumcircle");
}
#[test]
fn test_prelude_core_types() {
let p1 = Point::new([0.0, 0.0, 0.0]);
let p2 = Point::new([1.0, 0.0, 0.0]);
assert_ne!(p1, p2);
let v1: Vertex<f64, (), 3> = vertex!([0.0, 0.0, 0.0]);
let v2: Vertex<f64, (), 3> = vertex!([1.0, 0.0, 0.0]);
assert_ne!(v1.point(), v2.point());
let vertices = vec![
vertex!([0.0, 0.0, 0.0]),
vertex!([1.0, 0.0, 0.0]),
vertex!([0.0, 1.0, 0.0]),
vertex!([0.0, 0.0, 1.0]),
];
let dt: DelaunayTriangulation<_, (), (), 3> =
DelaunayTriangulation::new(&vertices).unwrap();
assert_eq!(dt.number_of_vertices(), 4);
assert_eq!(dt.number_of_simplices(), 1);
let tri = dt.as_triangulation();
assert_eq!(tri.number_of_vertices(), 4);
let tds = &tri.tds;
assert_eq!(tds.number_of_simplices(), 1);
for (simplex_key, _simplex) in tri.simplices() {
assert!(tds.simplex(simplex_key).is_some());
}
}
#[test]
fn test_prelude_point_location() {
let vertices = vec![
vertex!([0.0, 0.0]),
vertex!([1.0, 0.0]),
vertex!([0.0, 1.0]),
];
let dt: DelaunayTriangulation<_, (), (), 2> =
DelaunayTriangulation::new(&vertices).unwrap();
let kernel = FastKernel::<f64>::new();
let query_point = Point::new([0.3, 0.3]);
let result = locate(dt.tds(), &kernel, &query_point, None);
assert!(result.is_ok());
match result.unwrap() {
LocateResult::InsideSimplex(_)
| LocateResult::OnFacet { .. }
| LocateResult::OnEdge { .. }
| LocateResult::OnVertex(_) => { }
LocateResult::Outside => panic!("Point should be inside triangulation"),
}
let outside_point = Point::new([10.0, 10.0]);
let result = locate(dt.tds(), &kernel, &outside_point, None);
assert!(result.is_ok());
}
#[test]
fn test_prelude_geometry_types() {
let p = Point::new([1.0_f64, 2.0_f64, 3.0_f64]);
assert!((p.coords()[0] - 1.0_f64).abs() < f64::EPSILON);
assert!((p.coords()[1] - 2.0_f64).abs() < f64::EPSILON);
assert!((p.coords()[2] - 3.0_f64).abs() < f64::EPSILON);
let triangle = [
Point::new([0.0, 0.0]),
Point::new([1.0, 0.0]),
Point::new([0.0, 1.0]),
];
let orientation = simplex_orientation(&triangle).unwrap();
assert_ne!(orientation, Orientation::DEGENERATE);
let test_point = Point::new([0.25, 0.25]);
let result = insphere(&triangle, test_point).unwrap();
assert_eq!(result, InSphere::INSIDE);
}
#[test]
fn test_prelude_convex_hull() {
let vertices = vec![
vertex!([0.0, 0.0, 0.0]),
vertex!([1.0, 0.0, 0.0]),
vertex!([0.0, 1.0, 0.0]),
vertex!([0.0, 0.0, 1.0]),
];
let dt: DelaunayTriangulation<_, (), (), 3> =
DelaunayTriangulation::new(&vertices).unwrap();
let hull = ConvexHull::from_triangulation(dt.as_triangulation()).unwrap();
assert_eq!(hull.number_of_facets(), 4);
let outside_point = Point::new([2.0, 2.0, 2.0]);
let is_outside = hull
.is_point_outside(&outside_point, dt.as_triangulation())
.unwrap();
assert!(is_outside);
let inside_point = Point::new([0.25, 0.25, 0.25]);
let is_outside = hull
.is_point_outside(&inside_point, dt.as_triangulation())
.unwrap();
assert!(!is_outside);
}
#[cfg(feature = "count-allocations")]
#[test]
fn basic_alloc_counting() {
let result = measure(|| {
let x = 1 + 1;
assert_eq!(x, 2);
});
assert_eq!(
result.count_total, 0,
"Expected zero total allocations for trivial operation, found: {}",
result.count_total
);
assert_eq!(
result.bytes_total, 0,
"Expected zero total bytes allocated for trivial operation, found: {}",
result.bytes_total
);
assert_eq!(
result.count_current, 0,
"Expected zero current allocations after trivial operation, found: {}",
result.count_current
);
assert_eq!(
result.bytes_current, 0,
"Expected zero current bytes allocated after trivial operation, found: {}",
result.bytes_current
);
}
#[cfg(feature = "count-allocations")]
#[test]
fn alloc_counting_with_vec() {
let result = measure(|| {
let _vec: Vec<i32> = vec![1, 2, 3, 4, 5];
});
assert!(
result.count_total > 0,
"Expected some allocations for Vec creation, found: {}",
result.count_total
);
assert!(
result.bytes_total > 0,
"Expected some bytes allocated for Vec creation, found: {}",
result.bytes_total
);
assert_eq!(
result.count_current, 0,
"Expected zero current allocations after Vec drop, found: {}",
result.count_current
);
assert_eq!(
result.bytes_current, 0,
"Expected zero current bytes after Vec drop, found: {}",
result.bytes_current
);
assert!(
result.count_max >= result.count_total,
"Max count should be >= total count"
);
assert!(
result.bytes_max >= result.bytes_total,
"Max bytes should be >= total bytes"
);
}
}