Smith.Mesh (Smith v0.1.0)

Copy Markdown View Source

Low-level indexed triangle utilities used by the exporter.

A mesh has :vertices (world {x, y, z} tuples) and :triangles (zero-based {a, b, c} indices into that vertex list). Native meshes from OCEx.mesh/3 need welding to share indices across face boundaries.

These functions return maps or binaries directly, not tagged results. They assume trusted, well-formed mesh data and may raise on malformed input. For normal print output, use Smith.export/3, which handles meshing, checks, serialization, and files together.

Summary

Functions

Parses a binary STL and welds the resulting vertices.

Reports edge connectivity, winding, counts, and signed mesh volume.

Serializes a mesh as a geometry-only 3MF ZIP archive.

Serializes a mesh as binary STL, returning bytes without writing a file.

Merges vertices assigned to the same grid cell and remaps triangles.

Functions

from_stl(arg)

@spec from_stl(binary()) :: map()

Parses a binary STL and welds the resulting vertices.

Requires an 80-byte header, a 32-bit little-endian triangle count, and exactly 50 bytes per triangle. Facet normals and attribute words are ignored. Vertices are welded with the default tolerance of weld/2; the result is a mesh map, not a tagged result.

This utility is for trusted binary data. ASCII STL, truncated records, trailing bytes, and unsupported float encodings are not handled as tagged errors and may raise Elixir exceptions.

iex> {:ok, box} = OCEx.box(2, 3, 4)
iex> {:ok, raw} = OCEx.mesh(box)
iex> mesh = raw |> Smith.Mesh.to_stl() |> Smith.Mesh.from_stl()
iex> {length(mesh.vertices), length(mesh.triangles)}
{8, 12}

inspect(map)

@spec inspect(map()) :: map()

Reports edge connectivity, winding, counts, and signed mesh volume.

Returns a map directly:

  • :watertight — at least one edge exists and every edge belongs to exactly two triangles.
  • :winding_consistent — each shared edge is traversed in opposite directions by its two triangles. For an empty mesh this is true.
  • :components — number of triangle groups connected by shared edges.
  • :volume — signed volume in cubic model units.
  • :vertices, :triangles — input list lengths.

It does not weld vertices first. Call weld/2 on native face meshes before inspecting connectivity. Consistent winding does not necessarily mean outward winding; an entirely reversed shell has negative volume. The checks do not detect arbitrary triangle self-intersections or prove manifold vertex neighborhoods.

iex> {:ok, box} = OCEx.box(2, 3, 4)
iex> {:ok, raw} = OCEx.mesh(box)
iex> report = raw |> Smith.Mesh.weld() |> Smith.Mesh.inspect()
iex> {report.watertight, report.winding_consistent, report.components,
...>  report.volume}
{true, true, 1, 24.0}

to_3mf(map)

@spec to_3mf(map()) :: binary()

Serializes a mesh as a geometry-only 3MF ZIP archive.

Returns archive bytes without writing a file. The archive contains one mesh object and one build item, with millimeter units. Disconnected components remain within that one object. There are no materials, printer profiles, support settings, or slicer configuration.

This function does not validate the mesh. Use Smith.export/3 to run print mesh checks before producing files.

to_stl(map)

@spec to_stl(map()) :: binary()

Serializes a mesh as binary STL, returning bytes without writing a file.

Writes 32-bit float coordinates and calculated facet normals. STL does not store units. Vertex precision can change during serialization, so Smith.Export.mesh/3 checks the parsed STL rather than just this input. No topology or volume validation is performed here.

weld(map, tolerance \\ 1.0e-6)

@spec weld(map(), number()) :: map()

Merges vertices assigned to the same grid cell and remaps triangles.

tolerance is the grid spacing in model units, default 1.0e-6. Each coordinate is divided by that spacing and rounded to form a key. The first vertex in each cell is retained at its original coordinates; vertices are not snapped to the grid or averaged.

Triangles with repeated indices after welding are removed. Duplicate triangles are removed regardless of winding. Collinear triangles with three distinct indices are not removed. Only :vertices and :triangles are retained in the returned map.

This function assumes valid indices and a positive tolerance. It returns a mesh directly and may raise on malformed data.