Smith.Export (Smith v0.1.0)

Copy Markdown View Source

Part bundles containing geometry files, a preview mesh, and check results.

Use Smith.export/3 or write/3 with an evaluated part. Each call writes a new directory identified by the geometry revision and a random export ID. current.json points to the latest records by name; previous export directories remain available.

Print placement affects STL and 3MF. STEP and BREP retain the evaluated geometry's placement. Print meshes are checked after STL serialization, and requested STEP files are reimported and measured. These checks catch common export failures; they do not establish dimensional fit, strength, printer settings, or freedom from every mesh self-intersection.

See write/3 for all options and returned fields, mesh/3 for the precise checks, and the exporting guide for examples. Assembly exports go through Smith.export/3; this module's writers accept individual Smith.Result values.

Summary

Functions

Builds a printable mesh and checks its binary STL representation.

Updates current.json with existing export records.

Writes a checked export bundle for one evaluated Smith.Result.

Writes several part bundles and publishes their records together.

Functions

mesh(shape, tolerance \\ 0.03, angular_tolerance \\ 0.5)

@spec mesh(OCEx.Shape.t(), number(), number()) :: {:ok, map()} | {:error, term()}

Builds a printable mesh and checks its binary STL representation.

Accepts an OCEx.Shape, linear deflection in mm (default 0.03), and angular deflection in radians (default 0.5). The shape must contain solids and have positive total volume. Native mesh vertices are welded with Smith.Mesh.weld/2, then serialized as binary STL and parsed back.

The parsed mesh must have:

  • Exactly two triangles sharing every edge, with opposite edge directions.
  • As many edge-connected triangle components as native solids.
  • Signed volume within 0.5% of native volume (strictly less than 0.005 relative error).

Returns {:ok, %{mesh: mesh, stl: binary, checks: report}}. The mesh is the welded pre-STL mesh; checks describe the parsed STL. The report has the fields from Smith.Mesh.inspect/1, plus :relative_volume_error, :linear_deflection, and :angular_deflection.

Failures include :no_solids, :non_positive_volume, :invalid_print_mesh, and :mesh_volume_mismatch. A coarse curved mesh can fail the volume check; decrease deflections and retry. Component matching also rejects otherwise valid designs with multiple disconnected boundary shells per solid, such as a fully enclosed cavity. It is not a general self-intersection or manufacturability test.

iex> {:ok, box} = OCEx.box(2, 3, 4)
iex> {:ok, print} = Smith.Export.mesh(box)
iex> {print.checks.watertight, print.checks.components, byte_size(print.stl)}
{true, 1, 684}

publish(record, root)

@spec publish(map() | [map()], String.t()) :: {:ok, :ok} | {:error, term()}

Updates current.json with existing export records.

Accepts one record map or a nonempty list of records with distinct string :name values and string :revision values. Returns {:ok, :ok}. Records with matching names are replaced; unrelated models and assemblies remain. Standalone records cannot overwrite assembly-owned part names.

This function only updates the manifest. It does not write or verify geometry files, hashes, or paths. Use write/3 or write_many/2 for the complete checked export flow.

Malformed records return :invalid_argument, malformed existing manifests return :invalid_manifest, and ownership conflicts return :assembly_part_conflict. File-system errors are returned unchanged. The manifest is replaced through a temporary file; writers to one root must run sequentially.

write(result, root, opts)

@spec write(Smith.Result.t(), String.t(), keyword()) ::
  {:ok, map()} | {:error, term()}

Writes a checked export bundle for one evaluated Smith.Result.

root is an output directory, created as needed. Returns {:ok, record} after writing files and updating current.json. Smith.export/3 delegates here for individual results.

Options

OptionDefaultMeaning
:nameRequiredString starting with an ASCII letter/digit; remaining characters may also include _ or -
:formats[:step, :stl, :three_mf]Nonempty unique subset of these formats
:tolerance0.03Print mesh linear deflection in mm
:angular_tolerance0.5Print mesh angular deflection in radians
:step_tolerance1.0e-6Relative STEP volume error threshold; greater than zero and at most 1.0e-5
:print_rotationnil{axis, degrees} about world zero
:print_offset{0, 0, 0}World translation after print rotation
:on_bedfalseCenters rotated bounds in XY and puts minimum Z at zero
:display_orientation:print:print or :installed orientation for the preview mesh
:display_offset{0, 0, 0}World translation of the preview mesh only
:metadata%{}JSON-encodable map added to the verification report

:on_bed cannot be combined with :print_offset. Linear and angular deflections must exceed 1.0e-7. Metadata tuples become JSON arrays; generated verification fields take precedence over colliding metadata keys.

Files and returned record

Files are placed under root/name/revision/export_id/. Requested formats produce model.step, model.stl, and model.3mf. model.brep, model.json, and verification.json are always written. STEP and BREP retain evaluated placement; STL and 3MF use print placement. 3MF contains millimeter geometry without printer or slicer settings.

The record contains :name, :revision, :export_id, :step, :stl, :three_mf, native :volume, display :mesh, and :verification. Unrequested format paths are nil. Paths retain the form of root: use an absolute root if consuming them elsewhere. The display mesh uses fixed 0.03 mm / 0.5 rad settings, independently of print mesh settings.

Checks and failures

The result's BREP must match its revision. All bundles run mesh/3 checks, even STEP-only bundles. Each requested STEP is read back and checked for native validity, solid count, and relative volume error strictly below :step_tolerance. This is not a boundary-distance or dimensional comparison. 3MF is serialized from the checked mesh; it is not read back independently by this exporter.

Failures return {:error, reason}, including :revision_mismatch, :invalid_options, :invalid_metadata, mesh/STEP check errors, and file-system errors. Failed exports may leave new files, but preserve the previous manifest and earlier export directories. Run writers to one root sequentially.

write_many(entries, root)

@spec write_many([{Smith.Result.t(), keyword()}], String.t()) ::
  {:ok, [map()]} | {:error, term()}

Writes several part bundles and publishes their records together.

entries is a nonempty list of {result, options} pairs. Each result is a Smith.Result; options follow write/3. Names must be distinct. Returns {:ok, records} in input order.

Invalid batch options return :invalid_options. A part write failure returns {:error, {:export_failed, name, reason}}. Nothing is published until every bundle passes, although completed unpublished files may remain. This groups exports without creating a named assembly or ZIP.