pub struct Triangulation {
pub positions: Vec<Point>,
pub normals: Vec<Vector>,
pub parameters: Vec<(f64, f64)>,
pub triangles: Vec<[u32; 3]>,
pub deflection_met: bool,
}Expand description
A triangulated surface.
Vertices carry their parameters as well as their positions, so a caller can ask the exact surface about a triangulated point rather than only the approximation.
Fields§
§positions: Vec<Point>Vertex positions.
normals: Vec<Vector>Outward unit normals, one per vertex.
parameters: Vec<(f64, f64)>The surface parameters each vertex came from.
triangles: Vec<[u32; 3]>Triangles, as indices into the vertex arrays, wound counter-clockwise about the outward normal.
deflection_met: boolWhether every face met its requested deflection.
Implementations§
Source§impl Triangulation
impl Triangulation
Sourcepub fn vertex_count(&self) -> usize
pub fn vertex_count(&self) -> usize
Number of vertices.
Sourcepub fn triangle_count(&self) -> usize
pub fn triangle_count(&self) -> usize
Number of triangles.
Sourcepub fn area(&self) -> f64
pub fn area(&self) -> f64
The total area of the triangles.
An underestimate of the surface’s own area for a convex patch, since a triangle chord-cuts the surface it spans. It converges from below as the deflection tightens.
Sourcepub fn volume(&self) -> f64
pub fn volume(&self) -> f64
The signed volume enclosed, by the divergence theorem.
Meaningful only for a mesh that is closed and consistently wound
outward: each triangle contributes the signed volume of the tetrahedron
it forms with the origin, and the contributions cancel except over the
enclosed region. An open mesh gives a number with no meaning, and a mesh
wound inward gives the negative, which is why
Triangulation::is_closed exists to be asked first.
Sourcepub fn is_closed(&self) -> bool
pub fn is_closed(&self) -> bool
Whether every triangle edge is crossed as often one way as the other.
The mesh equivalent of a closed shell, and the precondition for
Triangulation::volume meaning anything. It is exactly what the
divergence theorem needs: the surface has no boundary, and it is
wound consistently, so each triangle’s contribution cancels against
its neighbours’ except over the region enclosed.
Counting directed edges rather than undirected ones is what makes this the right question, and it is stricter and looser than the obvious test in the two different ways that matter.
Stricter: two triangles sharing an edge and winding the same way round it traverse it twice in the same direction. The edge is used twice, so a count of uses calls it closed, and the volume that comes out is wrong because one of the two faces is inside out.
Looser: an edge may legitimately carry four triangles. Where two faces meet along a short edge that discretizes into several segments, each can fill the sliver between the polyline and its own chord, and the chord then belongs to both: four triangles round one edge, two crossing each way. There is no hole there and the volume is right; demanding exactly two refuses a mesh for being non-manifold when nothing was asked about manifoldness. Sixty-four bodies of one real assembly were refused that way, forty-four of them for this alone.
This also agrees with the topology side at last:
is_shell_closed counts an
edge’s uses and accepts any even number, and the two halves of the
kernel should not mean different things by the same word.
Sourcepub fn border_welded(&self, reach: f64) -> Self
pub fn border_welded(&self, reach: f64) -> Self
Weld only the mesh’s border vertices, within reach.
The second pass after Triangulation::welded: interior edges are
already manifold, and touching them at a widened tolerance would eat
real features. Borders are where imported slop lives (an edge’s curve
and its neighbour’s disagree by the file’s own tolerance, which the
model records on the edge), so only vertices on unmatched triangle
edges are candidates, merged to their nearest counterpart within
reach.
Sourcepub fn border_stitched(&self, reach: f64) -> Self
pub fn border_stitched(&self, reach: f64) -> Self
Split border segments at border vertices that lie on them.
The T-junction repair that follows Triangulation::border_welded:
after welding, two faces’ border chains share their vertices but may
subdivide the same stretch differently: one face’s segment spans two
of its neighbour’s. Splitting the long segment at the neighbour’s own
vertex index makes the chains segment-for-segment identical, which is
what closure counts. No positions move and none are added.
Sourcepub fn sealed(&self, width: f64) -> Self
pub fn sealed(&self, width: f64) -> Self
This mesh with its folds cancelled and its cracks sealed: the last pass over a mesh welded from faces that each met their edges.
A fold is two triangles on the same three vertices facing opposite
ways, left where a sliver face collapses in the weld; they enclose
nothing, and both go. A crack is a loop of border edges whose mean
width (twice its area over its perimeter) is within width: two
faces sampling a shared corner differently leave one, narrower than
the chord they were drawn to. It is fanned shut from one of its
corners, each new triangle crossing a border edge the other way from
the triangle already on it. A loop wider than that, or a border
vertex with more than one way on, is a real opening and stays.
Sourcepub fn welded(&self, tol: Tolerances) -> Self
pub fn welded(&self, tol: Tolerances) -> Self
Merge vertices that coincide within tol, rewiring the triangles.
Faces are triangulated independently, so a shared edge produces two
copies of every boundary vertex, at identical positions, since both
came from the same edge discretization, but as separate entries. Merging
them is what turns a pile of face meshes into one closed surface, and
what lets Triangulation::is_closed answer truthfully.
Trait Implementations§
Source§impl Clone for Triangulation
impl Clone for Triangulation
Source§fn clone(&self) -> Triangulation
fn clone(&self) -> Triangulation
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for Triangulation
impl Debug for Triangulation
Source§impl Default for Triangulation
impl Default for Triangulation
Source§fn default() -> Triangulation
fn default() -> Triangulation
Source§impl PartialEq for Triangulation
impl PartialEq for Triangulation
Source§fn eq(&self, other: &Triangulation) -> bool
fn eq(&self, other: &Triangulation) -> bool
self and other values to be equal, and is used by ==.impl StructuralPartialEq for Triangulation
Auto Trait Implementations§
impl Freeze for Triangulation
impl RefUnwindSafe for Triangulation
impl Send for Triangulation
impl Sync for Triangulation
impl Unpin for Triangulation
impl UnsafeUnpin for Triangulation
impl UnwindSafe for Triangulation
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,
impl<T> Scalar for T
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read more§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).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.