pub enum MeshIntersectionError {
MissingTopology,
MissingPseudoNormals,
TriTriError,
DuplicateVertices,
TriangulationError,
TriMeshBuilderError(TriMeshBuilderError),
}Expand description
Errors that can occur when computing the boolean intersection of two triangle meshes.
The intersect_meshes function computes the geometric intersection of two triangle meshes,
producing a new mesh that represents their overlapping volume. This operation requires both
input meshes to have certain properties and can fail for various reasons.
§Prerequisites for Mesh Intersection
Both input meshes must have:
- Topology information: Half-edge data structure for adjacency information
- Pseudo-normals: For robust inside/outside testing
These are enabled by setting the TriMeshFlags::ORIENTED flag when creating the mesh.
Variants§
MissingTopology
One or both meshes are missing topology information.
Mesh intersection requires half-edge topology data to determine adjacency
relationships between triangles. This information is automatically computed
when you create a mesh with the TriMeshFlags::ORIENTED flag.
§How to Fix
// Instead of:
// let mesh = TriMesh::new(vertices, indices)?;
// Use ORIENTED flag:
let mesh = TriMesh::with_flags(
vertices,
indices,
TriMeshFlags::ORIENTED
).unwrap();§Alternative
You can also add topology to an existing mesh:
let mut mesh = TriMesh::new(vertices, indices).unwrap();
mesh.set_flags(TriMeshFlags::ORIENTED).unwrap();MissingPseudoNormals
One or both meshes are missing pseudo-normal information.
Pseudo-normals are weighted normals used for robust point-in-mesh testing,
which is essential for determining which parts of the meshes are inside or
outside each other during intersection. They are computed when using the
TriMeshFlags::ORIENTED flag.
§Background
Mesh intersection needs to determine which triangles from each mesh are inside, outside, or intersecting the other mesh. This requires reliable point containment tests, which use pseudo-normals as described in:
“Signed distance computation using the angle weighted pseudonormal” by Baerentzen et al., DOI: 10.1109/TVCG.2005.49
§How to Fix
Use the same solution as MissingTopology - create your
meshes with TriMeshFlags::ORIENTED.
TriTriError
Internal failure while computing the intersection between two triangles.
This error occurs when the triangle-triangle intersection algorithm encounters a case it cannot handle, typically due to:
- Degenerate triangles (zero area, collinear vertices)
- Numerical precision issues with nearly-parallel triangles
- Edge cases in the intersection geometry
§What to Try
- Check your input meshes for degenerate triangles
- Try using
TriMeshFlags::DELETE_DEGENERATE_TRIANGLESwhen creating meshes - Ensure your mesh has reasonable numeric precision (not too small or too large coordinates)
- Consider using
intersect_meshes_with_toleranceswith custom tolerances
DuplicateVertices
Internal failure while merging vertices from triangle intersections.
After computing triangle-triangle intersections, the algorithm merges nearby vertices to create a clean mesh. This error occurs when the merging process detects inconsistencies, usually caused by:
- Numerical precision issues causing vertices to appear in wrong positions
- Complex intersection patterns that create ambiguous vertex relationships
§What to Try
- Use
intersect_meshes_with_toleranceswith larger tolerances - Simplify your input meshes if they have very high triangle counts
- Check for and remove nearly-degenerate triangles
TriangulationError
Internal failure while triangulating an intersection face.
The intersection of two meshes can create non-triangular polygonal faces that must be triangulated. This error occurs when the triangulation algorithm fails, typically due to:
- Self-intersecting intersection polygons
- Numerical issues creating invalid polygon geometry
- Very complex intersection patterns
This often happens with grazing intersections or when meshes have very different triangle sizes at the intersection boundary.
TriMeshBuilderError(TriMeshBuilderError)
The resulting intersection mesh could not be constructed.
After computing all triangle intersections and creating the intersection geometry,
the final mesh construction failed. This wraps errors from TriMeshBuilderError
and typically indicates:
- The intersection resulted in invalid mesh topology
- No triangles in the intersection (meshes don’t overlap)
- Topology violations in the computed intersection
See TriMeshBuilderError for details on the specific failure.
Trait Implementations§
Source§impl Clone for MeshIntersectionError
impl Clone for MeshIntersectionError
Source§fn clone(&self) -> MeshIntersectionError
fn clone(&self) -> MeshIntersectionError
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for MeshIntersectionError
impl Debug for MeshIntersectionError
Source§impl Display for MeshIntersectionError
impl Display for MeshIntersectionError
Source§impl Error for MeshIntersectionError
impl Error for MeshIntersectionError
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 From<TriMeshBuilderError> for MeshIntersectionError
impl From<TriMeshBuilderError> for MeshIntersectionError
Source§fn from(value: TriMeshBuilderError) -> Self
fn from(value: TriMeshBuilderError) -> Self
Source§impl PartialEq for MeshIntersectionError
impl PartialEq for MeshIntersectionError
impl Copy for MeshIntersectionError
impl Eq for MeshIntersectionError
impl StructuralPartialEq for MeshIntersectionError
Auto Trait Implementations§
impl Freeze for MeshIntersectionError
impl RefUnwindSafe for MeshIntersectionError
impl Send for MeshIntersectionError
impl Sync for MeshIntersectionError
impl Unpin for MeshIntersectionError
impl UnwindSafe for MeshIntersectionError
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.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.