Skip to main content

Mesh

Struct Mesh 

Source
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

Source

pub fn new(triangles: Vec<Triangle>) -> Mesh

A mesh from triangles, in metres.

Source

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.

Source

pub fn triangles(&self) -> &[Triangle]

The triangles, in the order read.

Source

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.

Source

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.

Source

pub fn area(&self) -> Area

The total surface area.

Source

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.

Source

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.

Trait Implementations§

Source§

impl Clone for Mesh

Source§

fn clone(&self) -> Mesh

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Mesh

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Mesh

Source§

fn default() -> Mesh

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Mesh

§

impl RefUnwindSafe for Mesh

§

impl Send for Mesh

§

impl Sync for Mesh

§

impl Unpin for Mesh

§

impl UnsafeUnpin for Mesh

§

impl UnwindSafe for Mesh

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.