pub enum ConvexHullError {
InternalError(&'static str),
MissingSupportPoint,
IncompleteInput,
Unreachable,
UnfinishedTriangle,
TJunction(usize, u32, u32),
DuplicatePoints(usize, usize),
}Expand description
Errors that can occur during convex hull computation.
When computing the convex hull of a set of points using convex_hull or try_convex_hull,
various problems can arise due to invalid input data or numerical issues. This enum describes
all possible error conditions.
§Overview
Convex hull computation uses incremental algorithms that build the hull by adding points one at a time. The algorithm can fail if the input is degenerate (too few points, collinear/coplanar points) or contains invalid data (NaN values, duplicates).
§Common Causes and Solutions
§Input Validation Issues
- Too few points: Need at least 4 non-coplanar points for 3D, or 3 non-collinear points for 2D
- Invalid coordinates: Check for NaN or infinite values in your point data
- Duplicate points: Remove duplicate points before computing the hull
- Degenerate geometry: Ensure points are not all collinear (2D) or coplanar (3D)
§How to Handle Errors
use parry3d::transformation::{try_convex_hull, ConvexHullError};
use nalgebra::Point3;
let points = vec![
Point3::origin(),
Point3::new(1.0, 0.0, 0.0),
Point3::new(0.0, 1.0, 0.0),
Point3::new(0.0, 0.0, 1.0),
];
match try_convex_hull(&points) {
Ok((vertices, indices)) => {
println!("Successfully computed hull with {} faces", indices.len());
}
Err(ConvexHullError::IncompleteInput) => {
println!("Not enough points provided (need at least 4 in 3D)");
}
Err(ConvexHullError::MissingSupportPoint) => {
println!("Points are invalid (NaN) or nearly coplanar");
// Try removing duplicate points or checking for degeneracies
}
Err(ConvexHullError::DuplicatePoints(i, j)) => {
println!("Points {} and {} are duplicates", i, j);
// Remove duplicates and try again
}
Err(err) => {
println!("Unexpected error: {}", err);
}
}Variants§
InternalError(&'static str)
An internal error occurred during convex hull computation.
This indicates a bug in the convex hull algorithm itself. If you encounter this error, please report it as a bug with a minimal reproducible example.
§Example
match try_convex_hull(&points) {
Err(ConvexHullError::InternalError(msg)) => {
eprintln!("Bug in convex hull algorithm: {}", msg);
// This should not happen - please report this!
}
_ => {}
}MissingSupportPoint
The algorithm could not find a valid support point.
This error occurs when:
- The input contains points with NaN or infinite coordinates
- All points are nearly collinear (in 2D) or coplanar (in 3D)
- The numerical precision is insufficient to distinguish between points
§Common Causes
- NaN values: Check your input data for NaN coordinates
- Nearly flat geometry: Points lie almost on a line (2D) or plane (3D)
- Numerical precision: Points are too close together relative to floating-point precision
IncompleteInput
Not enough points were provided to compute a convex hull.
A convex hull requires:
- 3D (dim3): At least 4 non-coplanar points to form a tetrahedron
- 2D (dim2): At least 3 non-collinear points to form a triangle
Providing fewer points than this minimum results in this error.
§Example
use parry3d::transformation::{try_convex_hull, ConvexHullError};
use nalgebra::Point3;
// Only 2 points - not enough for 3D hull
let points = vec![
Point3::origin(),
Point3::new(1.0, 0.0, 0.0),
];
match try_convex_hull(&points) {
Err(ConvexHullError::IncompleteInput) => {
println!("Need at least 4 points for 3D convex hull");
}
_ => {}
}Unreachable
Internal error: reached an unreachable code path.
This should never happen and indicates a serious bug in the implementation. If you encounter this, please report it with your input data.
UnfinishedTriangle
A triangle in the hull was not properly constructed.
This is an internal consistency error that indicates the algorithm failed to maintain the correct half-edge topology during hull construction.
This is likely caused by numerical precision issues or edge cases in the input geometry.
TJunction(usize, u32, u32)
Detected a T-junction in the hull topology.
A T-junction occurs when an edge has more than two adjacent faces, which violates the manifold property required for a valid convex hull. This is an internal error that shouldn’t occur with valid convex hull computation.
The error reports:
0: The triangle index where the T-junction was detected1,2: The vertex indices forming the problematic edge
§Example
match try_convex_hull(&points) {
Err(ConvexHullError::TJunction(tri_id, v1, v2)) => {
eprintln!("T-junction at triangle {} on edge ({}, {})", tri_id, v1, v2);
}
_ => {}
}DuplicatePoints(usize, usize)
The input contains duplicate points at the same location.
This error is raised during validation when two points have identical coordinates. Duplicate points can cause issues with the hull topology and should be removed before computing the hull.
The error reports the indices of the two duplicate points.
§How to Fix
Remove duplicate points from your input data:
use parry3d::transformation::try_convex_hull;
use nalgebra::Point3;
use std::collections::HashSet;
let points = vec![
Point3::origin(),
Point3::new(1.0, 0.0, 0.0),
Point3::new(0.0, 1.0, 0.0),
Point3::new(0.0, 0.0, 1.0),
Point3::origin(), // Duplicate!
];
// Remove duplicates (note: this is a simple example, not production code)
fn remove_duplicates(points: Vec<Point3<f32>>) -> Vec<Point3<f32>> {
let mut seen = Vec::new();
let mut result = Vec::new();
for pt in points {
if !seen.iter().any(|&p: &Point3<f32>| (p - pt).norm() < 1e-6) {
seen.push(pt);
result.push(pt);
}
}
result
}
let unique_points = remove_duplicates(points);
assert!(try_convex_hull(&unique_points).is_ok());Trait Implementations§
Source§impl Debug for ConvexHullError
impl Debug for ConvexHullError
Source§impl Display for ConvexHullError
impl Display for ConvexHullError
Source§impl Error for ConvexHullError
impl Error for ConvexHullError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
Source§impl PartialEq for ConvexHullError
impl PartialEq for ConvexHullError
impl StructuralPartialEq for ConvexHullError
Auto Trait Implementations§
impl Freeze for ConvexHullError
impl RefUnwindSafe for ConvexHullError
impl Send for ConvexHullError
impl Sync for ConvexHullError
impl Unpin for ConvexHullError
impl UnwindSafe for ConvexHullError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.