pub struct Mesh { /* private fields */ }Expand description
A closed surface as triangles, in metres.
§STL carries no topology, and that shapes what can be checked
The format is a flat list of facets, each with its three vertices written out in full. Two triangles
sharing an edge repeat those two vertices, and nothing in the file says they are the same points. So
Mesh::is_closed has to infer the topology by matching coordinates, and it matches them exactly —
bit for bit.
That is the right strictness for the thing being asked. A mesh whose shared vertices differ in the last bit is not closed for any purpose that matters here: a ray can pass between the two triangles, and the rasteriser below will see it. Reporting it as open is the true answer, and a tolerance would turn a real defect into a silent one.
Implementations§
Source§impl Mesh
impl Mesh
Sourcepub fn from_stl(bytes: &[u8]) -> Result<Mesh, String>
pub fn from_stl(bytes: &[u8]) -> Result<Mesh, String>
Read an STL, binary or ASCII.
§Which one it is, decided by arithmetic rather than by the first word
The usual test is whether the file starts with solid, and it is wrong: a binary STL’s header is
eighty arbitrary bytes and plenty of exporters write solid into it. The reliable test is the
length — a binary file is exactly 84 + 50n bytes for its own declared n, and no ASCII file of
that content is. This uses that, and falls back to ASCII.
Lengths are taken as millimetres, because STL has no units and every mechanical CAD tool writes millimetres. That is a convention rather than a fact about the format, so it is stated here and nowhere else has to guess.
Sourcepub fn bounds(&self) -> Option<(LengthVec, LengthVec)>
pub fn bounds(&self) -> Option<(LengthVec, LengthVec)>
The axis-aligned bounds, as (low, high).
None for a mesh with no triangles, because the bounds of nothing are not a box at the origin.
Sourcepub fn volume(&self) -> Volume
pub fn volume(&self) -> Volume
The enclosed volume, by the divergence theorem.
Σ a · (b × c) / 6 — the signed volume of the tetrahedron each triangle makes with the origin,
summed. Everything outside the surface cancels exactly, so for a closed mesh this is the
enclosed volume and it is exact to floating point, with no tolerance and no sampling.
That exactness is what makes it the reference Loss::volume_error measures
against: comparing a rasterisation to an analytic sphere would conflate two errors, the
tessellation’s and the grid’s. Comparing it to the mesh’s own volume isolates the one being
measured.
For an open mesh the number is meaningless rather than approximate — check Mesh::is_closed.
A negative volume means the winding is inside out, which is a real and common export defect.
Sourcepub fn is_closed(&self) -> bool
pub fn is_closed(&self) -> bool
Whether every edge is shared by exactly two triangles.
Matched on the vertices’ bit patterns, for the reason in this type’s documentation: STL stores no topology, so shared vertices are shared only if they were written identically, and a ray passes through a gap of one bit as readily as through a gap of one millimetre.
With one exception, and it is not a tolerance. Negative zero is folded onto zero, because
-0.0 and 0.0 are the same point — the distance between them is nothing, and no ray passes
between them. Their bit patterns differ, so a raw comparison reports a watertight mesh as open,
and that is a false alarm rather than a strict answer. It arises constantly on anything symmetric
about an axis, where one side’s coordinate is a product that happened to carry a minus sign.
A mesh that is not closed has no enclosed volume and cannot be rasterised by parity, so
Voxels::of refuses one rather than producing a shape with holes in it.
Sourcepub fn triangles_below(&self, cell: Length) -> usize
pub fn triangles_below(&self, cell: Length) -> usize
How many triangles are smaller than one face of a cell of side cell.
A feature the grid cannot hold, counted before anything is rasterised. It is not a proof that something is lost — a large flat face can be tessellated into small triangles and lose nothing — but a mesh where many facets are below the cell’s own area is a mesh whose detail is finer than the grid, and that is worth being told before the run rather than after.